* Patch from Mattias Gaertner:

jswriter: 
    fixed some empty lines 
  pasresolver: 
    procedure str, function str
  fppas2js: 
    procedure str,function str
    write less empty blocks
    target platform browser and nodejs

git-svn-id: trunk@35633 -
This commit is contained in:
michael 2017-03-20 23:29:53 +00:00
parent a2d397c064
commit 44c5fe99c9
8 changed files with 787 additions and 279 deletions

View File

@ -127,7 +127,7 @@ Type
// one per type of statement
Procedure WriteValue(V : TJSValue); virtual;
Procedure WriteRegularExpressionLiteral(El: TJSRegularExpressionLiteral);
Procedure WriteVariableStatement(el: TJSVariableStatement);
Procedure WriteVariableStatement(El: TJSVariableStatement);
Procedure WriteEmptyBlockStatement(El: TJSEmptyBlockStatement); virtual;
Procedure WriteEmptyStatement(El: TJSEmptyStatement);virtual;
Procedure WriteLiteral(El: TJSLiteral);virtual;
@ -157,6 +157,8 @@ Type
Procedure WriteFuncDef(FD: TJSFuncDef);virtual;
Procedure WritePrimaryExpression(El: TJSPrimaryExpression);virtual;
Procedure WriteBinary(El: TJSBinary);virtual;
Function IsEmptyStatement(El: TJSElement): boolean;
Function HasLineEnding(El: TJSElement): boolean;
Public
Function EscapeString(const S: TJSString; Quote: TJSEscapeQuote = jseqDouble): TJSString;
Constructor Create(AWriter : TTextWriter);
@ -584,6 +586,7 @@ procedure TJSWriter.WriteFuncDef(FD: TJSFuncDef);
Var
C : Boolean;
I : Integer;
A: TJSElement;
begin
C:=(woCompact in Options);
@ -609,10 +612,11 @@ begin
FSkipCurlyBrackets:=True;
//writeln('TJSWriter.WriteFuncDef '+FD.Body.ClassName);
WriteJS(FD.Body);
If (Assigned(FD.Body.A))
and (not (FD.Body.A is TJSStatementList))
and (not (FD.Body.A is TJSSourceElements))
and (not (FD.Body.A is TJSEmptyBlockStatement))
A:=FD.Body.A;
If (Assigned(A))
and (not (A is TJSStatementList))
and (not (A is TJSSourceElements))
and (not (A is TJSEmptyBlockStatement))
then
if C then
Write('; ')
@ -861,7 +865,7 @@ begin
Indent;
if not C then writeln('');
end;
if Assigned(El.A) and (El.A.ClassType<>TJSEmptyBlockStatement) then
if not IsEmptyStatement(El.A) then
begin
WriteJS(El.A);
LastEl:=El.A;
@ -926,6 +930,9 @@ Var
S : AnsiString;
AllowCompact, WithBrackets: Boolean;
begin
{$IFDEF VerboseJSWriter}
System.writeln('TJSWriter.WriteBinary SkipRoundBrackets=',FSkipRoundBrackets);
{$ENDIF}
WithBrackets:=not FSkipRoundBrackets;
if WithBrackets then
Write('(');
@ -945,6 +952,25 @@ begin
Write(')');
end;
function TJSWriter.IsEmptyStatement(El: TJSElement): boolean;
begin
if (El=nil) then
exit(true);
if (El.ClassType=TJSEmptyStatement) and not (woEmptyStatementAsComment in Options) then
exit(true);
Result:=false;
end;
function TJSWriter.HasLineEnding(El: TJSElement): boolean;
begin
if El<>nil then
begin
if (El.ClassType=TJSStatementList) or (El.ClassType=TJSSourceElements) then
exit(true);
end;
Result:=false;
end;
procedure TJSWriter.WriteConditionalExpression(El: TJSConditionalExpression);
begin
@ -987,22 +1013,29 @@ end;
procedure TJSWriter.WriteIfStatement(El: TJSIfStatement);
var
BTrueEmpty, C: Boolean;
begin
C:=woCompact in Options;
Write('if (');
FSkipRoundBrackets:=true;
WriteJS(El.Cond);
FSkipRoundBrackets:=false;
Write(')');
If Not (woCompact in Options) then
If Not C then
Write(' ');
if (El.BTrue<>nil) and (not (El.BTrue is TJSEmptyStatement)) then
begin
BTrueEmpty:=IsEmptyStatement(El.BTrue);
if not BTrueEmpty then
WriteJS(El.BTrue);
end;
if Assigned(El.BFalse) then
if not IsEmptyStatement(El.BFalse) then
begin
if (El.BTrue=nil) or (El.BTrue is TJSEmptyStatement) then
Writeln('{}')
if BTrueEmpty then
begin
if C then
Write('{}')
else
Writeln('{}');
end
else
Write(' ');
Write('else ');
@ -1131,7 +1164,7 @@ begin
Indent;
WriteJS(EC.Body);
Undent;
if ((EC.Body is TJSStatementList) or (EC.Body is TJSEmptyBlockStatement)) then
if (EC.Body is TJSStatementList) or (EC.Body is TJSEmptyBlockStatement) then
begin
if C then
begin
@ -1226,12 +1259,15 @@ Var
begin
C:=woCompact in Options;
Write('try {');
if Not C then writeln('');
FSkipCurlyBrackets:=True;
Indent;
WriteJS(El.Block);
if Not C then writeln('');
Undent;
if not IsEmptyStatement(El.Block) then
begin
if Not C then writeln('');
FSkipCurlyBrackets:=True;
Indent;
WriteJS(El.Block);
if (Not C) and (not (El.Block is TJSStatementList)) then writeln('');
Undent;
end;
Write('}');
If (El is TJSTryCatchFinallyStatement) or (El is TJSTryCatchStatement) then
begin
@ -1241,11 +1277,14 @@ begin
Write(' {')
else
Writeln(' {');
FSkipCurlyBrackets:=True;
Indent;
WriteJS(El.BCatch);
Undent;
if Not C then writeln('');
if not IsEmptyStatement(El.BCatch) then
begin
FSkipCurlyBrackets:=True;
Indent;
WriteJS(El.BCatch);
Undent;
if (Not C) and (not (El.BCatch is TJSStatementList)) then writeln('');
end;
Write('}');
end;
If (El is TJSTryCatchFinallyStatement) or (El is TJSTryFinallyStatement) then
@ -1254,11 +1293,14 @@ begin
Write(' finally {')
else
Writeln(' finally {');
Indent;
FSkipCurlyBrackets:=True;
WriteJS(El.BFinally);
Undent;
if Not C then writeln('');
if not IsEmptyStatement(El.BFinally) then
begin
Indent;
FSkipCurlyBrackets:=True;
WriteJS(El.BFinally);
Undent;
if (Not C) and (not (El.BFinally is TJSStatementList)) then writeln('');
end;
Write('}');
end;
end;
@ -1267,7 +1309,7 @@ procedure TJSWriter.WriteFunctionBody(El: TJSFunctionBody);
begin
//writeln('TJSWriter.WriteFunctionBody '+El.A.ClassName+' FSkipBrackets='+BoolToStr(FSkipCurlyBrackets,'true','false'));
if Assigned(El.A) and (not (El.A is TJSEmptyBlockStatement)) then
if not IsEmptyStatement(El.A) then
WriteJS(El.A);
end;
@ -1311,11 +1353,11 @@ begin
WriteElements(El.Statements);
end;
procedure TJSWriter.WriteVariableStatement(el: TJSVariableStatement);
procedure TJSWriter.WriteVariableStatement(El: TJSVariableStatement);
begin
Write('var ');
WriteJS(EL.A);
WriteJS(El.A);
end;
procedure TJSWriter.WriteJS(El: TJSElement);

View File

@ -110,7 +110,7 @@ Works:
- procedure break, procedure continue
- built-in functions pred, succ for range type and enums
- untyped parameters
- built-in procedure str(const boolean|integer|enumvalue|classinstance,var s: string)
ToDo:
- fix slow lookup declaration proc in PParser
@ -159,9 +159,9 @@ Notes:
@f(); @ operator applies to result of f
f(); use f's result
FuncVar:=Func; if mode=objfpc: incompatible
if mode=delphi: implicit addr of function f, not yet implemented
if f=g then : can implicit resolve each side once, at the moment: always implicit
p(f), f as var parameter: always implicit, thus incompatible
if mode=delphi: implicit addr of function f
if f=g then : can implicit resolve each side once
p(f), f as var parameter: can implicit
}
unit PasResolver;
@ -430,7 +430,9 @@ type
bfLow,
bfHigh,
bfPred,
bfSucc
bfSucc,
bfStrProc,
bfStrFunc
);
TResolverBuiltInProcs = set of TResolverBuiltInProc;
const
@ -450,7 +452,9 @@ const
'Low',
'High',
'Pred',
'Succ'
'Succ',
'Str',
'Str'
);
bfAllStandardProcs = [Succ(bfCustom)..high(TResolverBuiltInProc)];
@ -1042,6 +1046,8 @@ type
ErrorEl: TPasElement; RaiseOnError: boolean): boolean;
procedure ConvertRangeToFirstValue(var ResolvedEl: TPasResolverResult);
function IsCharLiteral(const Value: string): boolean; virtual;
function CheckBuiltInMinParamCount(Proc: TResElDataBuiltInProc; Expr: TPasExpr;
MinCount: integer; RaiseOnError: boolean): boolean;
protected
// built-in functions
function BI_Length_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
@ -1082,6 +1088,17 @@ type
Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
procedure BI_PredSucc_OnGetCallResult({%H-}Proc: TResElDataBuiltInProc;
{%H-}Params: TParamsExpr; out ResolvedEl: TPasResolverResult); virtual;
function BI_Str_CheckParam(Param: TPasExpr;
const ParamResolved: TPasResolverResult; ArgNo: integer;
RaiseOnError: boolean): integer;
function BI_StrProc_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
procedure BI_StrProc_OnFinishParamsExpr(Proc: TResElDataBuiltInProc;
Params: TParamsExpr); virtual;
function BI_StrFunc_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
procedure BI_StrFunc_OnGetCallResult({%H-}Proc: TResElDataBuiltInProc;
{%H-}Params: TParamsExpr; out ResolvedEl: TPasResolverResult); virtual;
public
constructor Create;
destructor Destroy; override;
@ -4168,6 +4185,9 @@ begin
ComputeElement(Expr,ExprResolved,[rcSkipTypeAlias]);
if (rrfCanBeStatement in ExprResolved.Flags) then
exit;
{$IFDEF VerbosePasResolver}
writeln('TPasResolver.ResolveImplSimple El=',GetObjName(El),' El.Expr=',GetObjName(El.Expr),' ExprResolved=',GetResolverResultDesc(ExprResolved));
{$ENDIF}
RaiseMsg(20170216152127,nIllegalExpression,sIllegalExpression,[],El);
end;
@ -4215,9 +4235,9 @@ begin
Primitive:=TPrimitiveExpr(El);
case Primitive.Kind of
pekIdent: ResolveNameExpr(El,Primitive.Value,Access);
pekNumber: exit;
pekString: exit;
pekNil,pekBoolConst: exit;
pekNumber: ;
pekString: ;
pekNil,pekBoolConst: ;
else
RaiseNotYetImplemented(20160922163451,El);
end;
@ -4243,6 +4263,11 @@ begin
end
else
RaiseNotYetImplemented(20170222184329,El);
if El.format1<>nil then
ResolveExpr(El.format1,rraRead);
if El.format2<>nil then
ResolveExpr(El.format2,rraRead);
end;
procedure TPasResolver.ResolveStatementConditionExpr(El: TPasExpr);
@ -6077,6 +6102,19 @@ begin
end;
end;
function TPasResolver.CheckBuiltInMinParamCount(Proc: TResElDataBuiltInProc;
Expr: TPasExpr; MinCount: integer; RaiseOnError: boolean): boolean;
begin
if (not (Expr is TParamsExpr)) or (length(TParamsExpr(Expr).Params)<MinCount) then
begin
if RaiseOnError then
RaiseMsg(20170216152248,nWrongNumberOfParametersForCallTo,
sWrongNumberOfParametersForCallTo,[Proc.Signature],Expr);
exit(false);
end;
Result:=true;
end;
function TPasResolver.BI_Length_OnGetCallCompatibility(
Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
// check params of built in proc 'length'
@ -6085,13 +6123,8 @@ var
Param: TPasExpr;
ParamResolved: TPasResolverResult;
begin
if (not (Expr is TParamsExpr)) or (length(TParamsExpr(Expr).Params)<1) then
begin
if RaiseOnError then
RaiseMsg(20170216152248,nWrongNumberOfParametersForCallTo,
sWrongNumberOfParametersForCallTo,[Proc.Signature],Expr);
if not CheckBuiltInMinParamCount(Proc,Expr,1,RaiseOnError) then
exit(cIncompatible);
end;
Params:=TParamsExpr(Expr);
// first param: string or dynamic array
@ -6142,13 +6175,8 @@ var
ParamResolved: TPasResolverResult;
ArrayType: TPasArrayType;
begin
if (not (Expr is TParamsExpr)) or (length(TParamsExpr(Expr).Params)<2) then
begin
if RaiseOnError then
RaiseMsg(20170216152253,nWrongNumberOfParametersForCallTo,
sWrongNumberOfParametersForCallTo,[Proc.Signature],Expr);
if not CheckBuiltInMinParamCount(Proc,Expr,2,RaiseOnError) then
exit(cIncompatible);
end;
Params:=TParamsExpr(Expr);
// first param: string or array variable
@ -6222,13 +6250,8 @@ var
ParamResolved: TPasResolverResult;
EnumType: TPasEnumType;
begin
if (not (Expr is TParamsExpr)) or (length(TParamsExpr(Expr).Params)<2) then
begin
if RaiseOnError then
RaiseMsg(20170216152259,nWrongNumberOfParametersForCallTo,
sWrongNumberOfParametersForCallTo,[Proc.Signature],Expr);
if not CheckBuiltInMinParamCount(Proc,Expr,2,RaiseOnError) then
exit(cIncompatible);
end;
Params:=TParamsExpr(Expr);
// first param: variable of set of enumtype
@ -6412,13 +6435,8 @@ var
Param: TPasExpr;
ParamResolved, IncrResolved: TPasResolverResult;
begin
if (not (Expr is TParamsExpr)) or (length(TParamsExpr(Expr).Params)<1) then
begin
if RaiseOnError then
RaiseMsg(20170216152318,nWrongNumberOfParametersForCallTo,
sWrongNumberOfParametersForCallTo,[Proc.Signature],Expr);
if not CheckBuiltInMinParamCount(Proc,Expr,1,RaiseOnError) then
exit(cIncompatible);
end;
Params:=TParamsExpr(Expr);
// first param: var Integer
@ -6498,13 +6516,8 @@ var
Param: TPasExpr;
ParamResolved: TPasResolverResult;
begin
if (not (Expr is TParamsExpr)) or (length(TParamsExpr(Expr).Params)<1) then
begin
if RaiseOnError then
RaiseMsg(20170216152326,nWrongNumberOfParametersForCallTo,
sWrongNumberOfParametersForCallTo,[Proc.Signature],Expr);
if not CheckBuiltInMinParamCount(Proc,Expr,1,RaiseOnError) then
exit(cIncompatible);
end;
Params:=TParamsExpr(Expr);
// first param: pointer or proc type
@ -6551,13 +6564,8 @@ var
Param: TPasExpr;
ParamResolved: TPasResolverResult;
begin
if (not (Expr is TParamsExpr)) or (length(TParamsExpr(Expr).Params)<1) then
begin
if RaiseOnError then
RaiseMsg(20170216152332,nWrongNumberOfParametersForCallTo,
sWrongNumberOfParametersForCallTo,[Proc.Signature],Expr);
if not CheckBuiltInMinParamCount(Proc,Expr,1,RaiseOnError) then
exit(cIncompatible);
end;
Params:=TParamsExpr(Expr);
// first param: enum or char
@ -6606,13 +6614,8 @@ var
ParamResolved: TPasResolverResult;
TypeEl: TPasType;
begin
if (not (Expr is TParamsExpr)) or (length(TParamsExpr(Expr).Params)<1) then
begin
if RaiseOnError then
RaiseMsg(20170216152337,nWrongNumberOfParametersForCallTo,
sWrongNumberOfParametersForCallTo,[Proc.Signature],Expr);
if not CheckBuiltInMinParamCount(Proc,Expr,1,RaiseOnError) then
exit(cIncompatible);
end;
Params:=TParamsExpr(Expr);
// first param: enum, range or char
@ -6698,13 +6701,8 @@ var
Param: TPasExpr;
ParamResolved: TPasResolverResult;
begin
if (not (Expr is TParamsExpr)) or (length(TParamsExpr(Expr).Params)<1) then
begin
if RaiseOnError then
RaiseMsg(20170216152341,nWrongNumberOfParametersForCallTo,
sWrongNumberOfParametersForCallTo,[Proc.Signature],Expr);
if not CheckBuiltInMinParamCount(Proc,Expr,1,RaiseOnError) then
exit(cIncompatible);
end;
Params:=TParamsExpr(Expr);
// first param: enum, range, set, char or integer
@ -6740,6 +6738,165 @@ begin
ResolvedEl.Flags:=ResolvedEl.Flags-[rrfWritable];
end;
function TPasResolver.BI_Str_CheckParam(Param: TPasExpr;
const ParamResolved: TPasResolverResult; ArgNo: integer; RaiseOnError: boolean
): integer;
function CheckFormat(FormatExpr: TPasExpr; Index: integer;
const ParamResolved: TPasResolverResult): boolean;
var
ResolvedEl: TPasResolverResult;
Ok: Boolean;
begin
if FormatExpr=nil then exit(true);
Result:=false;
Ok:=false;
if ParamResolved.BaseType in btAllFloats then
// floats supports value:Width:Precision
Ok:=true
else
// all other only support only Width
Ok:=Index<2;
if not Ok then
begin
if RaiseOnError then
RaiseMsg(20170319222319,nIllegalExpression,sIllegalExpression,[],FormatExpr);
exit;
end;
ComputeElement(FormatExpr,ResolvedEl,[]);
if not (ResolvedEl.BaseType in btAllInteger) then
begin
if RaiseOnError then
RaiseMsg(20170319221515,nXExpectedButYFound,sXExpectedButYFound,
['integer',GetResolverResultDescription(ResolvedEl)],FormatExpr);
exit;
end;
if not (rrfReadable in ResolvedEl.Flags) then
begin
if RaiseOnError then
RaiseMsg(20170319221755,nNotReadable,sNotReadable,[],FormatExpr);
exit;
end;
Result:=true;
end;
var
TypeEl: TPasType;
begin
Result:=cIncompatible;
if ParamResolved.BaseType in (btAllInteger+btAllBooleans+btAllFloats) then
Result:=cExact
else if ParamResolved.BaseType=btContext then
begin
TypeEl:=ParamResolved.TypeEl;
if TypeEl.ClassType=TPasEnumType then
Result:=cExact
end;
if Result=cIncompatible then
begin
if RaiseOnError then
RaiseMsg(20170319220517,nIncompatibleTypeArgNo,sIncompatibleTypeArgNo,
[IntToStr(ArgNo),GetTypeDesc(ParamResolved.TypeEl),'boolean, integer, enum value'],
Param);
exit;
end;
if not CheckFormat(Param.format1,1,ParamResolved) then
exit(cIncompatible);
if not CheckFormat(Param.format2,2,ParamResolved) then
exit(cIncompatible);
end;
function TPasResolver.BI_StrProc_OnGetCallCompatibility(
Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
// check params of built-in procedure 'Str'
var
Params: TParamsExpr;
Param: TPasExpr;
ParamResolved: TPasResolverResult;
begin
if not CheckBuiltInMinParamCount(Proc,Expr,2,RaiseOnError) then
exit(cIncompatible);
Params:=TParamsExpr(Expr);
// first param: boolean, integer, enum, class instance
Param:=Params.Params[0];
ComputeElement(Param,ParamResolved,[]);
Result:=BI_Str_CheckParam(Param,ParamResolved,1,RaiseOnError);
if Result=cIncompatible then
exit;
// second parameter: string variable
Param:=Params.Params[1];
ComputeElement(Param,ParamResolved,[]);
Result:=cIncompatible;
if ResolvedElCanBeVarParam(ParamResolved) then
begin
if ParamResolved.BaseType in btAllStrings then
Result:=cExact;
end;
if Result=cIncompatible then
begin
if RaiseOnError then
RaiseMsg(20170319220806,nIncompatibleTypeArgNo,sIncompatibleTypeArgNo,
['1',GetTypeDesc(ParamResolved.TypeEl),'string variable'],
Param);
exit;
end;
if length(Params.Params)>2 then
begin
if RaiseOnError then
RaiseMsg(20170216152345,nWrongNumberOfParametersForCallTo,
sWrongNumberOfParametersForCallTo,[Proc.Signature],Params.Params[2]);
exit(cIncompatible);
end;
Result:=cExact;
end;
procedure TPasResolver.BI_StrProc_OnFinishParamsExpr(Proc: TResElDataBuiltInProc;
Params: TParamsExpr);
var
P: TPasExprArray;
begin
if Proc=nil then ;
P:=Params.Params;
FinishParamExpressionAccess(P[0],rraRead);
FinishParamExpressionAccess(P[1],rraVarParam);
end;
function TPasResolver.BI_StrFunc_OnGetCallCompatibility(
Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
var
Params: TParamsExpr;
Param: TPasExpr;
ParamResolved: TPasResolverResult;
i: Integer;
begin
if not CheckBuiltInMinParamCount(Proc,Expr,1,RaiseOnError) then
exit(cIncompatible);
Params:=TParamsExpr(Expr);
// param: string, boolean, integer, enum, class instance
for i:=0 to length(Params.Params)-1 do
begin
Param:=Params.Params[i];
ComputeElement(Param,ParamResolved,[]);
Result:=BI_Str_CheckParam(Param,ParamResolved,i+1,RaiseOnError);
if Result=cIncompatible then
exit;
end;
Result:=cExact;
end;
procedure TPasResolver.BI_StrFunc_OnGetCallResult(Proc: TResElDataBuiltInProc;
Params: TParamsExpr; out ResolvedEl: TPasResolverResult);
begin
if Params=nil then ;
SetResolverIdentifier(ResolvedEl,btString,Proc.Proc,FBaseTypes[btString],[rrfReadable]);
end;
constructor TPasResolver.Create;
begin
inherited Create;
@ -7255,6 +7412,13 @@ begin
if bfSucc in BaseProcs then
AddBuiltInProc('Succ','function Succ(const ordinal): ordinal',
@BI_PredSucc_OnGetCallCompatibility,@BI_PredSucc_OnGetCallResult,nil,bfSucc);
if bfStrProc in BaseProcs then
AddBuiltInProc('Str','procedure Str(const var; var String)',
@BI_StrProc_OnGetCallCompatibility,nil,
@BI_StrProc_OnFinishParamsExpr,bfStrProc,[bipfCanBeStatement]);
if bfStrFunc in BaseProcs then
AddBuiltInProc('Str','function Str(const var): String',
@BI_StrFunc_OnGetCallCompatibility,@BI_StrFunc_OnGetCallResult,nil,bfStrFunc);
end;
function TPasResolver.AddBaseType(aName: shortstring; Typ: TResolverBaseType

View File

@ -507,7 +507,7 @@ type
ElType: TPasType;
end;
{ TPasEnumValue }
{ TPasEnumValue - Parent is TPasEnumType }
TPasEnumValue = class(TPasElement)
public

View File

@ -159,6 +159,9 @@ type
Procedure TestIncDec;
Procedure TestIncStringFail;
Procedure TestVarExternal;
Procedure TestStr_BaseTypes;
Procedure TestStr_StringFail;
Procedure TestStr_CharFail;
// strings
Procedure TestString_SetLength;
@ -179,6 +182,7 @@ type
Procedure TestEnumOrd;
Procedure TestEnumPredSucc;
Procedure TestEnum_CastIntegerToEnum;
Procedure TestEnum_Str;
// operators
Procedure TestPrgAssignment;
@ -560,7 +564,7 @@ begin
+' Scanner at'
+' at '+aFilename+'('+IntToStr(aRow)+','+IntToStr(aCol)+')'
+' Line="'+Scanner.CurLine+'"');
raise E;
Fail(E.Message);
end;
on E: EPasResolve do
begin
@ -575,12 +579,12 @@ begin
WriteSources(aFilename,aRow,aCol);
writeln('ERROR: TTestResolver.ParseProgram PasResolver: '+E.ClassName+':'+E.Message
+' at '+aFilename+'('+IntToStr(aRow)+','+IntToStr(aCol)+')');
raise E;
Fail(E.Message);
end;
on E: Exception do
begin
writeln('ERROR: TTestResolver.ParseProgram Exception: '+E.ClassName+':'+E.Message);
raise E;
Fail(E.Message);
end;
end;
TAssert.AssertSame('Has resolver',ResolverEngine,Parser.Engine);
@ -607,7 +611,7 @@ begin
+' Col='+IntToStr(Scanner.CurColumn)
+' Line="'+Scanner.CurLine+'"'
);
raise E;
Fail(E.Message);
end;
on E: EPasResolve do
begin
@ -617,12 +621,12 @@ begin
+' Col='+IntToStr(Scanner.CurColumn)
+' Line="'+Scanner.CurLine+'"'
);
raise E;
Fail(E.Message);
end;
on E: Exception do
begin
writeln('ERROR: TTestResolver.ParseUnit Exception: '+E.ClassName+':'+E.Message);
raise E;
Fail(E.Message);
end;
end;
TAssert.AssertSame('Has resolver',ResolverEngine,Parser.Engine);
@ -1196,7 +1200,7 @@ begin
WriteSources(aFilename,aRow,aCol);
s:='[TTestResolver.RaiseErrorAtSrc] '+aFilename+'('+IntToStr(aRow)+','+IntToStr(aCol)+') Error: '+Msg;
writeln('ERROR: ',s);
raise EAssertionFailedError.Create(s);
Fail(s);
end;
procedure TCustomTestResolver.RaiseErrorAtSrcMarker(Msg: string; aMarker: PSrcMarker);
@ -1219,7 +1223,7 @@ function TCustomTestResolver.AddModule(aFilename: string): TTestEnginePasResolve
begin
//writeln('TTestResolver.AddModule ',aFilename);
if FindModuleWithFilename(aFilename)<>nil then
raise EAssertionFailedError.Create('TTestResolver.AddModule: file "'+aFilename+'" already exists');
Fail('TTestResolver.AddModule: file "'+aFilename+'" already exists');
Result:=TTestEnginePasResolver.Create;
Result.Filename:=aFilename;
Result.AddObjFPCBuiltInIdentifiers;
@ -1406,7 +1410,7 @@ begin
+' Line="'+CurEngine.Scanner.CurLine+'"'
);
WriteSources(ErrFilename,ErrRow,ErrCol);
raise E;
Fail(E.Message);
end;
end;
//writeln('TTestResolver.OnPasResolverFindUnit END ',CurUnitName);
@ -1415,7 +1419,7 @@ begin
end;
end;
writeln('TTestResolver.OnPasResolverFindUnit missing unit "',aUnitName,'"');
raise EAssertionFailedError.Create('can''t find unit "'+aUnitName+'"');
Fail('can''t find unit "'+aUnitName+'"');
end;
procedure TCustomTestResolver.OnFindReference(El: TPasElement; FindData: pointer);
@ -1445,7 +1449,7 @@ var
s:='TTestResolver.OnCheckElementParent El='+GetTreeDesc(El)+' '+
ResolverEngine.GetElementSourcePosStr(El)+' '+Msg;
writeln('ERROR: ',s);
raise EAssertionFailedError.Create(s);
Fail(s);
end;
begin
@ -1811,6 +1815,62 @@ begin
ParseProgram;
end;
procedure TTestResolver.TestStr_BaseTypes;
begin
StartProgram(false);
Add('var');
Add(' b: boolean;');
Add(' i: longint;');
Add(' i64: int64;');
Add(' s: single;');
Add(' d: double;');
Add(' aString: string;');
Add('begin');
Add(' Str(b,{#a_var}aString);');
Add(' Str(b:1,aString);');
Add(' Str(b:i,aString);');
Add(' Str(i,aString);');
Add(' Str(i:2,aString);');
Add(' Str(i:i64,aString);');
Add(' Str(i64,aString);');
Add(' Str(i64:3,aString);');
Add(' Str(i64:i,aString);');
Add(' Str(s,aString);');
Add(' Str(d,aString);');
Add(' Str(d:4,aString);');
Add(' Str(d:4:5,aString);');
Add(' Str(d:4:i,aString);');
Add(' aString:=Str(b);');
Add(' aString:=Str(i:3);');
Add(' aString:=Str(d:3:4);');
Add(' aString:=Str(b,i,d);');
ParseProgram;
CheckAccessMarkers;
end;
procedure TTestResolver.TestStr_StringFail;
begin
StartProgram(false);
Add('var');
Add(' aString: string;');
Add('begin');
Add(' Str(aString,aString);');
CheckResolverException('Incompatible type arg no. 1: Got "String", expected "boolean, integer, enum value"',
nIncompatibleTypeArgNo);
end;
procedure TTestResolver.TestStr_CharFail;
begin
StartProgram(false);
Add('var');
Add(' c: char;');
Add(' aString: string;');
Add('begin');
Add(' Str(c,aString);');
CheckResolverException('Incompatible type arg no. 1: Got "Char", expected "boolean, integer, enum value"',
nIncompatibleTypeArgNo);
end;
procedure TTestResolver.TestString_SetLength;
begin
StartProgram(false);
@ -2127,6 +2187,22 @@ begin
CheckAccessMarkers;
end;
procedure TTestResolver.TestEnum_Str;
begin
StartProgram(false);
Add('type');
Add(' TFlag = (red, green, blue);');
Add('var');
Add(' f: TFlag;');
Add(' i: longint;');
Add(' aString: string;');
Add('begin');
Add(' aString:=str(f);');
Add(' aString:=str(f:3);');
Add(' str(f,aString);');
ParseProgram;
end;
procedure TTestResolver.TestPrgAssignment;
var
El: TPasElement;

View File

@ -153,8 +153,7 @@ Works:
- use 0o for octal literals
ToDos:
- function str, procedure str
- try raise E1 except on E: E2 end;
- class external
Not in Version 1.0:
- write, writeln
@ -245,8 +244,8 @@ resourcestring
sMissingExternalName = 'Missing external name';
const
DefaultFuncNameArray_SetLength = 'arraySetLength'; // rtl.arraySetLength
DefaultFuncNameArray_NewMultiDim = 'arrayNewMultiDim'; // rtl.arrayNewMultiDim
DefaultFuncNameArray_SetLength = 'arraySetLength'; // rtl.arraySetLength
DefaultFuncNameAs = 'as'; // rtl.as
DefaultFuncNameCreateClass = 'createClass'; // rtl.createClass
DefaultFuncNameFreeClassInstance = '$destroy';
@ -268,6 +267,8 @@ const
DefaultFuncNameSet_Reference = 'refSet'; // rtl.refSet
DefaultFuncNameSet_SymDiffSet = 'symDiffSet'; // rtl.symDiffSet >< (symmetrical difference)
DefaultFuncNameSet_Union = 'unionSet'; // rtl.unionSet +
DefaultFuncNameSpaceLeft = 'spaceLeft'; // rtl.spaceLeft
DefaultVarNameExceptObject = '$e';
DefaultVarNameImplementation = '$impl';
DefaultVarNameLoopEnd = '$loopend';
DefaultVarNameModules = 'pas';
@ -544,9 +545,20 @@ type
TPas2JSIsElementUsedEvent = function(Sender: TObject; El: TPasElement): boolean of object;
TPasToJsPlatform = (
PlatformBrowser,
PlatformNodeJS
);
TPasToJsPlatforms = set of TPasToJsPlatform;
const
PasToJsPlatformNames: array[TPasToJsPlatform] of string = (
'Browser',
'NodeJS'
);
type
TPasToJsProcessor = (
pECMAScript5,
pECMAScript6
ProcessorECMAScript5,
ProcessorECMAScript6
);
TPasToJsProcessors = set of TPasToJsProcessor;
const
@ -614,9 +626,12 @@ type
FFuncNameSet_Reference: String;
FFuncNameSet_SymDiffSet: String;
FFuncNameSet_Union: String;
FFuncNameSpaceLeft: String;
FOnIsElementUsed: TPas2JSIsElementUsedEvent;
FOptions: TPasToJsConverterOptions;
FTargetPlatform: TPasToJsPlatform;
FTargetProcessor: TPasToJsProcessor;
FVarNameExceptObject: String;
FVarNameImplementation: String;
FVarNameLoopEnd: String;
FVarNameModules: String;
@ -635,7 +650,6 @@ type
DataClass: TPas2JsElementDataClass): TPas2JsElementData;
procedure AddElementData(Data: TPas2JsElementData);
Procedure AddToSourceElements(Src: TJSSourceElements; El: TJSElement);
procedure SetTargetProcessor(const AValue: TPasToJsProcessor);
procedure SetUseEnumNumbers(const AValue: boolean);
procedure SetUseLowerCase(const AValue: boolean);
procedure SetUseSwitchStatement(const AValue: boolean);
@ -658,7 +672,6 @@ type
Function TransformVariableName(El: TPasElement; AContext : TConvertContext) : String; virtual;
Function TransformModuleName(El: TPasModule; AContext : TConvertContext) : String; virtual;
Function IsPreservedWord(aName: string): boolean; virtual;
Function GetExceptionObjectName(AContext: TConvertContext) : string;
// Never create an element manually, always use the below functions
Function IsElementUsed(El: TPasElement): boolean; virtual;
Function CreateElement(C: TJSElementClass; Src: TPasElement): TJSElement; virtual;
@ -702,9 +715,10 @@ type
RecordExpr: TJSElement; AContext: TConvertContext): TJSElement; virtual;
Function CreateCallback(El: TPasElement; ResolvedEl: TPasResolverResult;
AContext: TConvertContext): TJSElement; virtual;
Function CreateAssignStatement(LeftEl: TPasElement; AssignContext: TAssignContext): TJSElement; virtual;
// Statements
Function ConvertImplBlockElements(El: TPasImplBlock; AContext: TConvertContext): TJSElement; virtual;
Function ConvertBeginEndStatement(El: TPasImplBeginBlock; AContext: TConvertContext): TJSElement; virtual;
Function ConvertImplBlockElements(El: TPasImplBlock; AContext: TConvertContext; NilIfEmpty: boolean): TJSElement; virtual;
Function ConvertBeginEndStatement(El: TPasImplBeginBlock; AContext: TConvertContext; NilIfEmpty: boolean): TJSElement; virtual;
Function ConvertStatement(El: TPasImplStatement; AContext: TConvertContext ): TJSElement; virtual;
Function ConvertAssignStatement(El: TPasImplAssign; AContext: TConvertContext): TJSElement; virtual;
Function ConvertRaiseStatement(El: TPasImplRaise; AContext: TConvertContext ): TJSElement; virtual;
@ -741,6 +755,9 @@ type
Function ConvertBuiltInHigh(El: TParamsExpr; AContext: TConvertContext): TJSElement; virtual;
Function ConvertBuiltInPred(El: TParamsExpr; AContext: TConvertContext): TJSElement; virtual;
Function ConvertBuiltInSucc(El: TParamsExpr; AContext: TConvertContext): TJSElement; virtual;
Function ConvertBuiltInStrProc(El: TParamsExpr; AContext: TConvertContext): TJSElement; virtual;
Function ConvertBuiltInStrFunc(El: TParamsExpr; AContext: TConvertContext): TJSElement; virtual;
Function ConvertBuiltInStrParam(El: TPasExpr; AContext: TConvertContext; IsFirst: boolean): TJSElement; virtual;
Function ConvertRecordValues(El: TRecordValues; AContext: TConvertContext): TJSElement; virtual;
Function ConvertSelfExpression(El: TSelfExpr; AContext: TConvertContext): TJSElement; virtual;
Function ConvertBinaryExpression(El: TBinaryExpr; AContext: TConvertContext): TJSElement; virtual;
@ -776,7 +793,8 @@ type
Function ConvertPasElement(El : TPasElement; Resolver: TPasResolver) : TJSElement;
// options
Property Options: TPasToJsConverterOptions read FOptions write FOptions;
Property TargetProcessor: TPasToJsProcessor read FTargetProcessor write SetTargetProcessor;
Property TargetPlatform: TPasToJsPlatform read FTargetPlatform write FTargetPlatform;
Property TargetProcessor: TPasToJsProcessor read FTargetProcessor write FTargetProcessor;
Property UseLowerCase: boolean read GetUseLowerCase write SetUseLowerCase default true;
Property UseSwitchStatement: boolean read GetUseSwitchStatement write SetUseSwitchStatement;// default false, because slower than "if" in many engines
Property UseEnumNumbers: boolean read GetUseEnumNumbers write SetUseEnumNumbers; // default false
@ -806,6 +824,8 @@ type
Property FuncNameSet_Reference: String read FFuncNameSet_Reference write FFuncNameSet_Reference; // rtl.refSet
Property FuncNameSet_SymDiffSet: String read FFuncNameSet_SymDiffSet write FFuncNameSet_SymDiffSet; // rtl.symDiffSet (symmetrical difference ><
Property FuncNameSet_Union: String read FFuncNameSet_Union write FFuncNameSet_Union; // rtl.unionSet +
Property FuncNameSpaceLeft: String read FFuncNameSpaceLeft write FFuncNameSpaceLeft;
Property VarNameExceptObject: String read FVarNameExceptObject write FVarNameExceptObject;
Property VarNameImplementation: String read FVarNameImplementation write FVarNameImplementation;// empty to not use, default '$impl'
Property VarNameLoopEnd: String read FVarNameLoopEnd write FVarNameLoopEnd;
Property VarNameModules: String read FVarNameModules write FVarNameModules;
@ -813,9 +833,6 @@ type
Property VarNameWith: String read FVarNameWith write FVarNameWith;
end;
var
DefaultJSExceptionObject: string = '$e';
function CodePointToJSString(u: cardinal): TJSString;
function PosLast(c: char; const s: string): integer;
@ -2202,11 +2219,11 @@ begin
S:=copy(El.Value,2,length(El.Value));
case El.Value[1] of
'$': S:='0x'+S;
'&': if TargetProcessor=pECMAScript5 then
'&': if TargetProcessor=ProcessorECMAScript5 then
S:='0'+S
else
S:='0o'+S;
'%': if TargetProcessor=pECMAScript5 then
'%': if TargetProcessor=ProcessorECMAScript5 then
S:=''
else
S:='0b'+S;
@ -2948,6 +2965,8 @@ begin
bfHigh: Result:=ConvertBuiltInHigh(El,AContext);
bfPred: Result:=ConvertBuiltInPred(El,AContext);
bfSucc: Result:=ConvertBuiltInSucc(El,AContext);
bfStrProc: Result:=ConvertBuiltInStrProc(El,AContext);
bfStrFunc: Result:=ConvertBuiltInStrFunc(El,AContext);
else
RaiseNotSupported(El,AContext,20161130164955,'built in proc '+ResolverBuiltInProcNames[BuiltInProc.BuiltIn]);
end;
@ -3142,7 +3161,7 @@ var
ResolvedParam0: TPasResolverResult;
ArrayType: TPasArrayType;
Call: TJSCallExpression;
ValInit, Arg, LHS: TJSElement;
ValInit, Arg: TJSElement;
AssignSt: TJSSimpleAssignStatement;
AssignContext: TAssignContext;
ElType: TPasType;
@ -3163,7 +3182,6 @@ begin
{$IFDEF VerbosePasResolver}
writeln('TPasToJSConverter.ConvertBuiltInSetLength array');
{$ENDIF}
LHS:=nil;
AssignContext:=TAssignContext.Create(El,nil,AContext);
try
AContext.Resolver.ComputeElement(El.Value,AssignContext.LeftResolved,[rcNoImplicitProc]);
@ -3187,26 +3205,8 @@ begin
Call.Args.Elements.AddElement.Expr:=ValInit;
// create left side: array =
LHS:=ConvertElement(Param0,AssignContext);
if AssignContext.Call<>nil then
begin
// array has a setter -> right side was already added as parameter
if AssignContext.RightSide<>nil then
RaiseInconsistency(20170207215447);
Result:=LHS;
end
else
begin
AssignSt:=TJSSimpleAssignStatement(CreateElement(TJSSimpleAssignStatement,El));
AssignSt.LHS:=LHS;
AssignSt.Expr:=AssignContext.RightSide;
AssignContext.RightSide:=nil;
Result:=AssignSt;
end;
Result:=CreateAssignStatement(Param0,AssignContext);
finally
if Result=nil then
LHS.Free;
AssignContext.RightSide.Free;
AssignContext.Free;
end;
@ -3241,12 +3241,9 @@ var
Call: TJSCallExpression;
Param0: TPasExpr;
AssignContext: TAssignContext;
AssignSt: TJSSimpleAssignStatement;
LHS: TJSElement;
FunName: String;
begin
Result:=nil;
LHS:=nil;
Param0:=El.Params[0];
AssignContext:=TAssignContext.Create(El,nil,AContext);
try
@ -3264,26 +3261,8 @@ begin
Call.Args.Elements.AddElement.Expr:=ConvertElement(Param0,AContext);
Call.Args.Elements.AddElement.Expr:=ConvertElement(El.Params[1],AContext);
// create left side: aSet =
LHS:=ConvertElement(Param0,AssignContext);
if AssignContext.Call<>nil then
begin
// set has a setter -> right side was already added as parameter
if AssignContext.RightSide<>nil then
RaiseInconsistency(20170301145100);
Result:=LHS;
end
else
begin
AssignSt:=TJSSimpleAssignStatement(CreateElement(TJSSimpleAssignStatement,El));
AssignSt.LHS:=LHS;
AssignSt.Expr:=AssignContext.RightSide;
AssignContext.RightSide:=nil;
Result:=AssignSt;
end;
Result:=CreateAssignStatement(Param0,AssignContext);
finally
if Result=nil then
LHS.Free;
AssignContext.RightSide.Free;
AssignContext.Free;
end;
@ -3617,7 +3596,7 @@ end;
function TPasToJSConverter.ConvertBuiltInSucc(El: TParamsExpr;
AContext: TConvertContext): TJSElement;
// pred(enumvalue) -> enumvalue-1
// succ(enumvalue) -> enumvalue+1
var
ResolvedEl: TPasResolverResult;
Param: TPasExpr;
@ -3642,6 +3621,163 @@ begin
DoError(20170210120626,nExpectedXButFoundY,sExpectedXButFoundY,['enum',GetResolverResultDescription(ResolvedEl)],Param);
end;
function TPasToJSConverter.ConvertBuiltInStrProc(El: TParamsExpr;
AContext: TConvertContext): TJSElement;
// convert 'str(value,aString)' to 'aString = <string>'
// for the conversion see ConvertBuiltInStrFunc
var
AssignContext: TAssignContext;
StrVar: TPasExpr;
begin
Result:=nil;
AssignContext:=TAssignContext.Create(El,nil,AContext);
try
StrVar:=El.Params[1];
AContext.Resolver.ComputeElement(StrVar,AssignContext.LeftResolved,[rcNoImplicitProc]);
// create right side
AssignContext.RightSide:=ConvertBuiltInStrParam(El.Params[0],AContext,true);
SetResolverValueExpr(AssignContext.RightResolved,btString,
AContext.Resolver.BaseType[btString],El,[rrfReadable]);
// create 'StrVar = rightside'
Result:=CreateAssignStatement(StrVar,AssignContext);
finally
AssignContext.RightSide.Free;
AssignContext.Free;
end;
end;
function TPasToJSConverter.ConvertBuiltInStrFunc(El: TParamsExpr;
AContext: TConvertContext): TJSElement;
// convert 'str(boolean)' to '""+boolean'
// convert 'str(integer)' to '""+integer'
// convert 'str(float)' to '""+float'
// convert 'str(float:width)' to rtl.spaceLeft('""+float,width)'
// convert 'str(float:width:precision)' to 'rtl.spaceLeft(float.toFixed(precision),width)'
var
i: Integer;
Param: TPasExpr;
Sum, Add: TJSElement;
AddEl: TJSAdditiveExpressionPlus;
begin
{$IFDEF VerbosePas2JS}
writeln('TPasToJSConverter.ConvertBuiltInStrFunc Count=',length(El.Params));
{$ENDIF}
Result:=nil;
Sum:=nil;
Add:=nil;
try
for i:=0 to length(El.Params)-1 do
begin
Param:=El.Params[i];
Add:=ConvertBuiltInStrParam(Param,AContext,i=0);
if Sum=nil then
Sum:=Add
else
begin
AddEl:=TJSAdditiveExpressionPlus(CreateElement(TJSAdditiveExpressionPlus,Param));
AddEl.A:=Sum;
AddEl.B:=Add;
Sum:=AddEl;
end;
Add:=nil;
end;
Result:=Sum;
finally
Add.Free;
if Result=nil then
Sum.Free;
end;
end;
function TPasToJSConverter.ConvertBuiltInStrParam(El: TPasExpr;
AContext: TConvertContext; IsFirst: boolean): TJSElement;
var
ResolvedEl: TPasResolverResult;
NeedStrLit: Boolean;
Add: TJSElement;
Call: TJSCallExpression;
PlusEl: TJSAdditiveExpressionPlus;
Bracket: TJSBracketMemberExpression;
procedure PrependStrLit;
begin
PlusEl:=TJSAdditiveExpressionPlus(CreateElement(TJSAdditiveExpressionPlus,El));
PlusEl.A:=CreateLiteralString(El,'');
PlusEl.B:=Add;
Add:=PlusEl;
end;
begin
Result:=nil;
AContext.Resolver.ComputeElement(El,ResolvedEl,[]);
Add:=nil;
Call:=nil;
Bracket:=nil;
try
NeedStrLit:=false;
if ResolvedEl.BaseType in (btAllBooleans+btAllInteger) then
begin
NeedStrLit:=true;
Add:=ConvertElement(El,AContext);
end
else if ResolvedEl.BaseType in btAllFloats then
begin
NeedStrLit:=true;
Add:=ConvertElement(El,AContext);
if El.format2<>nil then
begin
// precision -> rtl El.toFixed(precision);
NeedStrLit:=false;
Call:=CreateCallExpression(El);
Call.Expr:=CreateDotExpression(El,Add,CreateBuiltInIdentifierExpr('toFixed'));
Call.Args.Elements.AddElement.Expr:=ConvertElement(El.format2,AContext);
Add:=Call;
Call:=nil;
end;
end
else if ResolvedEl.BaseType=btContext then
begin
if ResolvedEl.TypeEl.ClassType=TPasEnumType then
begin
// create enumtype[enumvalue]
Bracket:=TJSBracketMemberExpression(CreateElement(TJSBracketMemberExpression,El));
Bracket.MExpr:=CreateReferencePathExpr(TPasEnumType(ResolvedEl.TypeEl),AContext);
Bracket.Name:=ConvertElement(El,AContext);
Add:=Bracket;
Bracket:=nil;
end
else
RaiseNotSupported(El,AContext,20170320123827);
end
else
RaiseNotSupported(El,AContext,20170320093001);
if El.format1<>nil then
begin
// width -> leading spaces
if NeedStrLit then
PrependStrLit;
// create 'rtl.spaceLeft(add,width)'
Call:=CreateCallExpression(El);
Call.Expr:=CreateMemberExpression([VarNameRTL,FuncNameSpaceLeft]);
Call.Args.Elements.AddElement.Expr:=Add;
Add:=nil;
Call.Args.Elements.AddElement.Expr:=ConvertElement(El.format1,AContext);
Add:=Call;
Call:=nil;
end
else if IsFirst and NeedStrLit then
PrependStrLit;
Result:=Add;
finally
Call.Free;
Bracket.Free;
if Result=nil then
Add.Free;
end;
end;
function TPasToJSConverter.ConvertRecordValues(El: TRecordValues;
AContext: TConvertContext): TJSElement;
@ -3884,7 +4020,7 @@ begin
if El.ElseBranch<>nil then
begin
JSCaseEl:=SwitchEl.Cases.AddCase;
JSCaseEl.Body:=ConvertImplBlockElements(El.ElseBranch,AContext);
JSCaseEl.Body:=ConvertImplBlockElements(El.ElseBranch,AContext,false);
SwitchEl.TheDefault:=JSCaseEl;
end;
ok:=true;
@ -4465,12 +4601,6 @@ begin
until false;
end;
procedure TPasToJSConverter.SetTargetProcessor(const AValue: TPasToJsProcessor);
begin
if FTargetProcessor=AValue then Exit;
FTargetProcessor:=AValue;
end;
constructor TPasToJSConverter.Create;
begin
FOptions:=[coLowerCase];
@ -4497,6 +4627,8 @@ begin
FFuncNameSet_Reference:=DefaultFuncNameSet_Reference;
FFuncNameSet_SymDiffSet:=DefaultFuncNameSet_SymDiffSet;
FFuncNameSet_Union:=DefaultFuncNameSet_Union;
FFuncNameSpaceLeft:=DefaultFuncNameSpaceLeft;
FVarNameExceptObject:=DefaultVarNameExceptObject;
FVarNameImplementation:=DefaultVarNameImplementation;
FVarNameLoopEnd:=DefaultVarNameLoopEnd;
FVarNameModules:=DefaultVarNameModules;
@ -4638,14 +4770,14 @@ begin
end;
function TPasToJSConverter.ConvertBeginEndStatement(El: TPasImplBeginBlock;
AContext: TConvertContext): TJSElement;
AContext: TConvertContext; NilIfEmpty: boolean): TJSElement;
begin
Result:=ConvertImplBlockElements(El,AContext);
Result:=ConvertImplBlockElements(El,AContext,NilIfEmpty);
end;
function TPasToJSConverter.ConvertImplBlockElements(El: TPasImplBlock;
AContext: TConvertContext): TJSElement;
AContext: TConvertContext; NilIfEmpty: boolean): TJSElement;
var
First, Last: TJSStatementList;
@ -4655,7 +4787,12 @@ var
begin
if Not (Assigned(El.Elements) and (El.Elements.Count>0)) then
Result:=TJSEmptyBlockStatement(CreateElement(TJSEmptyBlockStatement,El))
begin
if NilIfEmpty then
Result:=nil
else
Result:=TJSEmptyBlockStatement(CreateElement(TJSEmptyBlockStatement,El));
end
else
begin
First:=nil;
@ -4708,7 +4845,7 @@ begin
Body:=FDS.AFunction.Body;
FuncContext:=TFunctionContext.Create(El,Body,AContext);
FuncContext.This:=AContext.GetThis;
Body.A:=ConvertImplBlockElements(El,FuncContext);
Body.A:=ConvertImplBlockElements(El,FuncContext,false);
end;
ok:=true;
finally
@ -4754,15 +4891,15 @@ begin
if El.FinallyExcept is TPasImplTryFinally then
begin
T:=TJSTryFinallyStatement(CreateElement(TJSTryFinallyStatement,El));
T.Block:=ConvertImplBlockElements(El,AContext);
T.BFinally:=ConvertImplBlockElements(El.FinallyExcept,AContext);
T.Block:=ConvertImplBlockElements(El,AContext,true);
T.BFinally:=ConvertImplBlockElements(El.FinallyExcept,AContext,true);
end
else
begin
T:=TJSTryCatchStatement(CreateElement(TJSTryCatchStatement,El));
T.Block:=ConvertImplBlockElements(El,AContext);
T.Block:=ConvertImplBlockElements(El,AContext,true);
if NeedExceptObject then
T.Ident:=TJSString(GetExceptionObjectName(AContext));
T.Ident:=TJSString(VarNameExceptObject);
//T.BCatch:=ConvertElement(El.FinallyExcept,AContext);
ExceptBlock:=El.FinallyExcept;
if (ExceptBlock.Elements.Count>0)
@ -4780,13 +4917,20 @@ begin
Last:=IfSt;
end;
if El.ElseBranch<>nil then
Last.BFalse:=ConvertImplBlockElements(El.ElseBranch,AContext);
Last.BFalse:=ConvertImplBlockElements(El.ElseBranch,AContext,true)
else
begin
// default else: throw exceptobject
Last.BFalse:=TJSThrowStatement(CreateElement(TJSThrowStatement,El));
TJSThrowStatement(Last.BFalse).A:=
CreateBuiltInIdentifierExpr(VarNameExceptObject);
end;
end
else
begin
if El.ElseBranch<>nil then
RaiseNotSupported(El.ElseBranch,AContext,20170205003014);
T.BCatch:=ConvertImplBlockElements(ExceptBlock,AContext);
T.BCatch:=ConvertImplBlockElements(ExceptBlock,AContext,true);
end;
end;
Result:=T;
@ -4925,7 +5069,7 @@ begin
// Pascal 'else' or 'otherwise' -> create JS "else{}"
if LastIfSt=nil then
RaiseNotSupported(SubEl,AContext,20161128120802,'case-of needs at least one case');
LastIfSt.BFalse:=ConvertImplBlockElements(El.ElseBranch,AContext);
LastIfSt.BFalse:=ConvertImplBlockElements(El.ElseBranch,AContext,true);
end
else
RaiseNotSupported(SubEl,AContext,20161128113055);
@ -5170,6 +5314,34 @@ begin
end;
end;
function TPasToJSConverter.CreateAssignStatement(LeftEl: TPasElement;
AssignContext: TAssignContext): TJSElement;
var
LHS: TJSElement;
AssignSt: TJSSimpleAssignStatement;
begin
Result:=nil;
LHS:=ConvertElement(LeftEl,AssignContext);
if AssignContext.Call<>nil then
begin
// has a setter -> right side was already added as parameter
if AssignContext.RightSide<>nil then
begin
LHS.Free;
RaiseInconsistency(20170207215447);
end;
Result:=LHS;
end
else
begin
AssignSt:=TJSSimpleAssignStatement(CreateElement(TJSSimpleAssignStatement,AssignContext.PasElement));
AssignSt.LHS:=LHS;
AssignSt.Expr:=AssignContext.RightSide;
AssignContext.RightSide:=nil;
Result:=AssignSt;
end;
end;
function TPasToJSConverter.ConvertImplBlock(El: TPasImplBlock;
AContext: TConvertContext): TJSElement;
@ -5182,7 +5354,7 @@ begin
else if (El.ClassType=TPasImplRepeatUntil) then
Result:=ConvertRepeatStatement(TPasImplRepeatUntil(El),AContext)
else if (El.ClassType=TPasImplBeginBlock) then
Result:=ConvertBeginEndStatement(TPasImplBeginBlock(El),AContext)
Result:=ConvertBeginEndStatement(TPasImplBeginBlock(El),AContext,true)
else if (El.ClassType=TInitializationSection) then
Result:=ConvertInitializationSection(TInitializationSection(El),AContext)
else if (El.ClassType=TFinalizationSection) then
@ -5295,7 +5467,7 @@ begin
if El.ExceptObject<>Nil then
E:=ConvertElement(El.ExceptObject,AContext)
else
E:=CreateBuiltInIdentifierExpr(GetExceptionObjectName(AContext));
E:=CreateBuiltInIdentifierExpr(VarNameExceptObject);
T:=TJSThrowStatement(CreateElement(TJSThrowStatement,El));
T.A:=E;
Result:=T;
@ -5430,9 +5602,7 @@ begin
try
C:=ConvertElement(El.ConditionExpr,AContext);
if Assigned(El.IfBranch) then
BThen:=ConvertElement(El.IfBranch,AContext)
else
BThen:=TJSEmptyBlockStatement(CreateElement(TJSEmptyBlockStatement,El));
BThen:=ConvertElement(El.IfBranch,AContext);
if Assigned(El.ElseBranch) then
BElse:=ConvertElement(El.ElseBranch,AContext);
ok:=true;
@ -5502,7 +5672,7 @@ begin
C:=ConvertElement(EL.ConditionExpr,AContext);
N:=TJSUnaryNotExpression(CreateElement(TJSUnaryNotExpression,EL.ConditionExpr));
N.A:=C;
B:=ConvertImplBlockElements(El,AContext);
B:=ConvertImplBlockElements(El,AContext,false);
ok:=true;
finally
if not ok then
@ -5734,11 +5904,6 @@ begin
begin
B:=ConvertElement(El.Body,AContext);
AddToStatementList(FirstSt,LastSt,B,El.Body);
end
else
begin
B:=TJSEmptyBlockStatement(CreateElement(TJSEmptyBlockStatement,El));
AddToStatementList(FirstSt,LastSt,B,El);
end;
Result:=FirstSt;
finally
@ -5779,15 +5944,6 @@ begin
end;
end;
function TPasToJSConverter.GetExceptionObjectName(AContext: TConvertContext
): string;
begin
if AContext=nil then ;
Result:=DefaultJSExceptionObject; // use the same as the FPC RTL
if UseLowerCase then
Result:=lowercase(Result);
end;
function TPasToJSConverter.IsElementUsed(El: TPasElement): boolean;
begin
if Assigned(OnIsElementUsed) then
@ -6789,7 +6945,7 @@ begin
// create "T.isPrototypeOf(exceptObject)"
Call:=CreateCallExpression(El);
Call.Expr:=DotExpr;
Call.Args.Elements.AddElement.Expr:=CreateBuiltInIdentifierExpr(GetExceptionObjectName(AContext));
Call.Args.Elements.AddElement.Expr:=CreateBuiltInIdentifierExpr(VarNameExceptObject);
IfSt.Cond:=Call;
if El.VarEl<>nil then
@ -6803,11 +6959,11 @@ begin
VarDecl:=TJSVarDeclaration(CreateElement(TJSVarDeclaration,El));
V.A:=VarDecl;
VarDecl.Name:=TransformVariableName(El,El.VariableName,AContext);
VarDecl.Init:=CreateBuiltInIdentifierExpr(GetExceptionObjectName(AContext));
VarDecl.Init:=CreateBuiltInIdentifierExpr(VarNameExceptObject);
// add statements
AddToStatementList(ListFirst,ListLast,ConvertElement(El.Body,AContext),El);
end
else
else if El.Body<>nil then
// add statements
IfSt.BTrue:=ConvertElement(El.Body,AContext);
@ -7360,7 +7516,6 @@ begin
Result:=true;
if aName=VarNameModules then exit;
if aName=VarNameRTL then exit;
if aName=GetExceptionObjectName(nil) then exit;
l:=low(JSReservedWords);
r:=high(JSReservedWords);
@ -7387,7 +7542,10 @@ begin
aContext:=TRootContext.Create(El,nil,nil);
try
aContext.Resolver:=Resolver;
Result:=ConvertElement(El,aContext);
if (El.ClassType=TPasImplBeginBlock) then
Result:=ConvertBeginEndStatement(TPasImplBeginBlock(El),AContext,false)
else
Result:=ConvertElement(El,aContext);
finally
FreeAndNil(aContext);
end;

View File

@ -187,8 +187,8 @@ begin
R:=TPasImplIfElse.Create('',Nil);
R.ConditionExpr:=CreateCondition;
E:=TJSIfStatement(Convert(R,TJSIfStatement));
AssertEquals('If branch is empty block statement',TJSEmptyBlockStatement,E.btrue.ClassType);
AssertNull('No else branch',E.bfalse);
AssertNull('If branch is empty',E.BTrue);
AssertNull('No else branch',E.BFalse);
AssertIdentifier('Left hand side OK',E.Cond,'a');
end;
@ -668,7 +668,7 @@ begin
// Convert
El:=TJSTryCatchStatement(Convert(T,TJSTryCatchStatement));
// check "catch(exceptobject)"
AssertEquals('Correct exception object name',lowercase(DefaultJSExceptionObject),String(El.Ident));
AssertEquals('Correct exception object name',lowercase(DefaultVarNameExceptObject),String(El.Ident));
// check "if"
I:=TJSIfStatement(AssertElement('On block is if',TJSIfStatement,El.BCatch));
// check if condition "exception.isPrototypeOf(exceptobject)"
@ -679,14 +679,14 @@ begin
AssertNotNull('args of exception.isPrototypeOf(exceptobject)',IC.Args);
AssertEquals('args of exception.isPrototypeOf(exceptobject)',1,IC.Args.Elements.Count);
ExObj:=IC.Args.Elements.Elements[0].Expr;
Assertidentifier('arg of exception.isPrototypeOf(exceptobject)',ExObj,lowercase(DefaultJSExceptionObject));
Assertidentifier('arg of exception.isPrototypeOf(exceptobject)',ExObj,lowercase(DefaultVarNameExceptObject));
// check statement "var e = exceptobject;"
L:=AssertListStatement('On block is always a list',I.BTrue);
writeln('TTestStatementConverter.TestTryExceptStatementOnE ',L.A.ClassName);
VS:=TJSVariableStatement(AssertElement('First statement in list is a var statement',TJSVariableStatement,L.A));
V:=TJSVarDeclaration(AssertElement('var declaration e=ExceptObject',TJSVarDeclaration,VS.A));
AssertEquals('Variable name is identifier in On A : Ex do','e',V.Name);
Assertidentifier('Variable init is exception object',V.Init,lowercase(DefaultJSExceptionObject));
Assertidentifier('Variable init is exception object',V.Init,lowercase(DefaultVarNameExceptObject));
// check "b = c;"
AssertAssignStatement('Original assignment in second statement',L.B,'b','c');
end;
@ -727,7 +727,7 @@ begin
// Convert
El:=TJSTryCatchStatement(Convert(T,TJSTryCatchStatement));
// check "catch(exceptobject)"
AssertEquals('Correct exception object name',lowercase(DefaultJSExceptionObject),String(El.Ident));
AssertEquals('Correct exception object name',lowercase(DefaultVarNameExceptObject),String(El.Ident));
// check "if"
I:=TJSIfStatement(AssertElement('On block is if',TJSIfStatement,El.BCatch));
// check if condition "exception.isPrototypeOf(exceptobject)"
@ -738,16 +738,16 @@ begin
AssertNotNull('args of exception.isPrototypeOf(ExceptObject)',IC.Args);
AssertEquals('args of exception.isPrototypeOf(ExceptObject)',1,IC.Args.Elements.Count);
ExObj:=IC.Args.Elements.Elements[0].Expr;
Assertidentifier('arg of exception.isPrototypeOf(ExceptObject)',ExObj,lowercase(DefaultJSExceptionObject));
Assertidentifier('arg of exception.isPrototypeOf(ExceptObject)',ExObj,lowercase(DefaultVarNameExceptObject));
// check statement "var e = exceptobject;"
L:=AssertListStatement('On block is always a list',I.BTrue);
writeln('TTestStatementConverter.TestTryExceptStatementOnE ',L.A.ClassName);
VS:=TJSVariableStatement(AssertElement('First statement in list is a var statement',TJSVariableStatement,L.A));
V:=TJSVarDeclaration(AssertElement('var declaration e=ExceptObject',TJSVarDeclaration,VS.A));
AssertEquals('Variable name is identifier in On A : Ex do','e',V.Name);
Assertidentifier('Variable init is exception object',V.Init,lowercase(DefaultJSExceptionObject));
Assertidentifier('Variable init is exception object',V.Init,lowercase(DefaultVarNameExceptObject));
R:=TJSThrowStatement(AssertElement('On block is throw statement',TJSThrowStatement,L.B));
Assertidentifier('R expression is original exception ',R.A,lowercase(DefaultJSExceptionObject));
Assertidentifier('R expression is original exception ',R.A,lowercase(DefaultVarNameExceptObject));
end;
Procedure TTestStatementConverter.TestVariableStatement;

View File

@ -164,6 +164,7 @@ type
Procedure TestString_Compare;
Procedure TestString_SetLength;
Procedure TestString_CharAt;
Procedure TestStr;
// alias types
Procedure TestAliasTypeRef;
@ -211,6 +212,7 @@ type
Procedure TestSet_Property;
// statements
Procedure TestNestBegin;
Procedure TestIncDec;
Procedure TestAssignments;
Procedure TestArithmeticOperators1;
@ -458,7 +460,7 @@ begin
+' Col='+IntToStr(CurEngine.Scanner.CurColumn)
+' Line="'+CurEngine.Scanner.CurLine+'"'
);
raise E;
Fail(E.Message);
end;
end;
//writeln('TTestModule.OnPasResolverFindUnit END ',CurUnitName);
@ -467,7 +469,7 @@ begin
end;
end;
writeln('TTestModule.OnPasResolverFindUnit missing unit "',aUnitName,'"');
raise Exception.Create('can''t find unit "'+aUnitName+'"');
Fail('can''t find unit "'+aUnitName+'"');
end;
procedure TCustomTestModule.SetUp;
@ -547,7 +549,7 @@ begin
+' '+E.Filename+'('+IntToStr(E.Row)+','+IntToStr(E.Column)+')'
+' Line="'+Scanner.CurLine+'"'
);
raise E;
Fail(E.Message);
end;
on E: EPasResolve do
begin
@ -556,12 +558,12 @@ begin
writeln('ERROR: TTestModule.ParseModule PasResolver: '+E.ClassName+':'+E.Message
+' '+E.PasElement.SourceFilename
+'('+IntToStr(Row)+','+IntToStr(Col)+')');
raise E;
Fail(E.Message);
end;
on E: Exception do
begin
writeln('ERROR: TTestModule.ParseModule Exception: '+E.ClassName+':'+E.Message);
raise E;
Fail(E.Message);
end;
end;
AssertNotNull('Module resulted in Module',FModule);
@ -609,7 +611,7 @@ function TCustomTestModule.AddModule(aFilename: string
begin
//writeln('TTestModuleConverter.AddModule ',aFilename);
if FindModuleWithFilename(aFilename)<>nil then
raise Exception.Create('TTestModuleConverter.AddModule: file "'+aFilename+'" already exists');
Fail('TTestModuleConverter.AddModule: file "'+aFilename+'" already exists');
Result:=TTestEnginePasResolver.Create;
Result.Filename:=aFilename;
Result.AddObjFPCBuiltInIdentifiers([btChar,btString,btLongint,btInt64,btBoolean,btDouble]);
@ -695,14 +697,14 @@ begin
writeln('ERROR: TTestModule.ConvertModule Scanner: '+E.ClassName+':'+E.Message
+' '+Scanner.CurFilename
+'('+IntToStr(Scanner.CurRow)+','+IntToStr(Scanner.CurColumn)+')');
raise E;
Fail(E.Message);
end;
on E: EParserError do begin
WriteSource(Scanner.CurFilename,Scanner.CurRow,Scanner.CurColumn);
writeln('ERROR: TTestModule.ConvertModule Parser: '+E.ClassName+':'+E.Message
+' '+Scanner.CurFilename
+'('+IntToStr(Scanner.CurRow)+','+IntToStr(Scanner.CurColumn)+')');
raise E;
Fail(E.Message);
end;
on E: EPasResolve do
begin
@ -711,7 +713,7 @@ begin
writeln('ERROR: TTestModule.ConvertModule PasResolver: '+E.ClassName+':'+E.Message
+' '+E.PasElement.SourceFilename
+'('+IntToStr(Row)+','+IntToStr(Col)+')');
raise E;
Fail(E.Message);
end;
on E: EPas2JS do
begin
@ -725,12 +727,12 @@ begin
end
else
writeln('ERROR: TTestModule.ConvertModule Exception: '+E.ClassName+':'+E.Message);
raise E;
Fail(E.Message);
end;
on E: Exception do
begin
writeln('ERROR: TTestModule.ConvertModule Exception: '+E.ClassName+':'+E.Message);
raise E;
Fail(E.Message);
end;
end;
FJSSource:=TStringList.Create;
@ -1526,8 +1528,7 @@ begin
' this.FuncA(Bar);',
'};',
'this.FuncA = function (Bar) {',
' if (Bar == 3) {',
' };',
' if (Bar == 3);',
'};'
]),
LinesToStr([
@ -1563,8 +1564,7 @@ begin
' FuncB(i);',
' };',
' function FuncB(i) {',
' if (i == 3) {',
' };',
' if (i == 3);',
' };',
' FuncC(4);',
'};'
@ -1628,12 +1628,9 @@ begin
'this.i = 0;'
]),
LinesToStr([
'if (this.Func2()) {',
'};',
'if (this.i == this.Func1()) {',
'};',
'if (this.i == this.Func1()) {',
'};'
'if (this.Func2());',
'if (this.i == this.Func1());',
'if (this.i == this.Func1());'
]));
end;
@ -2230,6 +2227,7 @@ begin
Add('var');
Add(' e: TMyEnum;');
Add(' i: longint;');
Add(' s: string;');
Add('begin');
Add(' i:=ord(red);');
Add(' i:=ord(green);');
@ -2244,6 +2242,9 @@ begin
Add(' e:=succ(e);');
Add(' e:=tmyenum(1);');
Add(' e:=tmyenum(i);');
Add(' s:=str(e);');
Add(' str(e,s)');
Add(' s:=str(e:3);');
ConvertProgram;
CheckSource('TestEnumNumber',
LinesToStr([ // statements
@ -2254,7 +2255,8 @@ begin
' Green:1',
' };',
'this.e = 0;',
'this.i = 0;'
'this.i = 0;',
'this.s = "";'
]),
LinesToStr([
'this.i=this.TMyEnum.Red;',
@ -2270,6 +2272,9 @@ begin
'this.e=this.e+1;',
'this.e=1;',
'this.e=this.i;',
'this.s = this.TMyEnum[this.e];',
'this.s = this.TMyEnum[this.e];',
'this.s = rtl.spaceLeft(this.TMyEnum[this.e], 3);',
'']));
end;
@ -2687,6 +2692,23 @@ begin
'']));
end;
procedure TTestModule.TestNestBegin;
begin
StartProgram(false);
Add('begin');
Add(' begin');
Add(' begin');
Add(' end;');
Add(' begin');
Add(' if true then ;');
Add(' end;');
Add(' end;');
ConvertProgram;
CheckSource('TestNestBegin',
'',
'if (true) ;');
end;
procedure TTestModule.TestUnitImplVars;
begin
StartUnit(false);
@ -3103,6 +3125,55 @@ begin
'']));
end;
procedure TTestModule.TestStr;
begin
StartProgram(false);
Add('var');
Add(' b: boolean;');
Add(' i: longint;');
Add(' d: double;');
Add(' s: string;');
Add('begin');
Add(' s:=str(b);');
Add(' s:=str(i);');
Add(' s:=str(d);');
Add(' s:=str(i,i);');
Add(' s:=str(i:3);');
Add(' s:=str(d:3:2);');
Add(' s:=str(i:4,i);');
Add(' s:=str(i,i:5);');
Add(' s:=str(i:4,i:5);');
Add(' str(b,s);');
Add(' str(i,s);');
Add(' str(d,s);');
Add(' str(i:3,s);');
Add(' str(d:3:2,s);');
ConvertProgram;
CheckSource('TestStr',
LinesToStr([ // statements
'this.b = false;',
'this.i = 0;',
'this.d = 0.0;',
'this.s = "";',
'']),
LinesToStr([ // this.$main
'this.s = ""+this.b;',
'this.s = ""+this.i;',
'this.s = ""+this.d;',
'this.s = (""+this.i)+this.i;',
'this.s = rtl.spaceLeft(""+this.i,3);',
'this.s = rtl.spaceLeft(this.d.toFixed(2),3);',
'this.s = rtl.spaceLeft("" + this.i, 4) + this.i;',
'this.s = ("" + this.i) + rtl.spaceLeft("" + this.i, 5);',
'this.s = rtl.spaceLeft("" + this.i, 4) + rtl.spaceLeft("" + this.i, 5);',
'this.s = ""+this.b;',
'this.s = ""+this.i;',
'this.s = ""+this.d;',
'this.s = rtl.spaceLeft(""+this.i,3);',
'this.s = rtl.spaceLeft(this.d.toFixed(2),3);',
'']));
end;
procedure TTestModule.TestProcTwoArgs;
begin
StartProgram(false);
@ -3290,7 +3361,7 @@ begin
' var $loopend1 = 2;',
' for (this.vI = 1; this.vI <= $loopend1; this.vI++);',
' if(this.vI>$loopend1)this.vI--;',
' if (this.vI==3){} ;'
' if (this.vI==3) ;'
]));
end;
@ -3389,7 +3460,7 @@ begin
LinesToStr([ // this.$main
'this.vI = 1;',
'if (vI==1) {',
'vI=2;',
' vI=2;',
'}',
'if (vI==2){ vI=3; }',
';',
@ -3452,6 +3523,11 @@ begin
Add(' else');
Add(' vi:=5');
Add(' end;');
Add(' try');
Add(' VI:=6;');
Add(' except');
Add(' on einvalidcast do ;');
Add(' end;');
ConvertProgram;
CheckSource('TestTryExcept',
LinesToStr([ // statements
@ -3479,21 +3555,27 @@ begin
'};',
'try {',
' this.vI = 3;',
'} catch ('+DefaultJSExceptionObject+') {',
' throw '+DefaultJSExceptionObject+';',
'} catch ('+DefaultVarNameExceptObject+') {',
' throw '+DefaultVarNameExceptObject+';',
'};',
'try {',
' this.vI = 4;',
'} catch ('+DefaultJSExceptionObject+') {',
' if (this.EInvalidCast.isPrototypeOf('+DefaultJSExceptionObject+')) throw '+DefaultJSExceptionObject,
' else if (this.Exception.isPrototypeOf('+DefaultJSExceptionObject+')) {',
' var E = '+DefaultJSExceptionObject+';',
'} catch ('+DefaultVarNameExceptObject+') {',
' if (this.EInvalidCast.isPrototypeOf('+DefaultVarNameExceptObject+')) throw '+DefaultVarNameExceptObject,
' else if (this.Exception.isPrototypeOf('+DefaultVarNameExceptObject+')) {',
' var E = '+DefaultVarNameExceptObject+';',
' if (E.Msg == "") throw E;',
' } else {',
' this.vI = 5;',
' }',
'};'
]));
'};',
'try {',
' this.vI = 6;',
'} catch ('+DefaultVarNameExceptObject+') {',
' if (this.EInvalidCast.isPrototypeOf('+DefaultVarNameExceptObject+')){' ,
' } else throw '+DefaultVarNameExceptObject,
'};',
'']));
end;
procedure TTestModule.TestCaseOf;
@ -3614,8 +3696,7 @@ begin
]),
LinesToStr([ // this.$main
'var $tmp1 = this.vI;',
'if (($tmp1 >= 1) && ($tmp1 <= 3)) this.vI = 14 else if (($tmp1 == 4) || ($tmp1 == 5)) this.vI = 16 else if ((($tmp1 >= 6) && ($tmp1 <= 7)) || (($tmp1 >= 9) && ($tmp1 <= 10))) {} else {',
'};'
'if (($tmp1 >= 1) && ($tmp1 <= 3)) this.vI = 14 else if (($tmp1 == 4) || ($tmp1 == 5)) this.vI = 16 else if ((($tmp1 >= 6) && ($tmp1 <= 7)) || (($tmp1 >= 9) && ($tmp1 <= 10))) ;'
]));
end;
@ -3674,8 +3755,8 @@ begin
]),
LinesToStr([ // this.$main
'this.Arr = [];',
'if (this.Arr.length == 0) {};',
'if (0 == this.Arr.length) {};',
'if (this.Arr.length == 0);',
'if (0 == this.Arr.length);',
'this.DoIt([],[]);',
'']));
end;
@ -3714,8 +3795,8 @@ begin
]),
LinesToStr([ // this.$main
'this.Arr2 = [];',
'if (this.Arr2.length == 0) {};',
'if (0 == this.Arr2.length) {};',
'if (this.Arr2.length == 0);',
'if (0 == this.Arr2.length);',
'this.i = 0;',
'this.i = 0;',
'this.i = this.Arr2.length-1;',
@ -4735,8 +4816,7 @@ begin
'this.oO = this.TObject.$create("Create");',
'this.oA = this.TClassA.$create("Create");',
'this.oB = this.TClassB.$create("Create");',
'if (this.TClassA.isPrototypeOf(this.oO)) {',
'};',
'if (this.TClassA.isPrototypeOf(this.oO));',
'this.oB = rtl.as(this.oO, this.TClassB);',
'rtl.as(this.oO, this.TClassB).ProcB();'
]));
@ -5065,7 +5145,7 @@ begin
LinesToStr([ // this.$main
'this.Obj = this.TObject.$create("Create");',
'this.TObject.vI = 3;',
'if (this.TObject.vI == 4){};',
'if (this.TObject.vI == 4);',
'this.TObject.Sub=null;',
'this.Obj.$class.Sub=null;',
'this.Obj.Sub.$class.Sub=null;',
@ -5225,8 +5305,7 @@ begin
]),
LinesToStr([ // this.$main
'this.Obj.Fy = this.Obj.Fx + 1;',
'if (this.Obj.GetInt() == 2) {',
'};',
'if (this.Obj.GetInt() == 2);',
'this.Obj.SetInt(this.Obj.GetInt() + 2);',
'this.Obj.SetInt(this.Obj.Fx);'
]));
@ -5297,13 +5376,11 @@ begin
]),
LinesToStr([ // this.$main
'this.TObject.Fy = this.TObject.Fx + 1;',
'if (this.TObject.GetInt() == 2) {',
'};',
'if (this.TObject.GetInt() == 2);',
'this.TObject.SetInt(this.TObject.GetInt() + 2);',
'this.TObject.SetInt(this.TObject.Fx);',
'this.Obj.$class.Fy = this.Obj.Fx + 1;',
'if (this.Obj.$class.GetInt() == 2) {',
'};',
'if (this.Obj.$class.GetInt() == 2);',
'this.Obj.$class.SetInt(this.Obj.$class.GetInt() + 2);',
'this.Obj.$class.SetInt(this.Obj.Fx);'
]));
@ -5568,8 +5645,7 @@ begin
'this.b = false;'
]),
LinesToStr([ // this.$main
'if (this.Obj != null) {',
'};',
'if (this.Obj != null);',
'this.b = (this.Obj != null) || false;'
]));
end;
@ -5921,24 +5997,18 @@ begin
'this.ProcA = function (A) {',
' A.set(null);',
' A.set(A.get());',
' if (A.get() == null) {',
' };',
' if (null == A.get()) {',
' };',
' if (A.get() == null);',
' if (null == A.get());',
'};',
'this.ProcB = function (A) {',
' A.set(null);',
' A.set(A.get());',
' if (A.get() == null) {',
' };',
' if (null == A.get()) {',
' };',
' if (A.get() == null);',
' if (null == A.get());',
'};',
'this.ProcC = function (A) {',
' if (A == null) {',
' };',
' if (null == A) {',
' };',
' if (A == null);',
' if (null == A);',
'};',
'this.o = null;',
'']),

View File

@ -529,8 +529,7 @@ begin
'this.o = null;',
'']),
LinesToStr([
'if (this.o.FFoo){',
'};',
'if (this.o.FFoo);',
'']));
end;
@ -566,8 +565,7 @@ begin
'this.o = null;',
'']),
LinesToStr([
'if (this.o.GetFoo()){',
'};',
'if (this.o.GetFoo()) ;',
'']));
end;