diff --git a/packages/pastojs/src/fppas2js.pp b/packages/pastojs/src/fppas2js.pp index 508f1c87cd..beb731a62b 100644 --- a/packages/pastojs/src/fppas2js.pp +++ b/packages/pastojs/src/fppas2js.pp @@ -140,7 +140,7 @@ Works: - option to write numbers instead of variables - ord(), low(), high(), pred(), succ() - type cast alias to enumtype - - type cast number to enumtype + - type cast number to enumtype, enumtype to number - const aliasname = enumvalue - sets - set of enum @@ -1284,8 +1284,7 @@ type Function ConvertBuiltIn_Chr(El: TParamsExpr; AContext: TConvertContext): TJSElement; virtual; Function ConvertBuiltIn_Ord(El: TParamsExpr; AContext: TConvertContext): TJSElement; virtual; Function ConvertBuiltIn_LowHigh(El: TParamsExpr; AContext: TConvertContext; IsLow: boolean): TJSElement; virtual; - Function ConvertBuiltIn_Pred(El: TParamsExpr; AContext: TConvertContext): TJSElement; virtual; - Function ConvertBuiltIn_Succ(El: TParamsExpr; AContext: TConvertContext): TJSElement; virtual; + Function ConvertBuiltIn_PredSucc(El: TParamsExpr; AContext: TConvertContext; IsPred: boolean): TJSElement; virtual; Function ConvertBuiltIn_StrProc(El: TParamsExpr; AContext: TConvertContext): TJSElement; virtual; Function ConvertBuiltIn_StrFunc(El: TParamsExpr; AContext: TConvertContext): TJSElement; virtual; Function ConvertBuiltInStrParam(El: TPasExpr; AContext: TConvertContext; IsStrFunc, IsFirst: boolean): TJSElement; virtual; @@ -5652,8 +5651,8 @@ begin bfOrd: Result:=ConvertBuiltIn_Ord(El,AContext); bfLow: Result:=ConvertBuiltIn_LowHigh(El,AContext,true); bfHigh: Result:=ConvertBuiltIn_LowHigh(El,AContext,false); - bfPred: Result:=ConvertBuiltIn_Pred(El,AContext); - bfSucc: Result:=ConvertBuiltIn_Succ(El,AContext); + bfPred: Result:=ConvertBuiltIn_PredSucc(El,AContext,true); + bfSucc: Result:=ConvertBuiltIn_PredSucc(El,AContext,false); bfStrProc: Result:=ConvertBuiltIn_StrProc(El,AContext); bfStrFunc: Result:=ConvertBuiltIn_StrFunc(El,AContext); bfConcatArray: Result:=ConvertBuiltIn_ConcatArray(El,AContext); @@ -6724,6 +6723,7 @@ var SubParams: TParamsExpr; SubParamJS: TJSElement; Minus: TJSAdditiveExpressionMinus; + Add: TJSAdditiveExpressionPlus; begin Result:=nil; if AContext.Resolver=nil then @@ -6773,6 +6773,17 @@ begin Result:=Call; exit; end + else if ParamResolved.BaseType in btAllBooleans then + begin + // ord(bool) -> bool+0 + Result:=ConvertElement(Param,AContext); + // Note: convert Param first, as it might raise an exception + Add:=TJSAdditiveExpressionPlus(CreateElement(TJSAdditiveExpressionPlus,El)); + Add.A:=Result; + Add.B:=CreateLiteralNumber(El,0); + Result:=Add; + exit; + end else if ParamResolved.BaseType=btContext then begin if ParamResolved.TypeEl.ClassType=TPasEnumType then @@ -6970,62 +6981,47 @@ begin AContext.Resolver.GetResolverResultDescription(ResolvedEl)],Param); end; -function TPasToJSConverter.ConvertBuiltIn_Pred(El: TParamsExpr; - AContext: TConvertContext): TJSElement; +function TPasToJSConverter.ConvertBuiltIn_PredSucc(El: TParamsExpr; + AContext: TConvertContext; IsPred: boolean): TJSElement; // pred(enumvalue) -> enumvalue-1 +// succ(enumvalue) -> enumvalue+1 var ResolvedEl: TPasResolverResult; Param: TPasExpr; V: TJSElement; - Expr: TJSAdditiveExpressionMinus; + Expr: TJSAdditiveExpression; begin Result:=nil; if AContext.Resolver=nil then RaiseInconsistency(20170210120648); Param:=El.Params[0]; AContext.Resolver.ComputeElement(Param,ResolvedEl,[]); - if (ResolvedEl.BaseType=btContext) - and (ResolvedEl.TypeEl.ClassType=TPasEnumType) then + if (ResolvedEl.BaseType in btAllJSInteger) + or ((ResolvedEl.BaseType=btContext) + and (ResolvedEl.TypeEl.ClassType=TPasEnumType)) then begin V:=ConvertElement(Param,AContext); - Expr:=TJSAdditiveExpressionMinus(CreateElement(TJSAdditiveExpressionMinus,El)); + if IsPred then + Expr:=TJSAdditiveExpressionMinus(CreateElement(TJSAdditiveExpressionMinus,El)) + else + Expr:=TJSAdditiveExpressionPlus(CreateElement(TJSAdditiveExpressionPlus,El)); Expr.A:=V; Expr.B:=CreateLiteralNumber(El,1); Result:=Expr; exit; + end + else if ResolvedEl.BaseType in btAllJSBooleans then + begin + if IsPred then + Result:=CreateLiteralBoolean(El,false) + else + Result:=CreateLiteralBoolean(El,true); + exit; end; DoError(20170210120039,nExpectedXButFoundY,sExpectedXButFoundY,['enum', AContext.Resolver.GetResolverResultDescription(ResolvedEl)],Param); end; -function TPasToJSConverter.ConvertBuiltIn_Succ(El: TParamsExpr; - AContext: TConvertContext): TJSElement; -// succ(enumvalue) -> enumvalue+1 -var - ResolvedEl: TPasResolverResult; - Param: TPasExpr; - V: TJSElement; - Expr: TJSAdditiveExpressionPlus; -begin - Result:=nil; - if AContext.Resolver=nil then - RaiseInconsistency(20170210120645); - Param:=El.Params[0]; - AContext.Resolver.ComputeElement(Param,ResolvedEl,[]); - if (ResolvedEl.BaseType=btContext) - and (ResolvedEl.TypeEl.ClassType=TPasEnumType) then - begin - V:=ConvertElement(Param,AContext); - Expr:=TJSAdditiveExpressionPlus(CreateElement(TJSAdditiveExpressionPlus,El)); - Expr.A:=V; - Expr.B:=CreateLiteralNumber(El,1); - Result:=Expr; - exit; - end; - DoError(20170210120626,nExpectedXButFoundY,sExpectedXButFoundY,['enum', - AContext.Resolver.GetResolverResultDescription(ResolvedEl)],Param); -end; - function TPasToJSConverter.ConvertBuiltIn_StrProc(El: TParamsExpr; AContext: TConvertContext): TJSElement; // convert 'str(value,aString)' to 'aString = ' @@ -11047,6 +11043,10 @@ begin Call.Expr:=CreateDotExpression(Expr,Result,CreatePrimitiveDotExpr('charCodeAt',Expr)); Result:=Call; end + else if ExprResolved.BaseType in btAllJSInteger then + begin + // ok + end else if ExprResolved.BaseType=btContext then begin if ExprResolved.TypeEl.ClassType=TPasEnumType then @@ -11055,7 +11055,12 @@ begin RaiseNotSupported(Expr,AContext,20170415191933); end else + begin + {$IFDEF VerbosePas2JS} + writeln('TPasToJSConverter.CreateSetLiteralElement ',GetResolverResultDbg(ExprResolved)); + {$ENDIF} RaiseNotSupported(Expr,AContext,20170415191822); + end; end; end; diff --git a/packages/pastojs/tests/tcmodules.pas b/packages/pastojs/tests/tcmodules.pas index 1837503e4b..2848de6d9f 100644 --- a/packages/pastojs/tests/tcmodules.pas +++ b/packages/pastojs/tests/tcmodules.pas @@ -275,6 +275,7 @@ type Procedure TestSet_BooleanFail; Procedure TestSet_ConstEnum; Procedure TestSet_ConstChar; + Procedure TestSet_ConstInt; // statements Procedure TestNestBegin; @@ -3025,18 +3026,24 @@ begin Add(' e: TMyEnum;'); Add(' i: longint;'); Add(' s: string;'); + Add(' b: boolean;'); Add('begin'); Add(' i:=ord(red);'); Add(' i:=ord(green);'); Add(' i:=ord(e);'); + Add(' i:=ord(b);'); Add(' e:=low(tmyenum);'); Add(' e:=low(e);'); + Add(' b:=low(boolean);'); Add(' e:=high(tmyenum);'); Add(' e:=high(e);'); + Add(' b:=high(boolean);'); Add(' e:=pred(green);'); Add(' e:=pred(e);'); + Add(' b:=pred(b);'); Add(' e:=succ(red);'); Add(' e:=succ(e);'); + Add(' b:=succ(b);'); Add(' e:=tmyenum(1);'); Add(' e:=tmyenum(i);'); Add(' s:=str(e);'); @@ -3055,20 +3062,26 @@ begin ' };', 'this.e = 0;', 'this.i = 0;', - 'this.s = "";' - ]), + 'this.s = "";', + 'this.b = false;', + '']), LinesToStr([ '$mod.i=$mod.TMyEnum.Red;', '$mod.i=$mod.TMyEnum.Green;', '$mod.i=$mod.e;', + '$mod.i=$mod.b+0;', '$mod.e=$mod.TMyEnum.Red;', '$mod.e=$mod.TMyEnum.Red;', + '$mod.b=false;', '$mod.e=$mod.TMyEnum.Green;', '$mod.e=$mod.TMyEnum.Green;', + '$mod.b=true;', '$mod.e=$mod.TMyEnum.Green-1;', '$mod.e=$mod.e-1;', + '$mod.b=false;', '$mod.e=$mod.TMyEnum.Red+1;', '$mod.e=$mod.e+1;', + '$mod.b=true;', '$mod.e=1;', '$mod.e=$mod.i;', '$mod.s = $mod.TMyEnum[$mod.e];', @@ -3657,6 +3670,7 @@ begin ' if blue in teAny then;', ' if blue in teAny+[e] then;', ' if blue in teAny+teRedBlue then;', + ' if e in [red,blue] then;', ' s:=teAny;', ' s:=teAny+[e];', ' s:=[e]+teAny;', @@ -3683,6 +3697,7 @@ begin 'if ($mod.TEnum.blue in $mod.teAny) ;', 'if ($mod.TEnum.blue in rtl.unionSet($mod.teAny, rtl.createSet($mod.e))) ;', 'if ($mod.TEnum.blue in rtl.unionSet($mod.teAny, $mod.teRedBlue)) ;', + 'if ($mod.e in rtl.createSet($mod.TEnum.red, $mod.TEnum.blue)) ;', '$mod.s = rtl.refSet($mod.teAny);', '$mod.s = rtl.unionSet($mod.teAny, rtl.createSet($mod.e));', '$mod.s = rtl.unionSet(rtl.createSet($mod.e), $mod.teAny);', @@ -3725,6 +3740,36 @@ begin ''])); end; +procedure TTestModule.TestSet_ConstInt; +begin + StartProgram(false); + Add([ + 'const', + ' Months = [1..12];', + ' Mirror = [-12..-1]+Months;', + 'var', + ' i: smallint;', + 'begin', + ' if 3 in Months then;', + ' if i in Months+[i] then;', + ' if i in Months+Mirror then;', + ' if i in [4..6,8] then;', + '']); + ConvertProgram; + CheckSource('TestSet_ConstInt', + LinesToStr([ // statements + 'this.Months = rtl.createSet(null, 1, 12);', + 'this.Mirror = rtl.unionSet(rtl.createSet(null, -12, -1), $mod.Months);', + 'this.i = 0;', + '']), + LinesToStr([ + 'if (3 in $mod.Months) ;', + 'if ($mod.i in rtl.unionSet($mod.Months, rtl.createSet($mod.i))) ;', + 'if ($mod.i in rtl.unionSet($mod.Months, $mod.Mirror)) ;', + 'if ($mod.i in rtl.createSet(null, 4, 6, 8)) ;', + ''])); +end; + procedure TTestModule.TestNestBegin; begin StartProgram(false);