Browse Source

fix INC/DEC code generation when applied to variable paassed as VAR

Vladislav Folts 10 years ago
parent
commit
9432dafe40
6 changed files with 50 additions and 13 deletions
  1. BIN
      bin/compiled.zip
  2. 18 7
      src/ob/Cast.ob
  3. 1 1
      src/ob/Operator.ob
  4. 15 5
      src/ob/Procedure.ob
  5. 7 0
      test/expected/inc_dec.js
  6. 9 0
      test/input/inc_dec.ob

BIN
bin/compiled.zip


+ 18 - 7
src/ob/Cast.ob

@@ -121,17 +121,28 @@ PROCEDURE CastOpDoNothing.make(rtl: OberonRtl.PType; e: Code.PExpression): Code.
     RETURN e
 END CastOpDoNothing.make;
 
+PROCEDURE passedByReference*(e: Code.PExpression): BOOLEAN;
+BEGIN
+    info <- e.designator().info();
+    RETURN (info IS Types.PVariable) & info.isReference();
+END;
+
+PROCEDURE assignByReference*(left, right: Code.PExpression): STRING;
+    RETURN left.code() + ".set(" + Code.derefExpression(right).code() + ")";
+END;
+
 PROCEDURE CastOpDoNothing.assign(rtl: OberonRtl.PType; left, right: Code.PExpression): STRING;
+VAR
+    result: STRING;
 BEGIN
-    rightCode <- SELF.make(rtl, Code.derefExpression(right)).code();
-    info <- left.designator().info();
-    IF (info IS Types.PVariable) & info.isReference() THEN
-        rightCode := ".set(" + rightCode + ")";
+    rightConverted <- SELF.make(rtl, right);
+    IF passedByReference(left) THEN
+        result := assignByReference(left, rightConverted);
     ELSE
-        rightCode := " = " + rightCode;
+        result := left.lval() + " = " + Code.derefExpression(rightConverted).code();
     END;
-    RETURN left.lval() + rightCode
-END CastOpDoNothing.assign;
+    RETURN result;
+END;
 
 PROCEDURE cloneArray*(t: Types.Array; code: STRING; rtl: OberonRtl.Type): STRING;
 VAR

+ 1 - 1
src/ob/Operator.ob

@@ -10,7 +10,7 @@ IMPORT
     String,
     Types;
 TYPE
-    BinaryProc = PROCEDURE(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
+    BinaryProc* = PROCEDURE(left, right: Code.PExpression; rtl: OberonRtl.PType): Code.PExpression;
 
     BinaryOp = PROCEDURE(left, right: Code.PConst): Code.PConst;
     CodePredicate = PROCEDURE(left, right: STRING; rtl: OberonRtl.PType): STRING;

+ 15 - 5
src/ob/Procedure.ob

@@ -485,12 +485,13 @@ BEGIN
     END;
 END checkVariableArgumentsCount;
 
-PROCEDURE incImpl(name: STRING; unary: STRING; incOp: BinaryOpStr): Symbols.PSymbol;
+PROCEDURE incImpl(name: STRING; unary: STRING; incOp: BinaryOpStr; incRefOp: Operator.BinaryProc): Symbols.PSymbol;
     TYPE
         CallImpl = RECORD(StdCall)
             name: STRING;
             unary: STRING;
-            incOp: BinaryOpStr
+            incOp: BinaryOpStr;
+            incRefOp: Operator.BinaryProc;
         END;
 
     PROCEDURE CallImpl.make(args: ARRAY OF Code.PExpression; cx: LanguageContext.PType): Code.PExpression;
@@ -503,7 +504,15 @@ PROCEDURE incImpl(name: STRING; unary: STRING; incOp: BinaryOpStr): Symbols.PSym
         checkVariableArgumentsCount(1, 2, args);
         checkArgumentsType(args, SELF.args, NIL, cx.types);
         x := args[0];
-        IF LEN(args) = 1 THEN
+        IF Cast.passedByReference(x) THEN
+            IF LEN(args) = 1 THEN
+                y := Code.makeSimpleExpression("1", NIL);
+            ELSE
+                y := args[1];
+            END;
+            addExp <- SELF.incRefOp(x, y, cx.rtl);
+            code := Cast.assignByReference(x, addExp);
+        ELSIF LEN(args) = 1 THEN
             code := SELF.unary + x.code();
         ELSE
             y := args[1];
@@ -525,6 +534,7 @@ BEGIN
     call.name := name;
     call.unary := unary;
     call.incOp := incOp;
+    call.incRefOp := incRefOp;
     hasVarArgument(call, Types.basic.integer);
     hasArgument(call, Types.basic.integer);
     RETURN makeSymbol(NEW Std(call.name, call))
@@ -825,8 +835,8 @@ BEGIN
     predefined.add(makeAssert());
     predefined.add(setBitImpl("INCL", inclOp));
     predefined.add(setBitImpl("EXCL", exclOp));
-    predefined.add(incImpl("INC", "++", incOp));
-    predefined.add(incImpl("DEC", "--", decOp));
+    predefined.add(incImpl("INC", "++", incOp, Operator.addInt));
+    predefined.add(incImpl("DEC", "--", decOp, Operator.subInt));
     predefined.add(makeAbs());
     predefined.add(makeFloor());
     predefined.add(makeFlt());

+ 7 - 0
test/expected/inc_dec.js

@@ -1,6 +1,13 @@
 var m = function (){
 var ic = 10;
 var i = 0;
+
+function byRef(i/*VAR INTEGER*/){
+	i.set(i.get() + 1 | 0);
+	i.set(i.get() - 1 | 0);
+	i.set(i.get() + 123 | 0);
+	i.set(i.get() - 123 | 0);
+}
 ++i;
 i += 2;
 i += 15/*3 * 5 | 0*/;

+ 9 - 0
test/input/inc_dec.ob

@@ -3,6 +3,15 @@ MODULE m;
 CONST ic = 10;
 VAR i: INTEGER;
 
+PROCEDURE byRef(VAR i: INTEGER);
+BEGIN
+	INC(i);
+	DEC(i);
+
+	INC(i, 123);
+	DEC(i, 123);
+END byRef;
+
 BEGIN
 	INC(i);
 	INC(i, 2);