Selaa lähdekoodia

dynamic arrays of records/arrays

Vladislav Folts 10 vuotta sitten
vanhempi
commit
cab7a9a95b

BIN
bin/compiled.zip


+ 6 - 0
src/context.js

@@ -1880,6 +1880,12 @@ exports.ModuleDeclaration = ChainedContext.extend({
     qualifyScope: function(scope){
         if (scope != this.__moduleScope && scope instanceof Scope.Module){
             var id = Scope.moduleSymbol(scope).id();
+            
+            // implicitly imported module, e.g.: record.pointerToRecordFromAnotherModule.field
+            // should not be used in code generation, 
+            // just return non-empty value to indicate this is not current module
+            if (!(id in this.__imports))
+                return "module '" + id + "' is not imported";
             return this.__imports[id].id() + ".";
         }
         return "";

+ 12 - 6
src/eberon/EberonTypes.ob

@@ -33,7 +33,7 @@ TYPE
     DynamicArrayAddCallGenerator = RECORD(Procedure.CallGenerator)
         cx: LanguageContext.PType;
         elementsType: Types.PType;
-        argCode: Procedure.PArgumentsCode
+        code: STRING
     END;
 
     DynamicArrayMethod = RECORD(Procedure.Std)
@@ -150,26 +150,32 @@ END DynamicArrayMethodField.asVar;
 
 PROCEDURE DynamicArrayAddCallGenerator.handleArgument(e: Code.PExpression);
 BEGIN
-    IF SELF.argCode # NIL THEN
+    IF SELF.code # "" THEN
         Errors.raise("method 'add' expects one argument, got many");
     END;
 
-    SELF.argCode := Procedure.makeArgumentsCode(SELF.cx);
+    argCode <- Procedure.makeArgumentsCode(SELF.cx);
     Procedure.checkArgument(
         e, 
         Types.makeProcedureArgument(SELF.elementsType, FALSE), 
         0, 
-        SELF.argCode, 
+        argCode, 
         SELF.cx.types);
+    SELF.code := argCode.result();
+    
+    t <- e.type();
+    IF (t IS Types.PRecord) OR (t IS Types.PArray) THEN
+        SELF.code := SELF.cx.rtl.clone(SELF.code);
+    END;
 END DynamicArrayAddCallGenerator.handleArgument;
 
 PROCEDURE DynamicArrayAddCallGenerator.end(): Code.PExpression;
 BEGIN
-    IF SELF.argCode = NIL THEN
+    IF SELF.code = "" THEN
         Errors.raise("method 'add' expects one argument, got nothing");
     END;
     RETURN Code.makeSimpleExpression(
-            "(" + SELF.argCode.result() + ")",
+            "(" + SELF.code + ")",
             NIL)
 END DynamicArrayAddCallGenerator.end;
 

+ 1 - 0
src/ob/OberonRtl.ob

@@ -1,6 +1,7 @@
 MODULE OberonRtl;
 TYPE
     Type* = RECORD
+        clone*: PROCEDURE(s: STRING): STRING;
         copy*: PROCEDURE(s1, s2: STRING): STRING;
         strCmp*: PROCEDURE(s1, s2: STRING): STRING;
         assignArrayFromString*: PROCEDURE(s1, s2: STRING): STRING;

+ 55 - 14
test/expected/eberon/dynamic_array.js

@@ -41,6 +41,42 @@ var RTL$ = {
                     to[prop] = v;
             }
         }
+    },
+    clone: function (from){
+        var to;
+        var len;
+        var i;
+        var Ctr = from.constructor;
+        if (Ctr == Uint16Array){
+            len = from.length;
+            to = this.__makeCharArray(len);
+            for(i = 0; i < len; ++i)
+                to[i] = from[i];
+        }
+        else {
+            to = new Ctr();
+            if (Ctr == Array)
+                len = from.length;
+                if (len){
+                    if (typeof from[0] != "object")
+                        for(i = 0; i < len; ++i)
+                            to[i] = from[i];
+                    else
+                        for(i = 0; i < len; ++i){
+                            var o = from[i];
+                            if (o !== null)
+                                to[i] = this.clone(o);
+                        }
+                }
+            else
+                this.copy(from, to);
+        }
+        return to;
+    },
+    __makeCharArray: function (length){
+        var result = new Uint16Array(length);
+        result.charCodeAt = function(i){return this[i];};
+        return result;
     }
 };
 var m = function (){
@@ -49,25 +85,30 @@ var T = RTL$.extend({
 		this.a = [];
 	}
 });
-var a = [];
 var r = new T();
+var a = RTL$.makeArray(3, 0);
+var dynamicInt = [];
+var dynamicString = [];
+var dynamicByte = [];
+var dynamicRecord = [];
+var dynamicArrayOfStaticArrayInt = [];
+var i = 0;
+var s = '';
+var byte = 0;
 
 function assignDynamicArrayFromStatic(){
 	var static$ = RTL$.makeArray(3, 0);
 	var dynamic = [];
-	var dynamicString = [];
-	var dynamicByte = [];
-	var i = 0;
-	var s = '';
-	var byte = 0;
 	RTL$.copy(static$, dynamic);
-	dynamic.push(3);
-	dynamic.push(i);
-	dynamic.push(byte);
-	dynamicString.push("abc");
-	dynamicString.push("\"");
-	dynamicString.push(s);
-	dynamicByte.push(byte);
-	dynamicByte.push(i & 0xFF);
 }
+dynamicInt.push(3);
+dynamicInt.push(i);
+dynamicInt.push(byte);
+dynamicString.push("abc");
+dynamicString.push("\"");
+dynamicString.push(s);
+dynamicByte.push(byte);
+dynamicByte.push(i & 0xFF);
+dynamicRecord.push(RTL$.clone(r));
+dynamicArrayOfStaticArrayInt.push(RTL$.clone(a));
 }();

+ 19 - 10
test/input/eberon/dynamic_array.ob

@@ -3,25 +3,32 @@ TYPE
     T = RECORD
         a: ARRAY * OF INTEGER
     END;
+
+    A = ARRAY 3 OF INTEGER;
 VAR
-    a: ARRAY * OF INTEGER;
     r: T;
-
-PROCEDURE assignDynamicArrayFromStatic();
-VAR 
-    static: ARRAY 3 OF INTEGER;
-    dynamic: ARRAY * OF INTEGER;
+    a: A;
+    dynamicInt: ARRAY * OF INTEGER;
     dynamicString: ARRAY * OF STRING;
     dynamicByte: ARRAY * OF BYTE;
+    dynamicRecord: ARRAY * OF T;
+    dynamicArrayOfStaticArrayInt: ARRAY * OF A;
     i: INTEGER;
     s: STRING;
     byte: BYTE;
+
+PROCEDURE assignDynamicArrayFromStatic();
+VAR 
+    static: ARRAY 3 OF INTEGER;
+    dynamic: ARRAY * OF INTEGER;
 BEGIN
     dynamic := static;
+END assignDynamicArrayFromStatic;
 
-    dynamic.add(3);
-    dynamic.add(i);
-    dynamic.add(byte);
+BEGIN
+    dynamicInt.add(3);
+    dynamicInt.add(i);
+    dynamicInt.add(byte);
 
     dynamicString.add("abc");
     dynamicString.add(22X);
@@ -29,6 +36,8 @@ BEGIN
     
     dynamicByte.add(byte);
     dynamicByte.add(i);
-END assignDynamicArrayFromStatic;
 
+    dynamicRecord.add(r);
+
+    dynamicArrayOfStaticArrayInt.add(a);
 END m.

+ 16 - 2
test/test_unit_eberon.js

@@ -931,15 +931,29 @@ exports.suite = {
         ),
         "add": testWithContext(
             context(grammar.statement, 
-                    "VAR a: ARRAY * OF INTEGER; byte: BYTE;"),
+                    "VAR a: ARRAY * OF INTEGER;"
+                     + "a2: ARRAY * OF ARRAY * OF INTEGER;"
+                     + "aStatic: ARRAY 3 OF INTEGER;"
+                     + "byte: BYTE;"),
             pass("a.add(123)",
-                 "a.add(byte)"),
+                 "a.add(byte)",
+                 "a2.add(a)",
+                 "a2.add(aStatic)"
+                 ),
             fail(["a.add := NIL", "cannot assign to method"],
                  ["v <- a.add", "dynamic array method 'add' cannot be referenced"],                
                  ["a.add()", "method 'add' expects one argument, got nothing"],
                  ["a.add(1, 2)", "method 'add' expects one argument, got many"],                
                  ["a.add(TRUE)", "type mismatch for argument 1: 'BOOLEAN' cannot be converted to 'INTEGER'"]                
                 )
+        ),
+        "add open array to dynamic array of static arrays": testWithContext(
+            context(grammar.declarationSequence, 
+                    "VAR a: ARRAY * OF ARRAY 3 OF INTEGER;"),
+            pass(),
+            fail(["PROCEDURE p(paramA: ARRAY OF INTEGER); BEGIN a.add(paramA); END p", 
+                  "type mismatch for argument 1: 'ARRAY OF INTEGER' cannot be converted to 'ARRAY 3 OF INTEGER'"]                
+                )
         )
     }
 };