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

fix code generation for initialization MAP fields in constructor

Vladislav Folts 10 жил өмнө
parent
commit
0a43d5bfd7

BIN
bin/compiled.zip


+ 9 - 5
src/eberon/EberonConstructor.ob

@@ -1,5 +1,5 @@
 MODULE EberonConstructor;
-IMPORT Code, EberonRecord, Errors, LanguageContext, Operator, Procedure, Stream, Types;
+IMPORT Cast, Code, EberonCast, EberonRecord, Errors, LanguageContext, Operator, Procedure, Stream, Types;
 TYPE
     ConstructorCall = RECORD(Procedure.StdCall)
         recordType: EberonRecord.PRecord;
@@ -74,16 +74,20 @@ BEGIN
 END;
 
 PROCEDURE NonRecordInitCall.handleArgument(e: Code.PExpression);
+VAR
+    op: Cast.PCastOp;
 BEGIN
     IF LEN(SELF.code) # 0 THEN
         raiseSingleArgumentException(SELF);
     END;
 
-    variable <- Types.makeVariable(SELF.type, FALSE);
+    IF SELF.cx.types.implicitCast(e.type(), SELF.type, FALSE, Operator.castOperations, op)
+        # Cast.errNo THEN
+            Errors.raise("type mismatch: field '" + SELF.field + "' is '" + SELF.type.description()
+                         + "' and cannot be initialized using '" + e.type().description() + "' expression");
+    END;
     lval <- fieldInitLval(SELF.field, SELF.type);
-    designator <- NEW Code.Designator(SELF.field, lval, NIL, SELF.type, variable, NIL);
-    left <- Code.makeExpression(SELF.field, SELF.type, designator, NIL);
-    SELF.code := Operator.assign(left, e, SELF.cx^);    
+    SELF.code := lval + " = " + op.clone(SELF.cx.rtl, e);
 END;
         
 PROCEDURE NonRecordInitCall.end(): Code.PExpression;

+ 1 - 1
src/ob/Code.ob

@@ -18,7 +18,7 @@ TYPE
         PROCEDURE Designator*(code: STRING; lval: STRING; refCode: RefCodeProc; type: Types.PType; info: Types.PId; scope: ScopeBase.PType);
 
         PROCEDURE code(): STRING;
-        PROCEDURE lval(): STRING;
+        PROCEDURE lval*(): STRING;
         PROCEDURE refCode(): RefCodeProc;
         PROCEDURE type(): Types.PType;
         PROCEDURE info*(): Types.PId;

+ 1 - 1
src/ob/Operator.ob

@@ -493,7 +493,7 @@ BEGIN
         result := assignArrayFromString(leftType(Types.PArray)^, rightType^);
     ELSE
         IF cx.types.implicitCast(rightType, leftType, FALSE, castOperations, castOperation)
-            # Cast.errNo THEN;
+            # Cast.errNo THEN
             Errors.raise("type mismatch: '" + left.code() + "' is '" + leftType.description()
                          + "' and cannot be assigned to '" + rightType.description() + "' expression");
         END;

+ 7 - 4
test/expected/eberon/map.js

@@ -17,10 +17,6 @@ var RTL$ = {
                 result[i] = this.makeArray.apply(this, forward);
         return result;
     },
-    assert: function (condition){
-        if (!condition)
-            throw new Error("assertion failed");
-    },
     cloneMapOfScalars: function (from){
         var result = {};
         this.copyMapOfScalars(from, result);
@@ -35,6 +31,10 @@ var RTL$ = {
         for(var p in map)
             delete map[p];
     },
+    assert: function (condition){
+        if (!condition)
+            throw new Error("assertion failed");
+    },
     makeCharArray: function (/*dimensions*/){
         var forward = Array.prototype.slice.call(arguments);
         var length = forward.pop();
@@ -103,6 +103,9 @@ function anonymous$1(){
 }
 var r = new anonymous$1();
 var a = RTL$.makeArray(1, {});
+function RecordWithMapInitializedInConstructor(m/*MAP OF INTEGER*/){
+	this.$m = RTL$.cloneMapOfScalars(m);
+}
 
 function ForEach(){
 	var m = {};

+ 10 - 0
test/input/eberon/map.ob

@@ -1,11 +1,21 @@
 MODULE test;
 TYPE
     MapOfInteger = MAP OF INTEGER;
+
+    RecordWithMapInitializedInConstructor = RECORD
+        PROCEDURE RecordWithMapInitializedInConstructor(m: MapOfInteger);
+
+        m: MapOfInteger;
+    END;
 VAR
     m: MapOfInteger;
     r: RECORD m: MapOfInteger; END;
     a: ARRAY 1 OF MapOfInteger;
 
+PROCEDURE RecordWithMapInitializedInConstructor.RecordWithMapInitializedInConstructor(m: MapOfInteger)
+    | m(m);
+END;
+
 PROCEDURE ForEach();
 VAR
     m: MapOfInteger;

+ 3 - 2
test/test_unit_eberon.js

@@ -1179,7 +1179,8 @@ exports.suite = {
         pass("PROCEDURE T.T() | i(123); END;"),
         fail(["PROCEDURE T.T() | i(); END;", "single argument expected to initialize field 'i'"],
              ["PROCEDURE T.T() | i(123, 456); END;", "single argument expected to initialize field 'i'"],
-             ["PROCEDURE T.T() | i(TRUE); END;", "type mismatch: 'i' is 'INTEGER' and cannot be assigned to 'BOOLEAN' expression"]
+             ["PROCEDURE T.T() | i(TRUE); END;", 
+              "type mismatch: field 'i' is 'INTEGER' and cannot be initialized using 'BOOLEAN' expression"]
             )
         ),
     "initialize array fields": testWithContext(
@@ -1188,7 +1189,7 @@ exports.suite = {
                 ),
         pass("PROCEDURE RecordWithArray.RecordWithArray(a: ARRAY OF INTEGER) | aDynamic(a); END;"),
         fail(["PROCEDURE RecordWithArray.RecordWithArray(a: ARRAY OF INTEGER) | aStatic(a); END;", 
-              "type mismatch: 'aStatic' is 'ARRAY 3 OF INTEGER' and cannot be assigned to 'ARRAY OF INTEGER' expression"]
+              "type mismatch: field 'aStatic' is 'ARRAY 3 OF INTEGER' and cannot be initialized using 'ARRAY OF INTEGER' expression"]
             )
         ),
     "initialize fields (of record type)": testWithContext(