浏览代码

fix code generation for MAP passed as VAR parameter

Vladislav Folts 10 年之前
父节点
当前提交
e32000450e

二进制
bin/compiled.zip


+ 3 - 4
src/context.js

@@ -450,8 +450,7 @@ exports.Designator = ChainedContext.extend({
             new Code.Designator(code, this.__lval ? this.__lval : code, refCode, this.__currentType, this.__info, this.__scope));
             new Code.Designator(code, this.__lval ? this.__lval : code, refCode, this.__currentType, this.__info, this.__scope));
     },
     },
     __makeRefCode: function(code){
     __makeRefCode: function(code){
-        if (   this.__currentType instanceof Type.Array
-            || this.__currentType instanceof Type.Record
+        if (   !this.__currentType.isScalar()
             || this.__info.isReference())
             || this.__info.isReference())
             return code;
             return code;
         if (this.__derefCode)
         if (this.__derefCode)
@@ -1715,7 +1714,7 @@ function isTypeRecursive(type, base){
     if (type instanceof Type.Record){
     if (type instanceof Type.Record){
         if (isTypeRecursive(Type.recordBase(type), base))
         if (isTypeRecursive(Type.recordBase(type), base))
             return true;
             return true;
-        var fields = type.fields;
+        var fields = Type.recordOwnFields(type);
         for(var fieldName in fields){
         for(var fieldName in fields){
             if (isTypeRecursive(fields[fieldName].type(), base))
             if (isTypeRecursive(fields[fieldName].type(), base))
                 return true;
                 return true;
@@ -1786,7 +1785,7 @@ exports.RecordDecl = ChainedContext.extend({
     },
     },
     __generateFieldsInitializationCode: function(){
     __generateFieldsInitializationCode: function(){
         var result = "";
         var result = "";
-        var ownFields = this.__type.fields;
+        var ownFields = Type.recordOwnFields(this.__type);
         for(var f in ownFields){
         for(var f in ownFields){
             var fieldType = ownFields[f].type();
             var fieldType = ownFields[f].type();
             result += "this." + Type.mangleField(f, fieldType) + " = " + fieldType.initializer(this) + ";\n";
             result += "this." + Type.mangleField(f, fieldType) + " = " + fieldType.initializer(this) + ";\n";

+ 2 - 2
src/eberon/EberonCast.ob

@@ -19,9 +19,9 @@ PROCEDURE copyArray(t: Types.Array; leftCode, rightCode: STRING; rtl: OberonRtl.
 VAR
 VAR
     result: STRING;
     result: STRING;
 BEGIN
 BEGIN
-    IF Types.isScalar(Types.arrayElementsType(t)^) THEN
+    IF Types.arrayElementsType(t).isScalar() THEN
         result := "Array.prototype.splice.apply(" + leftCode + ", [0, Number.MAX_VALUE].concat(" + rightCode + "))";
         result := "Array.prototype.splice.apply(" + leftCode + ", [0, Number.MAX_VALUE].concat(" + rightCode + "))";
-    ELSIF Types.isScalar(Types.arrayBaseElementsType(t)^) THEN 
+    ELSIF Types.arrayBaseElementsType(t).isScalar() THEN 
         result := rtl.copyArrayOfScalars(rightCode, leftCode);
         result := rtl.copyArrayOfScalars(rightCode, leftCode);
     ELSE
     ELSE
         result := rtl.copyArrayOfRecords(rightCode, leftCode);
         result := rtl.copyArrayOfRecords(rightCode, leftCode);

+ 4 - 4
src/eberon/EberonConstructor.ob

@@ -16,7 +16,7 @@ TYPE
 
 
     NonRecordInitCall = RECORD(Procedure.CallGenerator)
     NonRecordInitCall = RECORD(Procedure.CallGenerator)
         cx: LanguageContext.PType;
         cx: LanguageContext.PType;
-        type: Types.PType;
+        type: Types.PStorageType;
         field: STRING;
         field: STRING;
         code: STRING;
         code: STRING;
     END;
     END;
@@ -41,14 +41,14 @@ BEGIN
     RETURN Code.makeSimpleExpression(code, NIL);
     RETURN Code.makeSimpleExpression(code, NIL);
 END;
 END;
 
 
-PROCEDURE fieldInitLval(field: STRING; type: Types.PType): STRING;
+PROCEDURE fieldInitLval(field: STRING; type: Types.PStorageType): STRING;
     RETURN "this." + Types.mangleField(field, type);
     RETURN "this." + Types.mangleField(field, type);
 END;
 END;
 
 
 PROCEDURE RecordInitCall.make(args: ARRAY OF Code.PExpression; cx: LanguageContext.PType): Code.PExpression;
 PROCEDURE RecordInitCall.make(args: ARRAY OF Code.PExpression; cx: LanguageContext.PType): Code.PExpression;
 BEGIN
 BEGIN
     e <- SUPER(args, cx);
     e <- SUPER(args, cx);
-    t <- e.type();
+    t <- e.type()(Types.PStorageType);
     RETURN Code.makeSimpleExpression(fieldInitLval(SELF.field, t) + " = " + e.code(), t);
     RETURN Code.makeSimpleExpression(fieldInitLval(SELF.field, t) + " = " + e.code(), t);
 END;
 END;
 
 
@@ -117,7 +117,7 @@ BEGIN
 END;
 END;
 
 
 PROCEDURE makeFieldInitCall*(
 PROCEDURE makeFieldInitCall*(
-    type: Types.PType; 
+    type: Types.PStorageType; 
     cx: LanguageContext.PType;
     cx: LanguageContext.PType;
     field: STRING
     field: STRING
     ): Procedure.PCallGenerator;
     ): Procedure.PCallGenerator;

+ 4 - 0
src/eberon/EberonMap.ob

@@ -72,6 +72,10 @@ BEGIN
     RETURN result;
     RETURN result;
 END;
 END;
 
 
+PROCEDURE Type.isScalar(): BOOLEAN;
+    RETURN FALSE;
+END;
+
 PROCEDURE MethodCallRemove.make(args: ARRAY OF Code.PExpression; cx: LanguageContext.PType): Code.PExpression;
 PROCEDURE MethodCallRemove.make(args: ARRAY OF Code.PExpression; cx: LanguageContext.PType): Code.PExpression;
 BEGIN
 BEGIN
     argCode <- Procedure.makeArgumentsCode(cx);
     argCode <- Procedure.makeArgumentsCode(cx);

+ 2 - 2
src/eberon/EberonRecord.ob

@@ -46,7 +46,7 @@ TYPE
     PRecord* = POINTER TO Record;
     PRecord* = POINTER TO Record;
 
 
     RecordField* = RECORD(Types.RecordField)
     RecordField* = RECORD(Types.RecordField)
-        PROCEDURE RecordField*(identdef: Context.PIdentdefInfo; type: Types.PType; record: PRecord);
+        PROCEDURE RecordField*(identdef: Context.PIdentdefInfo; type: Types.PStorageType; record: PRecord);
 
 
         record: PRecord;
         record: PRecord;
     END;
     END;
@@ -510,7 +510,7 @@ BEGIN
     RETURN result;
     RETURN result;
 END;
 END;
 
 
-PROCEDURE RecordField.RecordField(identdef: Context.PIdentdefInfo; type: Types.PType; record: PRecord)
+PROCEDURE RecordField.RecordField(identdef: Context.PIdentdefInfo; type: Types.PStorageType; record: PRecord)
     | SUPER(identdef, type);
     | SUPER(identdef, type);
 BEGIN
 BEGIN
     SELF.record := record;
     SELF.record := record;

+ 1 - 1
src/eberon/eberon_context.js

@@ -759,7 +759,7 @@ var ProcOrMethodDecl = Context.ProcDecl.extend({
         };
         };
     },
     },
     __handleFieldInit: function(id){
     __handleFieldInit: function(id){
-        var fields = this.__boundType.fields;
+        var fields = Type.recordOwnFields(this.__boundType);
         if (!fields.hasOwnProperty(id))
         if (!fields.hasOwnProperty(id))
             throw new Errors.Error("'" + id + "' is not record '" + Type.typeName(this.__boundType) + "' own field");
             throw new Errors.Error("'" + id + "' is not record '" + Type.typeName(this.__boundType) + "' own field");
         
         

+ 2 - 2
src/ob/Cast.ob

@@ -153,9 +153,9 @@ PROCEDURE cloneArray*(t: Types.Array; code: STRING; rtl: OberonRtl.Type): STRING
 VAR
 VAR
     result: STRING;
     result: STRING;
 BEGIN
 BEGIN
-    IF Types.isScalar(Types.arrayElementsType(t)^) THEN
+    IF Types.arrayElementsType(t).isScalar() THEN
         result := code + ".slice()";
         result := code + ".slice()";
-    ELSIF Types.isScalar(Types.arrayBaseElementsType(t)^) THEN 
+    ELSIF Types.arrayBaseElementsType(t).isScalar() THEN 
         result := rtl.cloneArrayOfScalars(code);
         result := rtl.cloneArrayOfScalars(code);
     ELSE
     ELSE
         result := rtl.cloneArrayOfRecords(code);
         result := rtl.cloneArrayOfRecords(code);

+ 6 - 2
src/ob/Module.ob

@@ -55,8 +55,12 @@ PROCEDURE AnyType.denote(id: STRING; isReadObly: BOOLEAN): Types.PField;
 END;
 END;
 
 
 PROCEDURE AnyType.designatorCode(id: STRING): STRING;
 PROCEDURE AnyType.designatorCode(id: STRING): STRING;
-    RETURN id
-END AnyType.designatorCode;
+    RETURN id;
+END;
+
+PROCEDURE AnyType.isScalar(): BOOLEAN;
+    RETURN FALSE;
+END;
 
 
 PROCEDURE AnyField.id(): STRING;
 PROCEDURE AnyField.id(): STRING;
     RETURN "any field"
     RETURN "any field"

+ 47 - 23
src/ob/Types.ob

@@ -106,21 +106,23 @@ TYPE
     END;
     END;
     PField* = POINTER TO Field;
     PField* = POINTER TO Field;
 
 
+    PStorageType* = POINTER TO StorageType;
+
     RecordField* = RECORD(Field)
     RecordField* = RECORD(Field)
-        PROCEDURE RecordField*(identdef: Context.PIdentdefInfo; type: PType);
+        PROCEDURE RecordField*(identdef: Context.PIdentdefInfo; type: PStorageType);
 
 
         PROCEDURE identdef*(): Context.PIdentdefInfo;
         PROCEDURE identdef*(): Context.PIdentdefInfo;
 
 
         mIdentdef: Context.PIdentdefInfo;
         mIdentdef: Context.PIdentdefInfo;
-        mType: PType;
+        mType: PStorageType;
     END;
     END;
     PRecordField* = POINTER TO RecordField;
     PRecordField* = POINTER TO RecordField;
 
 
     StorageType* = RECORD(Type)    
     StorageType* = RECORD(Type)    
         PROCEDURE initializer*(cx: Context.Type): STRING;
         PROCEDURE initializer*(cx: Context.Type): STRING;
         PROCEDURE denote*(id: STRING; isReadObly: BOOLEAN): PField;
         PROCEDURE denote*(id: STRING; isReadObly: BOOLEAN): PField;
+        PROCEDURE isScalar*(): BOOLEAN;
     END;
     END;
-    PStorageType* = POINTER TO StorageType;
 
 
     NamedType* = RECORD(StorageType)
     NamedType* = RECORD(StorageType)
         PROCEDURE NamedType(name: STRING);
         PROCEDURE NamedType(name: STRING);
@@ -129,9 +131,9 @@ TYPE
     END;
     END;
 
 
     Array* = RECORD(NamedType)
     Array* = RECORD(NamedType)
-        PROCEDURE Array*(elementsType: PType);
+        PROCEDURE Array*(elementsType: PStorageType);
 
 
-        elementsType-: PType
+        elementsType-: PStorageType
     END;
     END;
     PArray* = POINTER TO Array;
     PArray* = POINTER TO Array;
 
 
@@ -140,7 +142,7 @@ TYPE
     POpenArray* = POINTER TO OpenArray;
     POpenArray* = POINTER TO OpenArray;
 
 
     StaticArray* = RECORD(Array)
     StaticArray* = RECORD(Array)
-        PROCEDURE StaticArray*(initializer: STRING; elementsType: PType; len: INTEGER); 
+        PROCEDURE StaticArray*(initializer: STRING; elementsType: PStorageType; len: INTEGER); 
 
 
         PROCEDURE length*(): INTEGER;
         PROCEDURE length*(): INTEGER;
 
 
@@ -190,6 +192,8 @@ TYPE
 
 
     PBasicType* = POINTER TO BasicType;
     PBasicType* = POINTER TO BasicType;
 
 
+    FieldsMap = MAP OF PField;
+
     Record* = RECORD(NamedType)
     Record* = RECORD(NamedType)
         PROCEDURE Record*(name: STRING; cons: STRING; scope: ScopeBase.PType);
         PROCEDURE Record*(name: STRING; cons: STRING; scope: ScopeBase.PType);
 
 
@@ -199,7 +203,7 @@ TYPE
         PROCEDURE codeForNew*(cx: Context.Type): STRING;
         PROCEDURE codeForNew*(cx: Context.Type): STRING;
         PROCEDURE finalize*();
         PROCEDURE finalize*();
 
 
-        fields-: MAP OF PField;
+        fields-: FieldsMap;
         base-:   PRecord;
         base-:   PRecord;
         cons-:   STRING;
         cons-:   STRING;
         scope-:  ScopeBase.PType;
         scope-:  ScopeBase.PType;
@@ -261,6 +265,14 @@ BEGIN
     SELF.notExported.clear();
     SELF.notExported.clear();
 END Record.finalize;
 END Record.finalize;
 
 
+PROCEDURE Record.isScalar(): BOOLEAN;
+    RETURN FALSE;
+END;
+
+PROCEDURE recordOwnFields*(r: Record): FieldsMap;
+    RETURN r.fields;
+END;
+
 PROCEDURE Record.Record(name: STRING; cons: STRING; scope: ScopeBase.PType)
 PROCEDURE Record.Record(name: STRING; cons: STRING; scope: ScopeBase.PType)
     | SUPER(name),
     | SUPER(name),
       cons(cons),
       cons(cons),
@@ -404,6 +416,10 @@ PROCEDURE BasicType.initializer(cx: Context.Type): STRING;
     RETURN SELF.mInitializer
     RETURN SELF.mInitializer
 END BasicType.initializer;
 END BasicType.initializer;
 
 
+PROCEDURE BasicType.isScalar(): BOOLEAN;
+    RETURN TRUE;
+END;
+
 PROCEDURE Nil.description(): STRING;
 PROCEDURE Nil.description(): STRING;
     RETURN "NIL"
     RETURN "NIL"
 END Nil.description;
 END Nil.description;
@@ -546,6 +562,10 @@ BEGIN
     RETURN existingField(base^, id, d^)
     RETURN existingField(base^, id, d^)
 END;
 END;
 
 
+PROCEDURE Pointer.isScalar(): BOOLEAN;
+    RETURN TRUE;
+END;
+
 PROCEDURE foldArrayDimensions(VAR a: Array; dimToStr: ArrayDimensionDescriptionCallback; VAR sizes, of: STRING);
 PROCEDURE foldArrayDimensions(VAR a: Array; dimToStr: ArrayDimensionDescriptionCallback; VAR sizes, of: STRING);
 BEGIN  
 BEGIN  
     elementsType <- a.elementsType;
     elementsType <- a.elementsType;
@@ -587,7 +607,11 @@ END arrayDescription;
 
 
 PROCEDURE Array.description(): STRING;
 PROCEDURE Array.description(): STRING;
     RETURN arrayDescription(SELF, arrayDimensionDescription)
     RETURN arrayDescription(SELF, arrayDimensionDescription)
-END Array.description;
+END;
+
+PROCEDURE Array.isScalar(): BOOLEAN;
+    RETURN FALSE;
+END;
 
 
 PROCEDURE StorageType.denote(id: STRING; isReadObly: BOOLEAN): PField;
 PROCEDURE StorageType.denote(id: STRING; isReadObly: BOOLEAN): PField;
 BEGIN
 BEGIN
@@ -604,24 +628,20 @@ PROCEDURE StaticArray.initializer(cx: Context.Type): STRING;
     RETURN SELF.mInitializer
     RETURN SELF.mInitializer
 END StaticArray.initializer;
 END StaticArray.initializer;
 
 
-PROCEDURE arrayElementsType*(a: Array): PType;
+PROCEDURE arrayElementsType*(a: Array): PStorageType;
     RETURN a.elementsType
     RETURN a.elementsType
 END arrayElementsType;
 END arrayElementsType;
 
 
-PROCEDURE arrayBaseElementsType*(a: Array): PType;
+PROCEDURE arrayBaseElementsType*(a: Array): PStorageType;
 VAR
 VAR
-    result: PType;
+    result: PStorageType;
 BEGIN
 BEGIN
     result := a.elementsType;
     result := a.elementsType;
     WHILE result IS PArray DO
     WHILE result IS PArray DO
         result := result(PArray).elementsType;
         result := result(PArray).elementsType;
     END;
     END;
-    RETURN result
-END arrayBaseElementsType;
-
-PROCEDURE isScalar*(VAR t: Type): BOOLEAN;
-    RETURN ~(t IS Array) & ~(t IS Record) 
-END isScalar;
+    RETURN result;
+END;
 
 
 PROCEDURE StaticArray.length(): INTEGER;
 PROCEDURE StaticArray.length(): INTEGER;
     RETURN SELF.len
     RETURN SELF.len
@@ -635,6 +655,10 @@ PROCEDURE Procedure.description(): STRING;
     RETURN SELF.name
     RETURN SELF.name
 END Procedure.description;
 END Procedure.description;
 
 
+PROCEDURE Procedure.isScalar(): BOOLEAN;
+    RETURN TRUE;
+END;
+
 PROCEDURE DefinedProcedure.designatorCode(id: STRING): STRING;
 PROCEDURE DefinedProcedure.designatorCode(id: STRING): STRING;
     RETURN id
     RETURN id
 END DefinedProcedure.designatorCode;
 END DefinedProcedure.designatorCode;
@@ -674,7 +698,7 @@ PROCEDURE NamedType.NamedType(name: STRING)
     | name(name);
     | name(name);
 END;
 END;
 
 
-PROCEDURE Array.Array(elementsType: PType)
+PROCEDURE Array.Array(elementsType: PStorageType)
     | SUPER(""),
     | SUPER(""),
       elementsType(elementsType);
       elementsType(elementsType);
 BEGIN
 BEGIN
@@ -682,7 +706,7 @@ END;
 
 
 PROCEDURE StaticArray.StaticArray(
 PROCEDURE StaticArray.StaticArray(
     initializer: STRING;
     initializer: STRING;
-    elementsType: PType;
+    elementsType: PStorageType;
     len: INTEGER ) | 
     len: INTEGER ) | 
     SUPER(elementsType),
     SUPER(elementsType),
     mInitializer(initializer),
     mInitializer(initializer),
@@ -745,12 +769,12 @@ BEGIN
     RETURN result;
     RETURN result;
 END;
 END;
 
 
-PROCEDURE mangleField*(id: STRING; type: PType): STRING;
+PROCEDURE mangleField*(id: STRING; type: PStorageType): STRING;
 BEGIN
 BEGIN
     result <- id;
     result <- id;
-    IF isScalar(type^) 
+    IF type.isScalar() 
         OR ((type IS PArray)
         OR ((type IS PArray)
-            & isScalar(arrayBaseElementsType(type^)^)) THEN
+            & arrayBaseElementsType(type^).isScalar()) THEN
         result := mangleJSProperty(result);
         result := mangleJSProperty(result);
     ELSE
     ELSE
         result := "$" + result;
         result := "$" + result;
@@ -786,7 +810,7 @@ PROCEDURE RecordField.asVar(isReadOnly: BOOLEAN; cx: Context.Type): PId;
     RETURN makeVariable(SELF.mType, isReadOnly);
     RETURN makeVariable(SELF.mType, isReadOnly);
 END;
 END;
 
 
-PROCEDURE RecordField.RecordField(identdef: Context.PIdentdefInfo; type: PType)
+PROCEDURE RecordField.RecordField(identdef: Context.PIdentdefInfo; type: PStorageType)
     | mIdentdef(identdef),
     | mIdentdef(identdef),
       mType(type);
       mType(type);
 END;
 END;

+ 31 - 0
test/expected/eberon/map.js

@@ -1,4 +1,22 @@
 var RTL$ = {
 var RTL$ = {
+    makeArray: function (/*dimensions, initializer*/){
+        var forward = Array.prototype.slice.call(arguments);
+        var result = new Array(forward.shift());
+        var i;
+        if (forward.length == 1){
+            var init = forward[0];
+            if (typeof init == "function")
+                for(i = 0; i < result.length; ++i)
+                    result[i] = init();
+            else
+                for(i = 0; i < result.length; ++i)
+                    result[i] = init;
+        }
+        else
+            for(i = 0; i < result.length; ++i)
+                result[i] = this.makeArray.apply(this, forward);
+        return result;
+    },
     assert: function (condition){
     assert: function (condition){
         if (!condition)
         if (!condition)
             throw new Error("assertion failed");
             throw new Error("assertion failed");
@@ -80,6 +98,11 @@ var RTL$ = {
 };
 };
 var test = function (){
 var test = function (){
 var m = {};
 var m = {};
+function anonymous$1(){
+	this.$m = {};
+}
+var r = new anonymous$1();
+var a = RTL$.makeArray(1, {});
 
 
 function ForEach(){
 function ForEach(){
 	var m = {};
 	var m = {};
@@ -196,6 +219,11 @@ function assign(a/*MAP OF INTEGER*/){
 	var v4 = RTL$.cloneMapOfScalars(returnLocalMap());
 	var v4 = RTL$.cloneMapOfScalars(returnLocalMap());
 	var v5 = RTL$.cloneMapOfScalars(returnNonLocalMap(v));
 	var v5 = RTL$.cloneMapOfScalars(returnNonLocalMap(v));
 }
 }
+
+function passByRef(m/*VAR MAP OF INTEGER*/){
+	m["abc"] = 123;
+	RTL$.assert(Object.prototype.hasOwnProperty.call(m, "abc"));
+}
 var $map1 = m;
 var $map1 = m;
 for(var k in $map1){
 for(var k in $map1){
 	var v = $map1[k];
 	var v = $map1[k];
@@ -204,4 +232,7 @@ for(var k in $map1){
 		var v2 = $map2[k2];
 		var v2 = $map2[k2];
 	}
 	}
 }
 }
+passByRef(m);
+passByRef(r.$m);
+passByRef(a[0]);
 }();
 }();

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

@@ -3,6 +3,8 @@ TYPE
     MapOfInteger = MAP OF INTEGER;
     MapOfInteger = MAP OF INTEGER;
 VAR
 VAR
     m: MapOfInteger;
     m: MapOfInteger;
+    r: RECORD m: MapOfInteger; END;
+    a: ARRAY 1 OF MapOfInteger;
 
 
 PROCEDURE ForEach();
 PROCEDURE ForEach();
 VAR
 VAR
@@ -127,9 +129,19 @@ BEGIN
     v5 <- returnNonLocalMap(v);
     v5 <- returnNonLocalMap(v);
 END;
 END;
 
 
+PROCEDURE passByRef(VAR m: MapOfInteger);
+BEGIN
+    m["abc"] := 123;
+    ASSERT("abc" IN m);
+END;
+
 BEGIN
 BEGIN
     FOREACH v, k IN m DO
     FOREACH v, k IN m DO
         FOREACH v2, k2 IN m DO
         FOREACH v2, k2 IN m DO
         END;
         END;
     END;
     END;
+
+    passByRef(m);
+    passByRef(r.m);
+    passByRef(a[0]);
 END test.
 END test.