2
0
Эх сурвалжийг харах

js -> eberon transition
fix code generation for unary '-' and FLOOR

Vladislav Folts 10 жил өмнө
parent
commit
d7d29ba4ed

BIN
bin/compiled.zip


+ 2 - 14
src/context.js

@@ -31,26 +31,14 @@ ChainedContext.prototype.init = ContextHierarchy.Node;
 exports.Integer = ChainedContext.extend({
 exports.Integer = ChainedContext.extend({
     init: function IntegerContext(context){
     init: function IntegerContext(context){
         ChainedContext.prototype.init.call(this, context);
         ChainedContext.prototype.init.call(this, context);
-        this.__result = "";
-        this.__isHex = false;
+        this.attributes = {};
     },
     },
-    isLexem: function(){return true;},
-    handleChar: function(c){this.__result += String.fromCharCode(c);},
-    handleLiteral: function(){this.__isHex = true;},
-    toInt: function(s){return parseInt(this.__result, 10);},
     endParse: function(){
     endParse: function(){
-        var n = this.toInt();
+        var n = this.attributes.int;
         this.parent().handleConst(basicTypes.integer, Code.makeIntConst(n), n.toString());
         this.parent().handleConst(basicTypes.integer, Code.makeIntConst(n), n.toString());
     }
     }
 });
 });
 
 
-exports.HexInteger = exports.Integer.extend({
-    init: function HexIntegerContext(context){
-        exports.Integer.prototype.init.call(this, context);
-    },
-    toInt: function(s){return parseInt(this.__result, 16);}
-});
-
 exports.Real = ChainedContext.extend({
 exports.Real = ChainedContext.extend({
     init: function RealContext(context){
     init: function RealContext(context){
         ChainedContext.prototype.init.call(this, context);
         ChainedContext.prototype.init.call(this, context);

+ 1 - 3
src/grammar.js

@@ -9,7 +9,6 @@ var literal = Parser.literal;
 var digit = Lexer.digit;
 var digit = Lexer.digit;
 var hexDigit = Lexer.hexDigit;
 var hexDigit = Lexer.hexDigit;
 var point = Lexer.point;
 var point = Lexer.point;
-var separator = Lexer.separator;
 
 
 var and = Parser.and;
 var and = Parser.and;
 var or = Parser.or;
 var or = Parser.or;
@@ -67,8 +66,7 @@ var type = or(context(qualident, Context.Type),
 var identList = and(identdef, repeat(and(",", identdef)));
 var identList = and(identdef, repeat(and(",", identdef)));
 var variableDeclaration = context(and(identList, ":", type), contexts.variableDeclaration);
 var variableDeclaration = context(and(identList, ":", type), contexts.variableDeclaration);
 
 
-var integer = or(context(and(digit, repeat(hexDigit), "H", separator), Context.HexInteger)
-               , context(and(digit, repeat(digit), separator), Context.Integer));
+var integer = context(Lexer.integer, Context.Integer);
 
 
 var scaleFactor = and(or("E", "D"), optional(or("+", "-")), digit, repeat(digit));
 var scaleFactor = and(or("E", "D"), optional(or("+", "-")), digit, repeat(digit));
 var real = context(and(digit, repeat(digit), point, repeat(digit), optional(scaleFactor))
 var real = context(and(digit, repeat(digit), point, repeat(digit), optional(scaleFactor))

+ 1 - 0
src/ob/Context.ob

@@ -9,6 +9,7 @@ TYPE
         isLexem*:       PROCEDURE(): BOOLEAN;
         isLexem*:       PROCEDURE(): BOOLEAN;
         qualifyScope*:  PROCEDURE(scope: ScopeBase.PType): STRING;
         qualifyScope*:  PROCEDURE(scope: ScopeBase.PType): STRING;
         
         
+        attributes*: MAP OF INTEGER;
         rtl*: OberonRtl.PType;
         rtl*: OberonRtl.PType;
     END;
     END;
     PType* = POINTER TO Type;
     PType* = POINTER TO Type;

+ 49 - 4
src/ob/Lexer.ob

@@ -46,6 +46,55 @@ BEGIN
     RETURN result
     RETURN result
 END digit;
 END digit;
 
 
+PROCEDURE integer*(VAR stream: Stream.Type; VAR context: Context.Type): BOOLEAN;
+VAR
+    hexDetected: BOOLEAN;
+    dec, hex: INTEGER;
+
+    PROCEDURE collect(c: CHAR): BOOLEAN;
+    BEGIN
+        d <- -1;
+        IF (c >= "0") & (c <= "9") THEN
+            d := ORD(c) - ORD("0");
+        ELSIF (c >= "A") & (c <= "F") THEN
+            d := ORD(c) - ORD("A") + 10;
+            hexDetected := TRUE;
+        END;
+        IF d # -1 THEN
+            hex := hex * 16 + d;
+            IF ~hexDetected THEN
+                dec := dec * 10 + d;
+            END;
+        END;
+        RETURN d # -1;
+    END;
+
+BEGIN
+    result <- FALSE;
+    IF ~Stream.eof(stream) & collect(Stream.getChar(stream)) & ~hexDetected THEN
+        WHILE ~Stream.eof(stream) & collect(Stream.peekChar(stream)) DO
+            Stream.next(stream, 1);
+        END;
+        IF ~Stream.eof(stream) & (Stream.peekChar(stream) = "H") THEN
+            hexDetected := TRUE;
+            Stream.next(stream, 1);
+        ELSIF hexDetected THEN
+            Errors.raise("integer constant looks like having hexadecimal format but 'H' suffix is missing");
+        END;
+
+        IF Stream.eof(stream) OR ~isLetter(Stream.peekChar(stream)) THEN
+            IF hexDetected THEN
+                context.attributes["int"] := hex;
+            ELSE
+                context.attributes["int"] := dec;
+            END;
+        
+            result := TRUE;
+        END;
+    END
+    RETURN result;
+END;
+
 PROCEDURE hexDigit*(VAR stream: Stream.Type; context: Context.Type): BOOLEAN;
 PROCEDURE hexDigit*(VAR stream: Stream.Type; context: Context.Type): BOOLEAN;
 VAR
 VAR
     result: BOOLEAN;
     result: BOOLEAN;
@@ -187,10 +236,6 @@ BEGIN
     END
     END
 END skipSpaces;
 END skipSpaces;
 
 
-PROCEDURE separator*(stream: Stream.Type; context: Context.Type): BOOLEAN;
-    RETURN Stream.eof(stream) OR ~isLetter(Stream.peekChar(stream))
-END separator;
-
 PROCEDURE Literal.Literal(s: STRING)
 PROCEDURE Literal.Literal(s: STRING)
     | s(s);
     | s(s);
 END;
 END;

+ 16 - 4
src/ob/Operator.ob

@@ -221,8 +221,8 @@ BEGIN
     END;
     END;
     resultCode <- code 
     resultCode <- code 
                 + Code.adjustPrecedence(Code.derefExpression(e), Precedence.unary);
                 + Code.adjustPrecedence(Code.derefExpression(e), Precedence.unary);
-    RETURN Code.makeExpression(resultCode, e.type(), NIL, value)
-END unary;
+    RETURN NEW Code.Expression(resultCode, e.type(), NIL, value, Precedence.unary)
+END;
 
 
 PROCEDURE castToStr(e: Code.PExpression; cx: LanguageContext.PType): STRING;
 PROCEDURE castToStr(e: Code.PExpression; cx: LanguageContext.PType): STRING;
 VAR
 VAR
@@ -681,8 +681,20 @@ PROCEDURE not*(x: Code.PExpression; cx: LanguageContext.PType): Code.PExpression
 END not;
 END not;
 
 
 PROCEDURE negateInt*(x: Code.PExpression; cx: LanguageContext.PType): Code.PExpression;
 PROCEDURE negateInt*(x: Code.PExpression; cx: LanguageContext.PType): Code.PExpression;
-    RETURN promoteToWideIfNeeded(unary(x, opNegateInt, "-"))
-END negateInt;
+VAR
+    result: Code.PExpression;
+BEGIN
+    overflowCheck <- TRUE;
+    c <- x.constValue();
+    IF c # NIL THEN
+        value <- -c^(Code.IntConst).value;
+        result := NEW Code.Expression(String.fromInt(value), Types.basic.integer, NIL, Code.makeIntConst(value), Precedence.unary);
+    ELSE
+        result := promoteToWideIfNeeded(unary(x, opNegateInt, "-"));
+        result := NEW Code.Expression(result.code() + " | 0", result.type(), result.designator(), result.constValue(), Precedence.bitOr);
+    END;
+    RETURN result;
+END;
 
 
 PROCEDURE negateReal*(x: Code.PExpression; cx: LanguageContext.PType): Code.PExpression;
 PROCEDURE negateReal*(x: Code.PExpression; cx: LanguageContext.PType): Code.PExpression;
     RETURN promoteToWideIfNeeded(unary(x, opNegateReal, "-"))
     RETURN promoteToWideIfNeeded(unary(x, opNegateReal, "-"))

+ 8 - 3
src/ob/Procedure.ob

@@ -582,9 +582,14 @@ PROCEDURE makeFloor(): Symbols.PSymbol;
         arg: Code.PExpression;
         arg: Code.PExpression;
     BEGIN
     BEGIN
         arg := checkSingleArgument(args, SELF, cx.types, NIL);
         arg := checkSingleArgument(args, SELF, cx.types, NIL);
-        RETURN Code.makeSimpleExpression(
-            "Math.floor(" + arg.code() + ")",
-            Types.basic.integer)
+        code <- Code.adjustPrecedence(arg, Precedence.bitOr) + " | 0";
+        RETURN NEW Code.Expression(
+            code,
+            Types.basic.integer,
+            NIL,
+            NIL,
+            Precedence.bitOr
+            )
     END CallImpl.make;
     END CallImpl.make;
 BEGIN
 BEGIN
     call <- NEW CallImpl();
     call <- NEW CallImpl();

+ 10 - 4
test/expected/arithmetic.js

@@ -1,6 +1,6 @@
 var m = function (){
 var m = function (){
 var c1 = 2147483647 + 1 | 0;
 var c1 = 2147483647 + 1 | 0;
-var c2 = 4294967295 * 2 | 0;
+var c2 = -1 * 2 | 0;
 var i1 = 0;var i2 = 0;
 var i1 = 0;var i2 = 0;
 var b1 = 0;var b2 = 0;
 var b1 = 0;var b2 = 0;
 var r1 = 0;var r2 = 0;
 var r1 = 0;var r2 = 0;
@@ -12,10 +12,16 @@ i1 = i1 * i2 | 0;
 i1 = i1 / i2 | 0;
 i1 = i1 / i2 | 0;
 i1 = i1 % i2;
 i1 = i1 % i2;
 i1 = 1 + (i1 * i2 | 0) | 0;
 i1 = 1 + (i1 * i2 | 0) | 0;
+i1 = -i2 | 0;
+i1 = -(-i2 | 0) | 0;
+i1 = 1;
+i1 = i2;
+i1 = i2;
+i1 = 1;
 b1 = 1 & 0xFF;
 b1 = 1 & 0xFF;
 b1 = -1 & 0xFF;
 b1 = -1 & 0xFF;
 b1 = b2;
 b1 = b2;
-b1 = -b2 & 0xFF;
+b1 = (-b2 | 0) & 0xFF;
 b1 = b2;
 b1 = b2;
 b1 = (b1 + b2 | 0) & 0xFF;
 b1 = (b1 + b2 | 0) & 0xFF;
 b1 = (b1 - b2 | 0) & 0xFF;
 b1 = (b1 - b2 | 0) & 0xFF;
@@ -24,8 +30,8 @@ b1 = (b1 / b2 | 0) & 0xFF;
 b1 = b1 % b2;
 b1 = b1 % b2;
 i1 = b1;
 i1 = b1;
 b1 = i1 & 0xFF;
 b1 = i1 & 0xFF;
-i1 = -b1;
-b1 = -i1 & 0xFF;
+i1 = -b1 | 0;
+b1 = (-i1 | 0) & 0xFF;
 i1 = i2 + b1 | 0;
 i1 = i2 + b1 | 0;
 i1 = b1 - i2 | 0;
 i1 = b1 - i2 | 0;
 i1 = i2 * b1 | 0;
 i1 = i2 * b1 | 0;

+ 2 - 0
test/expected/const.js

@@ -6,6 +6,8 @@ var i3 = 31;
 var i4 = 10;
 var i4 = 10;
 var i5 = 3;
 var i5 = 3;
 var i6 = 256;
 var i6 = 256;
+var i7 = 1;
+var i8 = -2147483648;
 var r1 = 456700000;
 var r1 = 456700000;
 var r2 = 1.23;
 var r2 = 1.23;
 var r3 = 0.12345;
 var r3 = 0.12345;

+ 1 - 1
test/expected/floor.js

@@ -1,4 +1,4 @@
 var m = function (){
 var m = function (){
 var i = 0;
 var i = 0;
-i = Math.floor(1.23);
+i = 1.23 | 0;
 }();
 }();

+ 1 - 1
test/expected/inc_dec.js

@@ -18,6 +18,6 @@ i += i + 1 | 0;
 i -= 2;
 i -= 2;
 i -= 15/*3 * 5 | 0*/;
 i -= 15/*3 * 5 | 0*/;
 i -= 10/*ic*/;
 i -= 10/*ic*/;
-i -= -2/*4294967295 * 2 | 0*/;
+i -= -2/*-1 * 2 | 0*/;
 i -= i * 2 | 0;
 i -= i * 2 | 0;
 }();
 }();

+ 4 - 4
test/expected/parentheses.js

@@ -35,9 +35,9 @@ s = s & s ^ s;
 s = s & (s ^ s);
 s = s & (s ^ s);
 s = s & s | s;
 s = s & s | s;
 s = s & (s | s);
 s = s & (s | s);
-i = -(i * 2 | 0) + i | 0;
-i = -(i * (2 + i | 0) | 0);
-i = -(i % (2 * i | 0));
-i = -i + (2 * i | 0) | 0;
+i = (-(i * 2 | 0) | 0) + i | 0;
+i = -(i * (2 + i | 0) | 0) | 0;
+i = -(i % (2 * i | 0)) | 0;
+i = (-i | 0) + (2 * i | 0) | 0;
 s = ~s & ~~s;
 s = ~s & ~~s;
 }();
 }();

+ 1 - 1
test/expected/var_parameter.js

@@ -41,7 +41,7 @@ function p3(i/*VAR INTEGER*/, byte/*VAR BYTE*/, b/*VAR BOOLEAN*/){
 	j = i.get() + 1 | 0;
 	j = i.get() + 1 | 0;
 	j = 2 * i.get() | 0;
 	j = 2 * i.get() | 0;
 	j = i.get() / 2 | 0;
 	j = i.get() / 2 | 0;
-	j = -i.get();
+	j = -i.get() | 0;
 	b.set(!b.get());
 	b.set(!b.get());
 	a[i.get()] = i.get();
 	a[i.get()] = i.get();
 	p1({set: function($v){j = $v;}, get: function(){return j;}}, i, byte);
 	p1({set: function($v){j = $v;}, get: function(){return j;}}, i, byte);

+ 6 - 0
test/input/arithmetic.ob

@@ -17,6 +17,12 @@ BEGIN
 	i1 := i1 DIV i2;
 	i1 := i1 DIV i2;
 	i1 := i1 MOD i2;
 	i1 := i1 MOD i2;
 	i1 := 1 + i1 * i2;
 	i1 := 1 + i1 * i2;
+	i1 := -i2;
+	i1 := -(-i2);
+	i1 := -(-1);
+	i1 := +i2;
+	i1 := +(+i2);
+	i1 := +(+1);
 
 
 	b1 := 1;
 	b1 := 1;
 	b1 := -1;
 	b1 := -1;

+ 2 - 0
test/input/const.ob

@@ -8,6 +8,8 @@ CONST
 	i4 = 0AH;
 	i4 = 0AH;
 	i5 = 03H;
 	i5 = 03H;
 	i6 = 100H;
 	i6 = 100H;
+	i7 = -0FFFFFFFFH;
+	i8 = -2147483648;
 	r1 = 4.567E8;
 	r1 = 4.567E8;
 	r2 = 1.23;
 	r2 = 1.23;
 	r3 = 1.2345E-1;
 	r3 = 1.2345E-1;

+ 1 - 1
test/test_unit.js

@@ -560,7 +560,7 @@ return {
          ["1HH", "not parsed"],
          ["1HH", "not parsed"],
          ["1H0", "not parsed"],
          ["1H0", "not parsed"],
          ["1 23", "not parsed"],
          ["1 23", "not parsed"],
-         ["1F FH", "not parsed"])
+         ["1F FH", "integer constant looks like having hexadecimal format but 'H' suffix is missing"])
     ),
     ),
 "SET statement": testWithContext(
 "SET statement": testWithContext(
     context(grammar.statement, "VAR s: SET;"),
     context(grammar.statement, "VAR s: SET;"),