mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-14 22:09:32 +02:00
* Patch from Mattias Gaertner
- more tests - case-of: added option to change between switch and if-else - Some changes to the way the implementation block is generated for units. git-svn-id: trunk@35055 -
This commit is contained in:
parent
f3e33a9dde
commit
d6d10a522a
@ -883,7 +883,7 @@ Type
|
|||||||
Destructor Destroy; override;
|
Destructor Destroy; override;
|
||||||
Property Cond : TJSelement Read FCond Write FCond;
|
Property Cond : TJSelement Read FCond Write FCond;
|
||||||
Property Cases : TJSCaseElements Read FCases;
|
Property Cases : TJSCaseElements Read FCases;
|
||||||
Property TheDefault : TJSCaseelement Read FDefault Write FDefault; // one of Cases
|
Property TheDefault : TJSCaseElement Read FDefault Write FDefault; // one of Cases
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TJSLabeledStatement - e.g. 'TheLabel : A' }
|
{ TJSLabeledStatement - e.g. 'TheLabel : A' }
|
||||||
|
@ -136,7 +136,7 @@ Type
|
|||||||
Procedure WriteIfStatement(El: TJSIfStatement);virtual;
|
Procedure WriteIfStatement(El: TJSIfStatement);virtual;
|
||||||
Procedure WriteSourceElements(El: TJSSourceElements);virtual;
|
Procedure WriteSourceElements(El: TJSSourceElements);virtual;
|
||||||
Procedure WriteStatementList(El: TJSStatementList);virtual;
|
Procedure WriteStatementList(El: TJSStatementList);virtual;
|
||||||
Procedure WriteTryStatement(el: TJSTryStatement);virtual;
|
Procedure WriteTryStatement(El: TJSTryStatement);virtual;
|
||||||
Procedure WriteVarDeclaration(El: TJSVarDeclaration);virtual;
|
Procedure WriteVarDeclaration(El: TJSVarDeclaration);virtual;
|
||||||
Procedure WriteWithStatement(El: TJSWithStatement);virtual;
|
Procedure WriteWithStatement(El: TJSWithStatement);virtual;
|
||||||
Procedure WriteVarDeclarationList(El: TJSVariableDeclarationList);virtual;
|
Procedure WriteVarDeclarationList(El: TJSVariableDeclarationList);virtual;
|
||||||
@ -426,7 +426,7 @@ Var
|
|||||||
S : String;
|
S : String;
|
||||||
begin
|
begin
|
||||||
if V.CustomValue<>'' then
|
if V.CustomValue<>'' then
|
||||||
S:=V.CustomValue
|
S:=JSStringToStr(V.CustomValue)
|
||||||
else
|
else
|
||||||
Case V.ValueType of
|
Case V.ValueType of
|
||||||
jstUNDEFINED : S:='undefined';
|
jstUNDEFINED : S:='undefined';
|
||||||
@ -821,7 +821,7 @@ begin
|
|||||||
WriteJS(EL.LHS);
|
WriteJS(EL.LHS);
|
||||||
S:=El.OperatorString;
|
S:=El.OperatorString;
|
||||||
If Not (woCompact in Options) then
|
If Not (woCompact in Options) then
|
||||||
S:=' '+S+' ';
|
S:=' '+S+' ';
|
||||||
Write(s);
|
Write(s);
|
||||||
WriteJS(EL.Expr);
|
WriteJS(EL.Expr);
|
||||||
end;
|
end;
|
||||||
@ -841,11 +841,16 @@ procedure TJSWriter.WriteIfStatement(El: TJSIfStatement);
|
|||||||
|
|
||||||
begin
|
begin
|
||||||
Write('if (');
|
Write('if (');
|
||||||
WriteJS(EL.Cond);
|
WriteJS(El.Cond);
|
||||||
Write(') ');
|
Write(')');
|
||||||
WriteJS(El.BTrue);
|
If Not (woCompact in Options) then
|
||||||
|
Write(' ');
|
||||||
|
if (El.BTrue<>nil) and (not (El.BTrue is TJSEmptyStatement)) then
|
||||||
|
WriteJS(El.BTrue);
|
||||||
if Assigned(El.BFalse) then
|
if Assigned(El.BFalse) then
|
||||||
begin
|
begin
|
||||||
|
if (El.BTrue=nil) or (El.BTrue is TJSEmptyStatement) then
|
||||||
|
Write('{}');
|
||||||
Write(' else ');
|
Write(' else ');
|
||||||
WriteJS(El.BFalse)
|
WriteJS(El.BFalse)
|
||||||
end;
|
end;
|
||||||
@ -929,15 +934,15 @@ begin
|
|||||||
C:=(woCompact in Options);
|
C:=(woCompact in Options);
|
||||||
Write('switch (');
|
Write('switch (');
|
||||||
If Assigned(El.Cond) then
|
If Assigned(El.Cond) then
|
||||||
WriteJS(EL.Cond);
|
WriteJS(El.Cond);
|
||||||
if C then
|
if C then
|
||||||
Write(') {')
|
Write(') {')
|
||||||
else
|
else
|
||||||
Writeln(') {');
|
Writeln(') {');
|
||||||
For I:=0 to EL.Cases.Count-1 do
|
For I:=0 to El.Cases.Count-1 do
|
||||||
begin
|
begin
|
||||||
EC:=EL.Cases[i];
|
EC:=El.Cases[i];
|
||||||
if EC=EL.TheDefault then
|
if EC=El.TheDefault then
|
||||||
Write('default')
|
Write('default')
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
@ -950,14 +955,22 @@ begin
|
|||||||
Writeln(':');
|
Writeln(':');
|
||||||
if Assigned(EC.Body) then
|
if Assigned(EC.Body) then
|
||||||
begin
|
begin
|
||||||
|
FSkipBrackets:=true;
|
||||||
|
Indent;
|
||||||
WriteJS(EC.Body);
|
WriteJS(EC.Body);
|
||||||
|
Undent;
|
||||||
|
if Not ((EC.Body is TJSStatementList) or (EC.Body is TJSEmptyBlockStatement)) then
|
||||||
|
if C then
|
||||||
|
Write('; ')
|
||||||
|
else
|
||||||
|
Writeln(';');
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
if C then
|
if C then
|
||||||
begin
|
Write('; ')
|
||||||
if Not ((EC.Body is TJSStatementList) or (EC.Body is TJSEmptyBlockStatement)) then
|
|
||||||
write('; ')
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
Writeln('');
|
Writeln(';');
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
Write('}');
|
Write('}');
|
||||||
@ -1017,7 +1030,7 @@ begin
|
|||||||
WriteJS(EL.A);
|
WriteJS(EL.A);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TJSWriter.WriteTryStatement(el: TJSTryStatement);
|
procedure TJSWriter.WriteTryStatement(El: TJSTryStatement);
|
||||||
|
|
||||||
Var
|
Var
|
||||||
C : Boolean;
|
C : Boolean;
|
||||||
@ -1034,7 +1047,6 @@ begin
|
|||||||
Write('} ')
|
Write('} ')
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
Writeln('');
|
|
||||||
Writeln('}');
|
Writeln('}');
|
||||||
end;
|
end;
|
||||||
If (El is TJSTryCatchFinallyStatement) or (El is TJSTryCatchStatement) then
|
If (El is TJSTryCatchFinallyStatement) or (El is TJSTryCatchStatement) then
|
||||||
@ -1045,7 +1057,7 @@ begin
|
|||||||
else
|
else
|
||||||
Writeln(') {');
|
Writeln(') {');
|
||||||
Indent;
|
Indent;
|
||||||
WriteJS(EL.BCatch);
|
WriteJS(El.BCatch);
|
||||||
Undent;
|
Undent;
|
||||||
If C then
|
If C then
|
||||||
if (El is TJSTryCatchFinallyStatement) then
|
if (El is TJSTryCatchFinallyStatement) then
|
||||||
@ -1065,15 +1077,10 @@ begin
|
|||||||
else
|
else
|
||||||
Writeln('finally {');
|
Writeln('finally {');
|
||||||
Indent;
|
Indent;
|
||||||
WriteJS(EL.BFinally);
|
FSkipBrackets:=True;
|
||||||
|
WriteJS(El.BFinally);
|
||||||
Undent;
|
Undent;
|
||||||
If C then
|
Write('}');
|
||||||
Write('}')
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
Writeln('');
|
|
||||||
Writeln('}');
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -14,7 +14,8 @@
|
|||||||
**********************************************************************
|
**********************************************************************
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
./testpas2js --suite=TTestModuleConverter.TestEmptyProgram
|
./testpas2js --suite=TTestModule.TestEmptyProgram
|
||||||
|
./testpas2js --suite=TTestModule.TestEmptyUnit
|
||||||
}
|
}
|
||||||
unit tcmodules;
|
unit tcmodules;
|
||||||
|
|
||||||
@ -92,8 +93,9 @@ type
|
|||||||
procedure TearDown; override;
|
procedure TearDown; override;
|
||||||
Procedure Add(Line: string);
|
Procedure Add(Line: string);
|
||||||
Procedure StartParsing;
|
Procedure StartParsing;
|
||||||
Procedure ParseModule;
|
procedure ParseModule;
|
||||||
procedure ParseProgram;
|
procedure ParseProgram;
|
||||||
|
procedure ParseUnit;
|
||||||
protected
|
protected
|
||||||
function FindModuleWithFilename(aFilename: string): TTestEnginePasResolver;
|
function FindModuleWithFilename(aFilename: string): TTestEnginePasResolver;
|
||||||
function AddModule(aFilename: string): TTestEnginePasResolver;
|
function AddModule(aFilename: string): TTestEnginePasResolver;
|
||||||
@ -102,7 +104,10 @@ type
|
|||||||
ImplementationSrc: string): TTestEnginePasResolver;
|
ImplementationSrc: string): TTestEnginePasResolver;
|
||||||
procedure AddSystemUnit;
|
procedure AddSystemUnit;
|
||||||
procedure StartProgram(NeedSystemUnit: boolean);
|
procedure StartProgram(NeedSystemUnit: boolean);
|
||||||
|
procedure StartUnit(NeedSystemUnit: boolean);
|
||||||
|
Procedure ConvertModule;
|
||||||
Procedure ConvertProgram;
|
Procedure ConvertProgram;
|
||||||
|
Procedure ConvertUnit;
|
||||||
procedure CheckDottedIdentifier(Msg: string; El: TJSElement; DottedName: string);
|
procedure CheckDottedIdentifier(Msg: string; El: TJSElement; DottedName: string);
|
||||||
function GetDottedIdentifier(El: TJSElement): string;
|
function GetDottedIdentifier(El: TJSElement): string;
|
||||||
procedure CheckSource(Msg,Statements, InitStatements: string);
|
procedure CheckSource(Msg,Statements, InitStatements: string);
|
||||||
@ -128,10 +133,31 @@ type
|
|||||||
property Scanner: TPascalScanner read FScanner;
|
property Scanner: TPascalScanner read FScanner;
|
||||||
property Parser: TTestPasParser read FParser;
|
property Parser: TTestPasParser read FParser;
|
||||||
Published
|
Published
|
||||||
|
// modules
|
||||||
Procedure TestEmptyProgram;
|
Procedure TestEmptyProgram;
|
||||||
|
Procedure TestEmptyUnit;
|
||||||
|
|
||||||
|
// vars/const
|
||||||
Procedure TestVarInt;
|
Procedure TestVarInt;
|
||||||
|
Procedure TestVarBaseTypes;
|
||||||
|
Procedure TestConstBaseTypes;
|
||||||
|
Procedure TestUnitImplVars;
|
||||||
|
Procedure TestUnitImplConsts;
|
||||||
|
Procedure TestUnitImplRecord;
|
||||||
|
|
||||||
Procedure TestEmptyProc;
|
Procedure TestEmptyProc;
|
||||||
|
Procedure TestAliasTypeRef;
|
||||||
|
|
||||||
|
// functions
|
||||||
|
Procedure TestPrgProcVar;
|
||||||
Procedure TestProcTwoArgs;
|
Procedure TestProcTwoArgs;
|
||||||
|
Procedure TestUnitProcVar;
|
||||||
|
|
||||||
|
// ToDo: enums
|
||||||
|
|
||||||
|
// statements
|
||||||
|
Procedure TestIncDec;
|
||||||
|
Procedure TestAssignments;
|
||||||
Procedure TestFunctionInt;
|
Procedure TestFunctionInt;
|
||||||
Procedure TestFunctionString;
|
Procedure TestFunctionString;
|
||||||
Procedure TestVarRecord;
|
Procedure TestVarRecord;
|
||||||
@ -140,6 +166,11 @@ type
|
|||||||
Procedure TestRepeatUntil;
|
Procedure TestRepeatUntil;
|
||||||
Procedure TestAsmBlock;
|
Procedure TestAsmBlock;
|
||||||
Procedure TestTryFinally;
|
Procedure TestTryFinally;
|
||||||
|
Procedure TestCaseOf;
|
||||||
|
Procedure TestCaseOf_UseSwitch;
|
||||||
|
Procedure TestCaseOfNoElse;
|
||||||
|
Procedure TestCaseOfNoElse_UseSwitch;
|
||||||
|
Procedure TestCaseOfRange;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function LinesToStr(Args: array of const): string;
|
function LinesToStr(Args: array of const): string;
|
||||||
@ -365,22 +396,15 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TTestModule.ParseModule;
|
procedure TTestModule.ParseModule;
|
||||||
begin
|
|
||||||
StartParsing;
|
|
||||||
Parser.ParseMain(FModule);
|
|
||||||
AssertNotNull('Module resulted in Module',FModule);
|
|
||||||
AssertEquals('modulename',ChangeFileExt(FFileName,''),Module.Name);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TTestModule.ParseProgram;
|
|
||||||
begin
|
begin
|
||||||
FFirstPasStatement:=nil;
|
FFirstPasStatement:=nil;
|
||||||
try
|
try
|
||||||
ParseModule;
|
StartParsing;
|
||||||
|
Parser.ParseMain(FModule);
|
||||||
except
|
except
|
||||||
on E: EParserError do
|
on E: EParserError do
|
||||||
begin
|
begin
|
||||||
writeln('ERROR: TTestModule.ParseProgram Parser: '+E.ClassName+':'+E.Message
|
writeln('ERROR: TTestModule.ParseModule Parser: '+E.ClassName+':'+E.Message
|
||||||
+' File='+Scanner.CurFilename
|
+' File='+Scanner.CurFilename
|
||||||
+' LineNo='+IntToStr(Scanner.CurRow)
|
+' LineNo='+IntToStr(Scanner.CurRow)
|
||||||
+' Col='+IntToStr(Scanner.CurColumn)
|
+' Col='+IntToStr(Scanner.CurColumn)
|
||||||
@ -390,7 +414,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
on E: EPasResolve do
|
on E: EPasResolve do
|
||||||
begin
|
begin
|
||||||
writeln('ERROR: TTestModule.ParseProgram PasResolver: '+E.ClassName+':'+E.Message
|
writeln('ERROR: TTestModule.ParseModule PasResolver: '+E.ClassName+':'+E.Message
|
||||||
+' File='+Scanner.CurFilename
|
+' File='+Scanner.CurFilename
|
||||||
+' LineNo='+IntToStr(Scanner.CurRow)
|
+' LineNo='+IntToStr(Scanner.CurRow)
|
||||||
+' Col='+IntToStr(Scanner.CurColumn)
|
+' Col='+IntToStr(Scanner.CurColumn)
|
||||||
@ -400,11 +424,18 @@ begin
|
|||||||
end;
|
end;
|
||||||
on E: Exception do
|
on E: Exception do
|
||||||
begin
|
begin
|
||||||
writeln('ERROR: TTestModule.ParseProgram Exception: '+E.ClassName+':'+E.Message);
|
writeln('ERROR: TTestModule.ParseModule Exception: '+E.ClassName+':'+E.Message);
|
||||||
raise E;
|
raise E;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
AssertNotNull('Module resulted in Module',FModule);
|
||||||
|
AssertEquals('modulename',lowercase(ChangeFileExt(FFileName,'')),lowercase(Module.Name));
|
||||||
TAssert.AssertSame('Has resolver',Engine,Parser.Engine);
|
TAssert.AssertSame('Has resolver',Engine,Parser.Engine);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.ParseProgram;
|
||||||
|
begin
|
||||||
|
ParseModule;
|
||||||
AssertEquals('Has program',TPasProgram,Module.ClassType);
|
AssertEquals('Has program',TPasProgram,Module.ClassType);
|
||||||
FPasProgram:=TPasProgram(Module);
|
FPasProgram:=TPasProgram(Module);
|
||||||
AssertNotNull('Has program section',PasProgram.ProgramSection);
|
AssertNotNull('Has program section',PasProgram.ProgramSection);
|
||||||
@ -414,6 +445,18 @@ begin
|
|||||||
FFirstPasStatement:=TPasImplBlock(PasProgram.InitializationSection.Elements[0]);
|
FFirstPasStatement:=TPasImplBlock(PasProgram.InitializationSection.Elements[0]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.ParseUnit;
|
||||||
|
begin
|
||||||
|
ParseModule;
|
||||||
|
AssertEquals('Has unit (TPasModule)',TPasModule,Module.ClassType);
|
||||||
|
AssertNotNull('Has interface section',Module.InterfaceSection);
|
||||||
|
AssertNotNull('Has implementation section',Module.ImplementationSection);
|
||||||
|
if (Module.InitializationSection<>nil)
|
||||||
|
and (Module.InitializationSection.Elements.Count>0)
|
||||||
|
and (TObject(Module.InitializationSection.Elements[0]) is TPasImplBlock) then
|
||||||
|
FFirstPasStatement:=TPasImplBlock(Module.InitializationSection.Elements[0]);
|
||||||
|
end;
|
||||||
|
|
||||||
function TTestModule.FindModuleWithFilename(aFilename: string
|
function TTestModule.FindModuleWithFilename(aFilename: string
|
||||||
): TTestEnginePasResolver;
|
): TTestEnginePasResolver;
|
||||||
var
|
var
|
||||||
@ -488,20 +531,29 @@ begin
|
|||||||
Add('');
|
Add('');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TTestModule.ConvertProgram;
|
procedure TTestModule.StartUnit(NeedSystemUnit: boolean);
|
||||||
|
begin
|
||||||
|
if NeedSystemUnit then
|
||||||
|
AddSystemUnit
|
||||||
|
else
|
||||||
|
Parser.ImplicitUses.Clear;
|
||||||
|
Add('unit Test1;');
|
||||||
|
Add('');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.ConvertModule;
|
||||||
var
|
var
|
||||||
ModuleNameExpr: TJSLiteral;
|
ModuleNameExpr: TJSLiteral;
|
||||||
FunDecl, InitFunction: TJSFunctionDeclarationStatement;
|
FunDecl, InitFunction: TJSFunctionDeclarationStatement;
|
||||||
FunDef: TJSFuncDef;
|
FunDef: TJSFuncDef;
|
||||||
InitAssign: TJSSimpleAssignStatement;
|
InitAssign: TJSSimpleAssignStatement;
|
||||||
FunBody: TJSFunctionBody;
|
FunBody: TJSFunctionBody;
|
||||||
|
InitName: String;
|
||||||
begin
|
begin
|
||||||
FJSSource:=TStringList.Create;
|
|
||||||
Add('end.');
|
|
||||||
ParseProgram;
|
|
||||||
FJSModule:=FConverter.ConvertPasElement(Module,nil) as TJSSourceElements;
|
FJSModule:=FConverter.ConvertPasElement(Module,nil) as TJSSourceElements;
|
||||||
|
FJSSource:=TStringList.Create;
|
||||||
FJSSource.Text:=JSToStr(JSModule);
|
FJSSource.Text:=JSToStr(JSModule);
|
||||||
writeln('TTestModule.ConvertProgram JS:');
|
writeln('TTestModule.ConvertModule JS:');
|
||||||
write(FJSSource.Text);
|
write(FJSSource.Text);
|
||||||
|
|
||||||
// rtl.module(...
|
// rtl.module(...
|
||||||
@ -519,7 +571,10 @@ begin
|
|||||||
AssertNotNull('module name param',JSModuleCallArgs.Elements.Elements[0].Expr);
|
AssertNotNull('module name param',JSModuleCallArgs.Elements.Elements[0].Expr);
|
||||||
ModuleNameExpr:=JSModuleCallArgs.Elements.Elements[0].Expr as TJSLiteral;
|
ModuleNameExpr:=JSModuleCallArgs.Elements.Elements[0].Expr as TJSLiteral;
|
||||||
AssertEquals('module name param is string',ord(jstString),ord(ModuleNameExpr.Value.ValueType));
|
AssertEquals('module name param is string',ord(jstString),ord(ModuleNameExpr.Value.ValueType));
|
||||||
AssertEquals('module name','program',String(ModuleNameExpr.Value.AsString));
|
if Module is TPasProgram then
|
||||||
|
AssertEquals('module name','program',String(ModuleNameExpr.Value.AsString))
|
||||||
|
else
|
||||||
|
AssertEquals('module name',lowercase(Module.Name),String(ModuleNameExpr.Value.AsString));
|
||||||
|
|
||||||
// main uses section
|
// main uses section
|
||||||
AssertNotNull('interface uses section',JSModuleCallArgs.Elements.Elements[1].Expr);
|
AssertNotNull('interface uses section',JSModuleCallArgs.Elements.Elements[1].Expr);
|
||||||
@ -538,12 +593,39 @@ begin
|
|||||||
FJSModuleSrc:=FunBody.A as TJSSourceElements;
|
FJSModuleSrc:=FunBody.A as TJSSourceElements;
|
||||||
|
|
||||||
// init this.$main - the last statement
|
// init this.$main - the last statement
|
||||||
AssertEquals('this.$main function 1',true,JSModuleSrc.Statements.Count>0);
|
if Module is TPasProgram then
|
||||||
InitAssign:=JSModuleSrc.Statements.Nodes[JSModuleSrc.Statements.Count-1].Node as TJSSimpleAssignStatement;
|
begin
|
||||||
CheckDottedIdentifier('init function',InitAssign.LHS,'this.$main');
|
InitName:='$main';
|
||||||
|
AssertEquals('this.'+InitName+' function 1',true,JSModuleSrc.Statements.Count>0);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
InitName:='$init';
|
||||||
|
FJSInitBody:=nil;
|
||||||
|
if JSModuleSrc.Statements.Count>0 then
|
||||||
|
begin
|
||||||
|
InitAssign:=JSModuleSrc.Statements.Nodes[JSModuleSrc.Statements.Count-1].Node as TJSSimpleAssignStatement;
|
||||||
|
if GetDottedIdentifier(InitAssign.LHS)='this.'+InitName then
|
||||||
|
begin
|
||||||
|
InitFunction:=InitAssign.Expr as TJSFunctionDeclarationStatement;
|
||||||
|
FJSInitBody:=InitFunction.AFunction.Body as TJSFunctionBody;
|
||||||
|
end
|
||||||
|
else if Module is TPasProgram then
|
||||||
|
CheckDottedIdentifier('init function',InitAssign.LHS,'this.'+InitName);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
InitFunction:=InitAssign.Expr as TJSFunctionDeclarationStatement;
|
procedure TTestModule.ConvertProgram;
|
||||||
FJSInitBody:=InitFunction.AFunction.Body as TJSFunctionBody;
|
begin
|
||||||
|
Add('end.');
|
||||||
|
ParseProgram;
|
||||||
|
ConvertModule;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.ConvertUnit;
|
||||||
|
begin
|
||||||
|
Add('end.');
|
||||||
|
ParseUnit;
|
||||||
|
ConvertModule;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TTestModule.CheckDottedIdentifier(Msg: string; El: TJSElement;
|
procedure TTestModule.CheckDottedIdentifier(Msg: string; El: TJSElement;
|
||||||
@ -556,7 +638,7 @@ begin
|
|||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
AssertNotNull(Msg,El);
|
AssertNotNull(Msg,El);
|
||||||
AssertEquals(Msg,DottedName,GetDottedIdentifier(EL));
|
AssertEquals(Msg,DottedName,GetDottedIdentifier(El));
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -574,13 +656,20 @@ end;
|
|||||||
|
|
||||||
procedure TTestModule.CheckSource(Msg, Statements, InitStatements: string);
|
procedure TTestModule.CheckSource(Msg, Statements, InitStatements: string);
|
||||||
var
|
var
|
||||||
ActualSrc, ExpectedSrc: String;
|
ActualSrc, ExpectedSrc, InitName: String;
|
||||||
begin
|
begin
|
||||||
ActualSrc:=JSToStr(JSModuleSrc);
|
ActualSrc:=JSToStr(JSModuleSrc);
|
||||||
ExpectedSrc:=Statements+LineEnding
|
ExpectedSrc:=Statements;
|
||||||
+'this.$main = function () {'+LineEnding
|
if Module is TPasProgram then
|
||||||
+InitStatements
|
InitName:='$main'
|
||||||
+'};'+LineEnding;
|
else
|
||||||
|
InitName:='$init';
|
||||||
|
if (Module is TPasProgram) or (InitStatements<>'') then
|
||||||
|
ExpectedSrc:=ExpectedSrc+LineEnding
|
||||||
|
+'this.'+InitName+' = function () {'+LineEnding
|
||||||
|
+InitStatements
|
||||||
|
+'};'+LineEnding;
|
||||||
|
//writeln('TTestModule.CheckSource InitStatements="',InitStatements,'"');
|
||||||
CheckDiff(Msg,ExpectedSrc,ActualSrc);
|
CheckDiff(Msg,ExpectedSrc,ActualSrc);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -696,6 +785,14 @@ begin
|
|||||||
CheckSource('Empty program','','');
|
CheckSource('Empty program','','');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.TestEmptyUnit;
|
||||||
|
begin
|
||||||
|
StartUnit(false);
|
||||||
|
Add('interface');
|
||||||
|
Add('implementation');
|
||||||
|
ConvertUnit;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestModule.TestVarInt;
|
procedure TTestModule.TestVarInt;
|
||||||
begin
|
begin
|
||||||
StartProgram(false);
|
StartProgram(false);
|
||||||
@ -705,6 +802,70 @@ begin
|
|||||||
CheckSource('TestVarInt','this.i=0;','');
|
CheckSource('TestVarInt','this.i=0;','');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.TestVarBaseTypes;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add('var');
|
||||||
|
Add(' i: longint;');
|
||||||
|
Add(' s: string;');
|
||||||
|
Add(' c: char;');
|
||||||
|
Add(' b: boolean;');
|
||||||
|
Add(' d: double;');
|
||||||
|
Add(' i2: longint = 3;');
|
||||||
|
Add(' s2: string = ''foo'';');
|
||||||
|
Add(' c2: char = ''4'';');
|
||||||
|
Add(' b2: boolean = true;');
|
||||||
|
Add(' d2: double = 5.6;');
|
||||||
|
Add(' i3: longint = $707;');
|
||||||
|
Add(' i4: int64 = 4503599627370495;');
|
||||||
|
Add(' i5: int64 = -4503599627370496;');
|
||||||
|
Add(' i6: int64 = $fffffffffffff;');
|
||||||
|
Add(' i7: int64 = -$10000000000000;');
|
||||||
|
Add('begin');
|
||||||
|
ConvertProgram;
|
||||||
|
CheckSource('TestVarBaseTypes',
|
||||||
|
LinesToStr([
|
||||||
|
'this.i=0;',
|
||||||
|
'this.s="";',
|
||||||
|
'this.c="";',
|
||||||
|
'this.b=false;',
|
||||||
|
'this.d=0;',
|
||||||
|
'this.i2=3;',
|
||||||
|
'this.s2="foo";',
|
||||||
|
'this.c2="4";',
|
||||||
|
'this.b2=true;',
|
||||||
|
'this.d2=5.6;',
|
||||||
|
'this.i3=0x707;',
|
||||||
|
'this.i4= 4503599627370495;',
|
||||||
|
'this.i5= -4503599627370496;',
|
||||||
|
'this.i6= 0xfffffffffffff;',
|
||||||
|
'this.i7=-0x10000000000000;'
|
||||||
|
]),
|
||||||
|
'');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.TestConstBaseTypes;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add('const');
|
||||||
|
Add(' i: longint = 3;');
|
||||||
|
Add(' s: string = ''foo'';');
|
||||||
|
Add(' c: char = ''4'';');
|
||||||
|
Add(' b: boolean = true;');
|
||||||
|
Add(' d: double = 5.6;');
|
||||||
|
Add('begin');
|
||||||
|
ConvertProgram;
|
||||||
|
CheckSource('TestVarBaseTypes',
|
||||||
|
LinesToStr([
|
||||||
|
'this.i=3;',
|
||||||
|
'this.s="foo";',
|
||||||
|
'this.c="4";',
|
||||||
|
'this.b=true;',
|
||||||
|
'this.d=5.6;'
|
||||||
|
]),
|
||||||
|
'');
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestModule.TestEmptyProc;
|
procedure TTestModule.TestEmptyProc;
|
||||||
begin
|
begin
|
||||||
StartProgram(false);
|
StartProgram(false);
|
||||||
@ -723,6 +884,199 @@ begin
|
|||||||
]));
|
]));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.TestAliasTypeRef;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add('type');
|
||||||
|
Add(' a=longint;');
|
||||||
|
Add(' b=a;');
|
||||||
|
Add('var');
|
||||||
|
Add(' c: a;');
|
||||||
|
Add(' d: b;');
|
||||||
|
Add('begin');
|
||||||
|
ConvertProgram;
|
||||||
|
CheckSource('TestAliasTypeRef',
|
||||||
|
LinesToStr([ // statements
|
||||||
|
'this.c = 0;',
|
||||||
|
'this.d = 0;'
|
||||||
|
]),
|
||||||
|
LinesToStr([ // this.$main
|
||||||
|
''
|
||||||
|
]));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.TestIncDec;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add('var');
|
||||||
|
Add(' i: longint;');
|
||||||
|
Add('begin');
|
||||||
|
Add(' inc(i);');
|
||||||
|
Add(' inc(i,2);');
|
||||||
|
Add(' dec(i);');
|
||||||
|
Add(' dec(i,3);');
|
||||||
|
ConvertProgram;
|
||||||
|
CheckSource('TestIncDec',
|
||||||
|
LinesToStr([ // statements
|
||||||
|
'this.i = 0;'
|
||||||
|
]),
|
||||||
|
LinesToStr([ // this.$main
|
||||||
|
'this.i+=1;',
|
||||||
|
'this.i+=2;',
|
||||||
|
'this.i-=1;',
|
||||||
|
'this.i-=3;'
|
||||||
|
]));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.TestAssignments;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Parser.Options:=Parser.Options+[po_cassignments];
|
||||||
|
Add('var');
|
||||||
|
Add(' i:longint;');
|
||||||
|
Add('begin');
|
||||||
|
Add(' i:=3;');
|
||||||
|
Add(' i+=4;');
|
||||||
|
Add(' i-=5;');
|
||||||
|
Add(' i*=6;');
|
||||||
|
ConvertProgram;
|
||||||
|
CheckSource('TestAssignments',
|
||||||
|
LinesToStr([ // statements
|
||||||
|
'this.i = 0;'
|
||||||
|
]),
|
||||||
|
LinesToStr([ // this.$main
|
||||||
|
'this.i=3;',
|
||||||
|
'this.i+=4;',
|
||||||
|
'this.i-=5;',
|
||||||
|
'this.i*=6;'
|
||||||
|
]));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.TestPrgProcVar;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add('procedure Proc1;');
|
||||||
|
Add('type');
|
||||||
|
Add(' t1=longint;');
|
||||||
|
Add('var');
|
||||||
|
Add(' v1:t1;');
|
||||||
|
Add('begin');
|
||||||
|
Add('end;');
|
||||||
|
Add('begin');
|
||||||
|
ConvertProgram;
|
||||||
|
CheckSource('TestPrgProcVar',
|
||||||
|
LinesToStr([ // statements
|
||||||
|
'this.proc1 = function () {',
|
||||||
|
' var v1=0;',
|
||||||
|
'};'
|
||||||
|
]),
|
||||||
|
LinesToStr([ // this.$main
|
||||||
|
''
|
||||||
|
]));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.TestUnitProcVar;
|
||||||
|
begin
|
||||||
|
StartUnit(false);
|
||||||
|
Add('interface');
|
||||||
|
Add('');
|
||||||
|
Add('type t1=string; // unit scope');
|
||||||
|
Add('procedure Proc1;');
|
||||||
|
Add('');
|
||||||
|
Add('implementation');
|
||||||
|
Add('');
|
||||||
|
Add('procedure Proc1;');
|
||||||
|
Add('type t1=longint; // local proc scope');
|
||||||
|
Add('var v1:t1; // using local t1');
|
||||||
|
Add('begin');
|
||||||
|
Add('end;');
|
||||||
|
Add('var v2:t1; // using interface t1');
|
||||||
|
ConvertUnit;
|
||||||
|
CheckSource('TestUnitProcVar',
|
||||||
|
LinesToStr([ // statements
|
||||||
|
'var $impl = {',
|
||||||
|
'};',
|
||||||
|
'this.proc1 = function () {',
|
||||||
|
' var v1 = 0;',
|
||||||
|
'};',
|
||||||
|
'this.$impl = $impl;',
|
||||||
|
'$impl.v2 = "";'
|
||||||
|
]),
|
||||||
|
'' // this.$init
|
||||||
|
);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.TestUnitImplVars;
|
||||||
|
begin
|
||||||
|
StartUnit(false);
|
||||||
|
Add('interface');
|
||||||
|
Add('implementation');
|
||||||
|
Add('var');
|
||||||
|
Add(' v1:longint;');
|
||||||
|
Add(' v2:longint = 3;');
|
||||||
|
Add(' v3:string = ''abc'';');
|
||||||
|
ConvertUnit;
|
||||||
|
CheckSource('TestUnitImplVar',
|
||||||
|
LinesToStr([ // statements
|
||||||
|
' var $impl = {',
|
||||||
|
'};',
|
||||||
|
'this.$impl = $impl;',
|
||||||
|
'$impl.v1 = 0;',
|
||||||
|
'$impl.v2 = 3;',
|
||||||
|
'$impl.v3 = "abc";'
|
||||||
|
]),
|
||||||
|
'');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.TestUnitImplConsts;
|
||||||
|
begin
|
||||||
|
StartUnit(false);
|
||||||
|
Add('interface');
|
||||||
|
Add('implementation');
|
||||||
|
Add('const');
|
||||||
|
Add(' v1 = 3;');
|
||||||
|
Add(' v2:longint = 4;');
|
||||||
|
Add(' v3:string = ''abc'';');
|
||||||
|
ConvertUnit;
|
||||||
|
CheckSource('TestUnitImplVar',
|
||||||
|
LinesToStr([ // statements
|
||||||
|
'var $impl = {',
|
||||||
|
'};',
|
||||||
|
'this.$impl = $impl;',
|
||||||
|
'$impl.v1 = 3;',
|
||||||
|
'$impl.v2 = 4;',
|
||||||
|
'$impl.v3 = "abc";'
|
||||||
|
]),
|
||||||
|
'');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.TestUnitImplRecord;
|
||||||
|
begin
|
||||||
|
StartUnit(false);
|
||||||
|
Add('interface');
|
||||||
|
Add('implementation');
|
||||||
|
Add('type');
|
||||||
|
Add(' TMyRecord = record');
|
||||||
|
Add(' i: longint;');
|
||||||
|
Add(' end;');
|
||||||
|
Add('var r: TMyRecord;');
|
||||||
|
Add('initialization');
|
||||||
|
Add(' r.i:=3;');
|
||||||
|
ConvertUnit;
|
||||||
|
CheckSource('TestUnitImplVar',
|
||||||
|
LinesToStr([ // statements
|
||||||
|
'var $impl = {',
|
||||||
|
'};',
|
||||||
|
'this.$impl = $impl;',
|
||||||
|
'$impl.tmyrecord = function () {',
|
||||||
|
' this.i = 0;',
|
||||||
|
'};',
|
||||||
|
'$impl.r = new $impl.tmyrecord();'
|
||||||
|
]),
|
||||||
|
'$impl.r.i = 3;'
|
||||||
|
);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestModule.TestProcTwoArgs;
|
procedure TTestModule.TestProcTwoArgs;
|
||||||
begin
|
begin
|
||||||
StartProgram(false);
|
StartProgram(false);
|
||||||
@ -799,7 +1153,7 @@ begin
|
|||||||
CheckSource('TestVarRecord',
|
CheckSource('TestVarRecord',
|
||||||
LinesToStr([ // statements
|
LinesToStr([ // statements
|
||||||
'this.treca = function () {',
|
'this.treca = function () {',
|
||||||
' b = 0;',
|
' this.b = 0;',
|
||||||
'};',
|
'};',
|
||||||
'this.r = new this.treca();'
|
'this.r = new this.treca();'
|
||||||
]),
|
]),
|
||||||
@ -944,6 +1298,141 @@ begin
|
|||||||
Add(' i:=3');
|
Add(' i:=3');
|
||||||
Add(' end;');
|
Add(' end;');
|
||||||
ConvertProgram;
|
ConvertProgram;
|
||||||
|
CheckSource('TestVarRecord',
|
||||||
|
LinesToStr([ // statements
|
||||||
|
'this.i = 0;'
|
||||||
|
]),
|
||||||
|
LinesToStr([ // this.$main
|
||||||
|
'try {',
|
||||||
|
' this.i = 0;',
|
||||||
|
' this.i = (2 / this.i);',
|
||||||
|
'} finally {',
|
||||||
|
' this.i = 3;',
|
||||||
|
'};'
|
||||||
|
]));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.TestCaseOf;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add('var i: longint;');
|
||||||
|
Add('begin');
|
||||||
|
Add(' case i of');
|
||||||
|
Add(' 1: ;');
|
||||||
|
Add(' 2: i:=3;');
|
||||||
|
Add(' else');
|
||||||
|
Add(' i:=4');
|
||||||
|
Add(' end;');
|
||||||
|
ConvertProgram;
|
||||||
|
CheckSource('TestVarRecord',
|
||||||
|
LinesToStr([ // statements
|
||||||
|
'this.i = 0;'
|
||||||
|
]),
|
||||||
|
LinesToStr([ // this.$main
|
||||||
|
'var $tmp1 = this.i;',
|
||||||
|
'if (($tmp1 == 1)) {} else if (($tmp1 == 2)) this.i = 3 else {',
|
||||||
|
' this.i = 4;',
|
||||||
|
'};'
|
||||||
|
]));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.TestCaseOf_UseSwitch;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Converter.UseSwitchStatement:=true;
|
||||||
|
Add('var i: longint;');
|
||||||
|
Add('begin');
|
||||||
|
Add(' case i of');
|
||||||
|
Add(' 1: ;');
|
||||||
|
Add(' 2: i:=3;');
|
||||||
|
Add(' else');
|
||||||
|
Add(' i:=4');
|
||||||
|
Add(' end;');
|
||||||
|
ConvertProgram;
|
||||||
|
CheckSource('TestVarRecord',
|
||||||
|
LinesToStr([ // statements
|
||||||
|
'this.i = 0;'
|
||||||
|
]),
|
||||||
|
LinesToStr([ // this.$main
|
||||||
|
'switch (this.i) {',
|
||||||
|
'case 1:',
|
||||||
|
' break;',
|
||||||
|
'case 2:',
|
||||||
|
' this.i = 3;',
|
||||||
|
' break;',
|
||||||
|
'default:',
|
||||||
|
' this.i = 4;',
|
||||||
|
'};'
|
||||||
|
]));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.TestCaseOfNoElse;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add('var i: longint;');
|
||||||
|
Add('begin');
|
||||||
|
Add(' case i of');
|
||||||
|
Add(' 1: begin i:=2; i:=3; end;');
|
||||||
|
Add(' end;');
|
||||||
|
ConvertProgram;
|
||||||
|
CheckSource('TestVarRecord',
|
||||||
|
LinesToStr([ // statements
|
||||||
|
'this.i = 0;'
|
||||||
|
]),
|
||||||
|
LinesToStr([ // this.$main
|
||||||
|
'var $tmp1 = this.i;',
|
||||||
|
'if (($tmp1 == 1)) {',
|
||||||
|
' this.i = 2;',
|
||||||
|
' this.i = 3;',
|
||||||
|
'};'
|
||||||
|
]));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.TestCaseOfNoElse_UseSwitch;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Converter.UseSwitchStatement:=true;
|
||||||
|
Add('var i: longint;');
|
||||||
|
Add('begin');
|
||||||
|
Add(' case i of');
|
||||||
|
Add(' 1: begin i:=2; i:=3; end;');
|
||||||
|
Add(' end;');
|
||||||
|
ConvertProgram;
|
||||||
|
CheckSource('TestVarRecord',
|
||||||
|
LinesToStr([ // statements
|
||||||
|
'this.i = 0;'
|
||||||
|
]),
|
||||||
|
LinesToStr([ // this.$main
|
||||||
|
'switch (this.i) {',
|
||||||
|
'case 1:',
|
||||||
|
' this.i = 2;',
|
||||||
|
' this.i = 3;',
|
||||||
|
' break;',
|
||||||
|
'};'
|
||||||
|
]));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.TestCaseOfRange;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add('var i: longint;');
|
||||||
|
Add('begin');
|
||||||
|
Add(' case i of');
|
||||||
|
Add(' 1..3: i:=14;');
|
||||||
|
Add(' 4,5: i:=16;');
|
||||||
|
Add(' 6..7,9..10: ;');
|
||||||
|
Add(' else ;');
|
||||||
|
Add(' end;');
|
||||||
|
ConvertProgram;
|
||||||
|
CheckSource('TestVarRecord',
|
||||||
|
LinesToStr([ // statements
|
||||||
|
'this.i = 0;'
|
||||||
|
]),
|
||||||
|
LinesToStr([ // this.$main
|
||||||
|
'var $tmp1 = this.i;',
|
||||||
|
'if ((($tmp1 >= 1) && ($tmp1 <= 3))) this.i = 14 else if ((($tmp1 == 4) || ($tmp1 == 5))) this.i = 16 else if (((($tmp1 >= 6) && ($tmp1 <= 7)) || (($tmp1 >= 9) && ($tmp1 <= 10)))) {} else {',
|
||||||
|
'};'
|
||||||
|
]));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Initialization
|
Initialization
|
||||||
|
Loading…
Reference in New Issue
Block a user