Przeglądaj źródła

pastojs: fixed a div b<0

mattias 4 lat temu
rodzic
commit
7f101cc3bb

+ 39 - 30
compiler/packages/pastojs/src/fppas2js.pp

@@ -665,6 +665,7 @@ type
     pbifnSet_Union,
     pbifnSet_Union,
     pbifnSpaceLeft,
     pbifnSpaceLeft,
     pbifnStringSetLength,
     pbifnStringSetLength,
+    pbifnTrunc, // rtl.trunc
     pbifnUnitInit,
     pbifnUnitInit,
     pbivnExceptObject,
     pbivnExceptObject,
     pbivnIntfExprRefs,
     pbivnIntfExprRefs,
@@ -830,6 +831,7 @@ const
     'unionSet', // rtl.unionSet +
     'unionSet', // rtl.unionSet +
     'spaceLeft', // rtl.spaceLeft
     'spaceLeft', // rtl.spaceLeft
     'strSetLength', // rtl.strSetLength
     'strSetLength', // rtl.strSetLength
+    'trunc', // pbifnTrunc
     '$init',
     '$init',
     '$e',
     '$e',
     '$ir',
     '$ir',
@@ -1783,7 +1785,7 @@ type
     // simple JS expressions
     // simple JS expressions
     Function CreateMulNumber(El: TPasElement; JS: TJSElement; n: TMaxPrecInt): TJSElement; virtual;
     Function CreateMulNumber(El: TPasElement; JS: TJSElement; n: TMaxPrecInt): TJSElement; virtual;
     Function CreateDivideNumber(El: TPasElement; JS: TJSElement; n: TMaxPrecInt): TJSElement; virtual;
     Function CreateDivideNumber(El: TPasElement; JS: TJSElement; n: TMaxPrecInt): TJSElement; virtual;
-    Function CreateMathFloor(El: TPasElement; JS: TJSElement): TJSElement; virtual;
+    Function CreateTruncFloor(El: TPasElement; JS: TJSElement; FloorAndCeil: boolean): TJSElement; virtual;
     Function CreateDotNameExpr(PosEl: TPasElement; MExpr: TJSElement;
     Function CreateDotNameExpr(PosEl: TPasElement; MExpr: TJSElement;
       const aName: TJSString): TJSDotMemberExpression; virtual;
       const aName: TJSString): TJSDotMemberExpression; virtual;
     Function CreateDotExpression(aParent: TPasElement; Left, Right: TJSElement;
     Function CreateDotExpression(aParent: TPasElement; Left, Right: TJSElement;
@@ -7115,8 +7117,8 @@ begin
       case El.OpCode of
       case El.OpCode of
       eopDiv:
       eopDiv:
         begin
         begin
-        // convert "a div b" to "Math.floor(a/b)"
-        Result:=CreateMathFloor(El,Result);
+        // convert "a div b" to "rtl.trunc(a/b)"
+        Result:=CreateTruncFloor(El,Result,true);
         end;
         end;
       end;
       end;
 
 
@@ -7305,7 +7307,7 @@ begin
         else if El.OpCode=eopShr then
         else if El.OpCode=eopShr then
           begin
           begin
           // BigInt shr const -> Math.floor(A/otherconst)
           // BigInt shr const -> Math.floor(A/otherconst)
-          Result:=CreateMathFloor(El,CreateDivideNumber(El,A,TMaxPrecInt(1) shl BInt));
+          Result:=CreateTruncFloor(El,CreateDivideNumber(El,A,TMaxPrecInt(1) shl BInt),false);
           A:=nil;
           A:=nil;
           FreeAndNil(B);
           FreeAndNil(B);
           exit;
           exit;
@@ -7379,22 +7381,22 @@ begin
       end;
       end;
     eopDivide:
     eopDivide:
       begin
       begin
-      // currency / currency  ->  Math.floor((currency/currency)*10000)
-      // currency / number  ->  Math.floor(currency/number)
-      // number / currency  ->  Math.floor(number/currency)
+      // currency / currency  ->  rtl.trunc((currency/currency)*10000)
+      // currency / number  ->  rtl.trunc(currency/number)
+      // number / currency  ->  rtl.trunc(number/currency)
       Result:=TJSMultiplicativeExpressionDiv(CreateElement(TJSMultiplicativeExpressionDiv,El));
       Result:=TJSMultiplicativeExpressionDiv(CreateElement(TJSMultiplicativeExpressionDiv,El));
       TJSBinaryExpression(Result).A:=A; A:=nil;
       TJSBinaryExpression(Result).A:=A; A:=nil;
       TJSBinaryExpression(Result).B:=B; B:=nil;
       TJSBinaryExpression(Result).B:=B; B:=nil;
       if (LeftResolved.BaseType=btCurrency) and (RightResolved.BaseType=btCurrency) then
       if (LeftResolved.BaseType=btCurrency) and (RightResolved.BaseType=btCurrency) then
         Result:=CreateMulNumber(El,Result,10000);
         Result:=CreateMulNumber(El,Result,10000);
-      Result:=CreateMathFloor(El,Result);
+      Result:=CreateTruncFloor(El,Result,true);
       exit;
       exit;
       end;
       end;
     eopPower:
     eopPower:
       begin
       begin
-      // currency^^currency  ->  Math.floor(Math.pow(currency/10000,currency/10000)*10000)
-      // currency^^number  ->  Math.floor(Math.pow(currency/10000,number)*10000)
-      // number^^currency  ->  Math.floor(Math.pow(number,currency/10000)*10000)
+      // currency^^currency  ->  rtl.trunc(Math.pow(currency/10000,currency/10000)*10000)
+      // currency^^number  ->  rtl.trunc(Math.pow(currency/10000,number)*10000)
+      // number^^currency  ->  rtl.trunc(Math.pow(number,currency/10000)*10000)
       if LeftResolved.BaseType=btCurrency then
       if LeftResolved.BaseType=btCurrency then
         A:=CreateDivideNumber(El,A,10000);
         A:=CreateDivideNumber(El,A,10000);
       if RightResolved.BaseType=btCurrency then
       if RightResolved.BaseType=btCurrency then
@@ -7404,7 +7406,7 @@ begin
       Call.AddArg(A); A:=nil;
       Call.AddArg(A); A:=nil;
       Call.AddArg(B); B:=nil;
       Call.AddArg(B); B:=nil;
       Result:=CreateMulNumber(El,Call,10000);
       Result:=CreateMulNumber(El,Call,10000);
-      Result:=CreateMathFloor(El,Result);
+      Result:=CreateTruncFloor(El,Result,true);
       end
       end
     else
     else
       RaiseNotSupported(El,AContext,20180422104215);
       RaiseNotSupported(El,AContext,20180422104215);
@@ -8468,8 +8470,8 @@ begin
   if FromBT=btCurrency then
   if FromBT=btCurrency then
     begin
     begin
     if ToBT<>btCurrency then
     if ToBT<>btCurrency then
-      // currency to integer -> Math.floor(value/10000)
-      Result:=CreateMathFloor(PosEl,CreateDivideNumber(PosEl,Result,10000));
+      // currency to integer -> rtl.trunc(value/10000)
+      Result:=CreateTruncFloor(PosEl,CreateDivideNumber(PosEl,Result,10000),true);
     end
     end
   else if ToBT=btCurrency then
   else if ToBT=btCurrency then
     // integer to currency -> value*10000
     // integer to currency -> value*10000
@@ -10302,13 +10304,13 @@ begin
       begin
       begin
       if JSBaseType=pbtJSValue then
       if JSBaseType=pbtJSValue then
         begin
         begin
-        // convert jsvalue to integer -> Math.floor(value)
+        // convert jsvalue to integer -> rtl.trunc(value)
         Result:=ConvertExpression(Param,AContext);
         Result:=ConvertExpression(Param,AContext);
         // Note: convert Param first in case it raises an exception
         // Note: convert Param first in case it raises an exception
         if to_bt=btCurrency then
         if to_bt=btCurrency then
-          // jsvalue to currency -> Math.floor(value*10000)
+          // jsvalue to currency -> rtl.trunc(value*10000)
           Result:=CreateMulNumber(Param,Result,10000);
           Result:=CreateMulNumber(Param,Result,10000);
-        Result:=CreateMathFloor(El,Result);
+        Result:=CreateTruncFloor(El,Result,true);
         exit;
         exit;
         end;
         end;
       end
       end
@@ -11873,7 +11875,7 @@ begin
     if Shift=32 then
     if Shift=32 then
       begin
       begin
       // JS bitwise operations work only 32bit -> use division for bigger shifts
       // JS bitwise operations work only 32bit -> use division for bigger shifts
-      Result:=CreateMathFloor(El,CreateDivideNumber(El,Result,$100000000));
+      Result:=CreateTruncFloor(El,CreateDivideNumber(El,Result,$100000000),false);
       end
       end
     else
     else
       begin
       begin
@@ -18762,9 +18764,9 @@ begin
         // currency := currency
         // currency := currency
       else if AssignContext.RightResolved.BaseType in btAllJSFloats then
       else if AssignContext.RightResolved.BaseType in btAllJSFloats then
         begin
         begin
-        // currency := double  ->  currency := Math.floor(double*10000)
+        // currency := double  ->  currency := rtl.trunc(double*10000)
         AssignContext.RightSide:=CreateMulNumber(El,AssignContext.RightSide,10000);
         AssignContext.RightSide:=CreateMulNumber(El,AssignContext.RightSide,10000);
-        AssignContext.RightSide:=CreateMathFloor(El,AssignContext.RightSide);
+        AssignContext.RightSide:=CreateTruncFloor(El,AssignContext.RightSide,true);
         end
         end
       else if AssignContext.RightResolved.BaseType in btAllJSInteger then
       else if AssignContext.RightResolved.BaseType in btAllJSInteger then
         begin
         begin
@@ -20845,11 +20847,12 @@ begin
   Mul.B:=CreateLiteralNumber(El,n);
   Mul.B:=CreateLiteralNumber(El,n);
 end;
 end;
 
 
-function TPasToJSConverter.CreateMathFloor(El: TPasElement; JS: TJSElement
-  ): TJSElement;
+function TPasToJSConverter.CreateTruncFloor(El: TPasElement; JS: TJSElement;
+  FloorAndCeil: boolean): TJSElement;
 // create Math.floor(JS)
 // create Math.floor(JS)
 var
 var
   Value: TJSValue;
   Value: TJSValue;
+  Call: TJSCallExpression;
 begin
 begin
   if JS is TJSLiteral then
   if JS is TJSLiteral then
     begin
     begin
@@ -20877,18 +20880,24 @@ begin
         exit(JS);
         exit(JS);
         end;
         end;
       jstNumber:
       jstNumber:
+        begin
         if IsNan(Value.AsNumber) or IsInfinite(Value.AsNumber) then
         if IsNan(Value.AsNumber) or IsInfinite(Value.AsNumber) then
-          exit(JS)
-        else
-          begin
-          Value.AsNumber:=Trunc(Value.AsNumber);
           exit(JS);
           exit(JS);
-          end;
+        if FloorAndCeil then
+          Value.AsNumber:=Trunc(Value.AsNumber)
+        else
+          Value.AsNumber:=Floor(Value.AsNumber);
+        exit(JS);
+        end;
     end;
     end;
     end;
     end;
-  Result:=CreateCallExpression(El);
-  TJSCallExpression(Result).Expr:=CreatePrimitiveDotExpr('Math.floor',El);
-  TJSCallExpression(Result).AddArg(JS);
+  Call:=CreateCallExpression(El);
+  Result:=Call;
+  if FloorAndCeil then
+    Call.Expr:=CreatePrimitiveDotExpr(GetBIName(pbivnRTL)+'.'+GetBIName(pbifnTrunc),El)
+  else
+    Call.Expr:=CreatePrimitiveDotExpr('Math.floor',El);
+  Call.AddArg(JS);
 end;
 end;
 
 
 function TPasToJSConverter.CreateDotNameExpr(PosEl: TPasElement;
 function TPasToJSConverter.CreateDotNameExpr(PosEl: TPasElement;

+ 21 - 21
compiler/packages/pastojs/tests/tcmodules.pas

@@ -3057,9 +3057,9 @@ begin
     LinesToStr([ // this.$main
     LinesToStr([ // this.$main
     '$mod.vA = 1;',
     '$mod.vA = 1;',
     '$mod.vB = $mod.vA + $mod.vA;',
     '$mod.vB = $mod.vA + $mod.vA;',
-    '$mod.vB = Math.floor($mod.vA / $mod.vB);',
+    '$mod.vB = rtl.trunc($mod.vA / $mod.vB);',
     '$mod.vB = $mod.vA % $mod.vB;',
     '$mod.vB = $mod.vA % $mod.vB;',
-    '$mod.vB = $mod.vA + ($mod.vA * $mod.vB) + Math.floor($mod.vA / $mod.vB);',
+    '$mod.vB = $mod.vA + ($mod.vA * $mod.vB) + rtl.trunc($mod.vA / $mod.vB);',
     '$mod.vC = -$mod.vA;',
     '$mod.vC = -$mod.vA;',
     '$mod.vA = $mod.vA - $mod.vB;',
     '$mod.vA = $mod.vA - $mod.vB;',
     '$mod.vB = $mod.vA;',
     '$mod.vB = $mod.vA;',
@@ -6618,7 +6618,7 @@ begin
     '$mod.d = -5.00E-1;',
     '$mod.d = -5.00E-1;',
     '$mod.d = Math.pow(10, 3);',
     '$mod.d = Math.pow(10, 3);',
     '$mod.d = 10 % 3;',
     '$mod.d = 10 % 3;',
-    '$mod.d = Math.floor(10 / 3);',
+    '$mod.d = rtl.trunc(10 / 3);',
     '$mod.d = 1;',
     '$mod.d = 1;',
     '$mod.d = 0.1;',
     '$mod.d = 0.1;',
     '$mod.d = 0.3;',
     '$mod.d = 0.3;',
@@ -6947,17 +6947,17 @@ begin
     LinesToStr([
     LinesToStr([
     '$mod.c = 10000;',
     '$mod.c = 10000;',
     '$mod.c = 1000;',
     '$mod.c = 1000;',
-    '$mod.c = Math.floor((1.0 / 3.0) * 10000);',
-    '$mod.c = Math.floor((1 / 3) * 10000);',
+    '$mod.c = rtl.trunc((1.0 / 3.0) * 10000);',
+    '$mod.c = rtl.trunc((1 / 3) * 10000);',
     '$mod.c = $mod.a;',
     '$mod.c = $mod.a;',
     '$mod.d = $mod.c / 10000;',
     '$mod.d = $mod.c / 10000;',
-    '$mod.c = Math.floor($mod.d * 10000);',
+    '$mod.c = rtl.trunc($mod.d * 10000);',
     '$mod.c = $mod.c;',
     '$mod.c = $mod.c;',
     '$mod.c = $mod.d * 10000;',
     '$mod.c = $mod.d * 10000;',
     '$mod.d = $mod.c / 10000;',
     '$mod.d = $mod.c / 10000;',
     '$mod.c = $mod.i * 10000;',
     '$mod.c = $mod.i * 10000;',
     '$mod.c = $mod.i * 10000;',
     '$mod.c = $mod.i * 10000;',
-    '$mod.i = Math.floor($mod.c / 10000);',
+    '$mod.i = rtl.trunc($mod.c / 10000);',
     '$mod.c = $mod.c + $mod.a;',
     '$mod.c = $mod.c + $mod.a;',
     '$mod.c = -$mod.c - $mod.a;',
     '$mod.c = -$mod.c - $mod.a;',
     '$mod.c = ($mod.d * 10000) + $mod.c;',
     '$mod.c = ($mod.d * 10000) + $mod.c;',
@@ -6968,14 +6968,14 @@ begin
     '$mod.c = ($mod.a * $mod.c) / 10000;',
     '$mod.c = ($mod.a * $mod.c) / 10000;',
     '$mod.c = $mod.d * $mod.c;',
     '$mod.c = $mod.d * $mod.c;',
     '$mod.c = $mod.c * $mod.d;',
     '$mod.c = $mod.c * $mod.d;',
-    '$mod.c = Math.floor(($mod.c / $mod.a) * 10000);',
-    '$mod.c = Math.floor(($mod.a / $mod.c) * 10000);',
-    '$mod.c = Math.floor($mod.d / $mod.c);',
-    '$mod.c = Math.floor($mod.c / $mod.d);',
-    '$mod.c = Math.floor(Math.pow($mod.c / 10000, $mod.a / 10000) * 10000);',
-    '$mod.c = Math.floor(Math.pow($mod.a / 10000, $mod.c / 10000) * 10000);',
-    '$mod.c = Math.floor(Math.pow($mod.d, $mod.c / 10000) * 10000);',
-    '$mod.c = Math.floor(Math.pow($mod.c / 10000, $mod.d) * 10000);',
+    '$mod.c = rtl.trunc(($mod.c / $mod.a) * 10000);',
+    '$mod.c = rtl.trunc(($mod.a / $mod.c) * 10000);',
+    '$mod.c = rtl.trunc($mod.d / $mod.c);',
+    '$mod.c = rtl.trunc($mod.c / $mod.d);',
+    '$mod.c = rtl.trunc(Math.pow($mod.c / 10000, $mod.a / 10000) * 10000);',
+    '$mod.c = rtl.trunc(Math.pow($mod.a / 10000, $mod.c / 10000) * 10000);',
+    '$mod.c = rtl.trunc(Math.pow($mod.d, $mod.c / 10000) * 10000);',
+    '$mod.c = rtl.trunc(Math.pow($mod.c / 10000, $mod.d) * 10000);',
     'if ($mod.c === $mod.c) ;',
     'if ($mod.c === $mod.c) ;',
     'if ($mod.c === $mod.a) ;',
     'if ($mod.c === $mod.a) ;',
     'if ($mod.a === $mod.c) ;',
     'if ($mod.a === $mod.c) ;',
@@ -6984,7 +6984,7 @@ begin
     '$mod.c = $mod.DoIt($mod.c);',
     '$mod.c = $mod.DoIt($mod.c);',
     '$mod.c = $mod.DoIt($mod.i * 10000);',
     '$mod.c = $mod.DoIt($mod.i * 10000);',
     '$mod.c = $mod.DoIt($mod.d * 10000);',
     '$mod.c = $mod.DoIt($mod.d * 10000);',
-    '$mod.c = Math.floor($mod.GetIt($mod.c / 10000) * 10000);',
+    '$mod.c = rtl.trunc($mod.GetIt($mod.c / 10000) * 10000);',
     '$mod.j = $mod.c / 10000;',
     '$mod.j = $mod.c / 10000;',
     '$mod.Write($mod.c / 10000);',
     '$mod.Write($mod.c / 10000);',
     '$mod.c = 0;',
     '$mod.c = 0;',
@@ -8042,7 +8042,7 @@ begin
     LinesToStr([ // $mod.$main
     LinesToStr([ // $mod.$main
     'try {',
     'try {',
     '  $mod.i = 0;',
     '  $mod.i = 0;',
-    '  $mod.i = Math.floor(2 / $mod.i);',
+    '  $mod.i = rtl.trunc(2 / $mod.i);',
     '} finally {',
     '} finally {',
     '  $mod.i = 3;',
     '  $mod.i = 3;',
     '};'
     '};'
@@ -17513,7 +17513,7 @@ begin
     '']),
     '']),
     LinesToStr([ // $mod.$main
     LinesToStr([ // $mod.$main
     '$mod.v = $mod.Arr[$mod.i];',
     '$mod.v = $mod.Arr[$mod.i];',
-    '$mod.Arr[Math.floor($mod.v)] = $mod.Arr[$mod.IntArr[0]];',
+    '$mod.Arr[rtl.trunc($mod.v)] = $mod.Arr[$mod.IntArr[0]];',
     '$mod.Arr[$mod.IntArr[1]] = $mod.Arr[$mod.IntArr[2]];',
     '$mod.Arr[$mod.IntArr[1]] = $mod.Arr[$mod.IntArr[2]];',
     '']));
     '']));
 end;
 end;
@@ -26057,8 +26057,8 @@ begin
     'this.c = "";',
     'this.c = "";',
     '']),
     '']),
     LinesToStr([ // $mod.$main
     LinesToStr([ // $mod.$main
-    '$mod.i = Math.floor($mod.v);',
-    '$mod.i = Math.floor($mod.v);',
+    '$mod.i = rtl.trunc($mod.v);',
+    '$mod.i = rtl.trunc($mod.v);',
     '$mod.s = "" + $mod.v;',
     '$mod.s = "" + $mod.v;',
     '$mod.s = "" + $mod.v;',
     '$mod.s = "" + $mod.v;',
     '$mod.b = !($mod.v == false);',
     '$mod.b = !($mod.v == false);',
@@ -26566,7 +26566,7 @@ begin
     '      this.p.v = v;',
     '      this.p.v = v;',
     '    }',
     '    }',
     '});',
     '});',
-    '$mod.i = Math.floor($mod.DoSome($mod.i, $mod.i));',
+    '$mod.i = rtl.trunc($mod.DoSome($mod.i, $mod.i));',
     '$mod.b = !($mod.DoSome($mod.b, $mod.b) == false);',
     '$mod.b = !($mod.DoSome($mod.b, $mod.b) == false);',
     '$mod.d = rtl.getNumber($mod.DoSome($mod.d, $mod.d));',
     '$mod.d = rtl.getNumber($mod.DoSome($mod.d, $mod.d));',
     '$mod.s = "" + $mod.DoSome($mod.s, $mod.s);',
     '$mod.s = "" + $mod.DoSome($mod.s, $mod.s);',

+ 4 - 0
compiler/utils/pas2js/dist/rtl.js

@@ -749,6 +749,10 @@ var rtl = {
     return intf;
     return intf;
   },
   },
 
 
+  trunc: function(a){
+    return a<0 ? Math.ceil(a) : Math.floor(a);
+  },
+
   checkMethodCall: function(obj,type){
   checkMethodCall: function(obj,type){
     if (rtl.isObject(obj) && rtl.is(obj,type)) return;
     if (rtl.isObject(obj) && rtl.is(obj,type)) return;
     rtl.raiseE("EInvalidCast");
     rtl.raiseE("EInvalidCast");