Selaa lähdekoodia

dynamic arrays code generation (in process)

Vladislav Folts 11 vuotta sitten
vanhempi
commit
015410e645

BIN
bin/compiled.zip


+ 3 - 7
src/context.js

@@ -379,7 +379,7 @@ exports.Designator = ChainedContext.extend({
         if (!isArray && !(type instanceof Type.String))
         if (!isArray && !(type instanceof Type.String))
             throw new Errors.Error("ARRAY or string expected, got '" + type.description() + "'");
             throw new Errors.Error("ARRAY or string expected, got '" + type.description() + "'");
 
 
-        var length = isArray ? Type.arrayLength(type) : Type.stringLen(type);
+        var length = isArray ? type.length() : Type.stringLen(type);
         if (!isArray && !length)
         if (!isArray && !length)
             throw new Errors.Error("cannot index empty string" );
             throw new Errors.Error("cannot index empty string" );
         var indexType = isArray ? Type.arrayElementsType(type) : basicTypes.ch;
         var indexType = isArray ? Type.arrayElementsType(type) : basicTypes.ch;
@@ -483,9 +483,7 @@ exports.FormalType = HandleSymbolAsType.extend({
     },
     },
     setType: function(type){           
     setType: function(type){           
         for(var i = 0; i < this.__arrayDimension; ++i)
         for(var i = 0; i < this.__arrayDimension; ++i)
-            type = Type.makeArray(undefined,
-                                  type,
-                                  0);
+            type = Type.makeOpenArray(type);
         this.parent().setType(type);
         this.parent().setType(type);
 
 
     },
     },
@@ -763,9 +761,7 @@ exports.ArrayDecl = HandleSymbolAsType.extend({
         return rtl.makeArray(dimensions + ", " + initializer);
         return rtl.makeArray(dimensions + ", " + initializer);
     },
     },
     _makeType: function(elementsType, init, length){
     _makeType: function(elementsType, init, length){
-        return Type.makeArray(init,
-                              elementsType,
-                              length);
+        return Type.makeStaticArray(init, elementsType, length);
     }
     }
 });
 });
 
 

+ 5 - 11
src/eberon/EberonCast.ob

@@ -2,14 +2,8 @@ MODULE EberonCast;
 IMPORT Cast, EberonString, EberonTypes, Types;
 IMPORT Cast, EberonString, EberonTypes, Types;
 
 
 PROCEDURE isOpenCharArray(type: Types.PType): BOOLEAN;
 PROCEDURE isOpenCharArray(type: Types.PType): BOOLEAN;
-VAR
-    result: BOOLEAN;
-BEGIN
-    IF type IS Types.PArray THEN
-        result := (Types.arrayElementsType(type^) = Types.basic.ch)
-                & (Types.arrayLength(type^) = Types.openArrayLength);
-    END;
-    RETURN result
+    RETURN (type IS Types.POpenArray) 
+         & (Types.arrayElementsType(type^) = Types.basic.ch)
 END isOpenCharArray;
 END isOpenCharArray;
 
 
 PROCEDURE implicit*(from, to: Types.PType; toVar: BOOLEAN; ops: Cast.Operations; VAR op: Cast.PCastOp): INTEGER;
 PROCEDURE implicit*(from, to: Types.PType; toVar: BOOLEAN; ops: Cast.Operations; VAR op: Cast.PCastOp): INTEGER;
@@ -23,10 +17,10 @@ BEGIN
         ELSE
         ELSE
             result := Cast.errNo;
             result := Cast.errNo;
         END;
         END;
-    ELSIF (from IS Types.PArray) & EberonTypes.isDynamicArray(to^) 
+    ELSIF (from IS Types.PArray) & (to IS EberonTypes.PDynamicArray)
         & Cast.areTypesExactlyMatch(Types.arrayElementsType(from^), 
         & Cast.areTypesExactlyMatch(Types.arrayElementsType(from^), 
-                                    Types.arrayElementsType(to^(Types.Array))) THEN
-        IF toVar & ~EberonTypes.isDynamicArray(from^) THEN
+                                    Types.arrayElementsType(to^)) THEN
+        IF toVar & ~(from IS EberonTypes.PDynamicArray) THEN
             result := Cast.errVarParameter;
             result := Cast.errVarParameter;
         ELSE
         ELSE
             result := Cast.errNo;
             result := Cast.errNo;

+ 20 - 20
src/eberon/EberonTypes.ob

@@ -1,45 +1,45 @@
 MODULE EberonTypes;
 MODULE EberonTypes;
-IMPORT Types;
+IMPORT Context, Types;
 
 
 CONST
 CONST
     dynamicArrayLength* = Types.openArrayLength - 1;
     dynamicArrayLength* = Types.openArrayLength - 1;
 
 
 TYPE
 TYPE
-    Array = RECORD(Types.Array)
+    DynamicArray* = RECORD(Types.Array)
     END;
     END;
-    PArray = POINTER TO Array;
+    PDynamicArray* = POINTER TO DynamicArray;
 
 
-PROCEDURE isDynamicArray*(VAR type: Types.Type): BOOLEAN;
-    RETURN (type IS Types.Array) & (Types.arrayLength(type) = dynamicArrayLength)
-END isDynamicArray;
-
-PROCEDURE arrayDimensionDescription*(dim: INTEGER): STRING;
+PROCEDURE arrayDimensionDescription*(VAR a: Types.Array): STRING;
 VAR
 VAR
     result: STRING;
     result: STRING;
 BEGIN
 BEGIN
-    IF dim = dynamicArrayLength THEN
+    IF a IS DynamicArray THEN
         result := "*";
         result := "*";
     ELSE
     ELSE
-        result := Types.arrayDimensionDescription(dim);
+        result := Types.arrayDimensionDescription(a);
     END;
     END;
     RETURN result
     RETURN result
 END arrayDimensionDescription;
 END arrayDimensionDescription;
 
 
-PROCEDURE Array.description(): STRING;
+PROCEDURE DynamicArray.initializer(cx: Context.Type; forNew: BOOLEAN): STRING;
+    RETURN "[]"
+END DynamicArray.initializer;
+
+PROCEDURE DynamicArray.length(): INTEGER;
+    RETURN Types.openArrayLength
+END DynamicArray.length;
+
+PROCEDURE DynamicArray.description(): STRING;
     RETURN Types.arrayDescription(SELF, arrayDimensionDescription)
     RETURN Types.arrayDescription(SELF, arrayDimensionDescription)
-END Array.description;
+END DynamicArray.description;
 
 
-PROCEDURE makeArray*(
-    initializer: STRING;
-    elementsType: Types.PType;
-    len: INTEGER (* see openArrayLength *)
-    ): PArray;
+PROCEDURE makeDynamicArray*(elementsType: Types.PType): PDynamicArray;
 VAR
 VAR
-    result: PArray;
+    result: PDynamicArray;
 BEGIN
 BEGIN
     NEW(result);
     NEW(result);
-    Types.initArray(initializer, elementsType, len, result^);
+    Types.initArray(elementsType, result^);
     RETURN result
     RETURN result
-END makeArray;
+END makeDynamicArray;
 
 
 END EberonTypes.
 END EberonTypes.

+ 10 - 8
src/eberon/eberon_context.js

@@ -284,7 +284,7 @@ var InPlaceVariableInit = Context.Chained.extend({
             this._code += this.language().rtl.clone(e.code());
             this._code += this.language().rtl.clone(e.code());
         }
         }
         else if (type instanceof Type.Array){
         else if (type instanceof Type.Array){
-            if (Type.arrayLength(type) == Type.openArrayLength)
+            if (type.length() == Type.openArrayLength)
                 throw new Errors.Error("cannot initialize variable '" + this.__id + "' with open array");
                 throw new Errors.Error("cannot initialize variable '" + this.__id + "' with open array");
             this._code += this.language().rtl.clone(e.code());
             this._code += this.language().rtl.clone(e.code());
         }
         }
@@ -1119,7 +1119,9 @@ var ArrayDecl = Context.ArrayDecl.extend({
         return Context.ArrayDecl.prototype._makeInit.call(this, type, dimensions, length);
         return Context.ArrayDecl.prototype._makeInit.call(this, type, dimensions, length);
     },
     },
     _makeType: function(elementsType, init, length){
     _makeType: function(elementsType, init, length){
-        return EberonTypes.makeArray(init, elementsType, length);
+        return length == EberonTypes.dynamicArrayLength
+            ? EberonTypes.makeDynamicArray(elementsType)
+            : Type.makeStaticArray(init, elementsType, length);
     }
     }
 });
 });
 
 
@@ -1129,7 +1131,7 @@ function assertArgumentIsNotNonVarDynamicArray(msg){
         if (!arg.isVar){
         if (!arg.isVar){
             var type = arg.type;
             var type = arg.type;
             while (type instanceof Type.Array){
             while (type instanceof Type.Array){
-                if (EberonTypes.isDynamicArray(type))
+                if (type instanceof EberonTypes.DynamicArray)
                     throw new Errors.Error("dynamic array has no use as non-VAR argument '" + msg.name + "'");
                     throw new Errors.Error("dynamic array has no use as non-VAR argument '" + msg.name + "'");
                 type = Type.arrayElementsType(type);
                 type = Type.arrayElementsType(type);
             }
             }
@@ -1146,7 +1148,7 @@ var FormalParameters = Context.FormalParameters.extend({
         return Context.FormalParameters.prototype.handleMessage.call(this, msg);
         return Context.FormalParameters.prototype.handleMessage.call(this, msg);
     },
     },
     _checkResultType: function(type){
     _checkResultType: function(type){
-        if (EberonTypes.isDynamicArray(type))
+        if (type instanceof EberonTypes.DynamicArray)
             return;
             return;
         Context.FormalParameters.prototype._checkResultType.call(this, type);
         Context.FormalParameters.prototype._checkResultType.call(this, type);
     }
     }
@@ -1160,9 +1162,9 @@ var FormalType = Context.HandleSymbolAsType.extend({
     },
     },
     setType: function(type){           
     setType: function(type){           
         for(var i = this.__arrayDimensions.length; i--;){
         for(var i = this.__arrayDimensions.length; i--;){
-            var length = this.__arrayDimensions[i] ? EberonTypes.dynamicArrayLength 
-                                                  : Type.openArrayLength;
-            type = EberonTypes.makeArray(undefined, type, length);
+            type = this.__arrayDimensions[i] 
+                ? EberonTypes.makeDynamicArray(type)
+                : Type.makeOpenArray(type);
         }
         }
         this.parent().setType(type);
         this.parent().setType(type);
     },
     },
@@ -1185,7 +1187,7 @@ var FormalParametersProcDecl = Context.FormalParametersProcDecl.extend({
         return Context.FormalParametersProcDecl.prototype.handleMessage.call(this, msg);
         return Context.FormalParametersProcDecl.prototype.handleMessage.call(this, msg);
     },
     },
     _checkResultType: function(type){
     _checkResultType: function(type){
-        if (EberonTypes.isDynamicArray(type))
+        if (type instanceof EberonTypes.DynamicArray)
             return;
             return;
         Context.FormalParametersProcDecl.prototype._checkResultType.call(this, type);
         Context.FormalParametersProcDecl.prototype._checkResultType.call(this, type);
     }
     }

+ 3 - 3
src/ob/Cast.ob

@@ -105,7 +105,7 @@ BEGIN
     IF t1 = t2 THEN
     IF t1 = t2 THEN
         result := TRUE;
         result := TRUE;
     ELSIF (t1 IS Types.PArray) & (t2 IS Types.PArray) THEN
     ELSIF (t1 IS Types.PArray) & (t2 IS Types.PArray) THEN
-        result := (Types.arrayLength(t1^) = Types.arrayLength(t2^)) 
+        result := (t1.length() = t2.length()) 
                 & (areTypesMatch(Types.arrayElementsType(t1^), 
                 & (areTypesMatch(Types.arrayElementsType(t1^), 
                                  Types.arrayElementsType(t2^)));
                                  Types.arrayElementsType(t2^)));
     ELSIF (t1 IS Types.PPointer) & (t2 IS Types.PPointer) THEN
     ELSIF (t1 IS Types.PPointer) & (t2 IS Types.PPointer) THEN
@@ -163,8 +163,8 @@ BEGIN
             result := errNo;
             result := errNo;
         END;
         END;
     ELSIF (from IS Types.PArray) & (to IS Types.PArray) THEN
     ELSIF (from IS Types.PArray) & (to IS Types.PArray) THEN
-        IF ((Types.arrayLength(from^) = Types.arrayLength(to^))
-                OR (Types.arrayLength(to^) = Types.openArrayLength))
+        IF ((from.length() = to.length())
+                OR (to.length() = Types.openArrayLength))
             & areTypesExactlyMatch(Types.arrayElementsType(from^), 
             & areTypesExactlyMatch(Types.arrayElementsType(from^), 
                                    Types.arrayElementsType(to^)) THEN
                                    Types.arrayElementsType(to^)) THEN
             result := errNo;
             result := errNo;

+ 9 - 10
src/ob/Operator.ob

@@ -472,7 +472,6 @@ VAR
     designator: Code.PDesignator;
     designator: Code.PDesignator;
     info: Types.PId;
     info: Types.PId;
     leftCode, rightCode: STRING;
     leftCode, rightCode: STRING;
-    leftType, rightType: Types.PType;
     isArray: BOOLEAN;
     isArray: BOOLEAN;
     castOperation: Cast.PCastOp;
     castOperation: Cast.PCastOp;
     castExp: Code.PExpression;
     castExp: Code.PExpression;
@@ -481,10 +480,11 @@ VAR
 
 
     PROCEDURE assignArrayFromString(a: Types.Array; s: Types.String): STRING;
     PROCEDURE assignArrayFromString(a: Types.Array; s: Types.String): STRING;
     BEGIN
     BEGIN
-        IF Types.arrayLength(a) = Types.openArrayLength THEN
+        len <- a.length();
+        IF len = Types.openArrayLength THEN
             Errors.raise("string cannot be assigned to open " + a.description());
             Errors.raise("string cannot be assigned to open " + a.description());
-        ELSIF Types.stringLen(s) > Types.arrayLength(a) THEN
-            Errors.raise(String.fromInt(Types.arrayLength(a)) 
+        ELSIF Types.stringLen(s) > len THEN
+            Errors.raise(String.fromInt(len) 
                          + "-character ARRAY is too small for "
                          + "-character ARRAY is too small for "
                          + String.fromInt(Types.stringLen(s))
                          + String.fromInt(Types.stringLen(s))
                          + "-character string");
                          + "-character string");
@@ -501,22 +501,21 @@ BEGIN
 
 
     leftCode := left.lval();
     leftCode := left.lval();
     rightCode := right.code();
     rightCode := right.code();
-    leftType := left.type();
-    rightType := right.type();
+    leftType <- left.type();
+    rightType <- right.type();
 
 
     isArray := leftType IS Types.PArray;
     isArray := leftType IS Types.PArray;
     IF isArray
     IF isArray
         & (Types.arrayElementsType(leftType(Types.PArray)^) = Types.basic.ch)
         & (Types.arrayElementsType(leftType(Types.PArray)^) = Types.basic.ch)
         & (rightType IS Types.PString) THEN
         & (rightType IS Types.PString) THEN
-        result := assignArrayFromString(leftType(Types.PArray)^, rightType(Types.PString)^);
+        result := assignArrayFromString(leftType(Types.PArray)^, rightType^);
     ELSE
     ELSE
         IF cx.types.implicitCast(rightType, leftType, FALSE, castOperations, castOperation)
         IF cx.types.implicitCast(rightType, leftType, FALSE, castOperations, castOperation)
             # Cast.errNo THEN;
             # Cast.errNo THEN;
             Errors.raise("type mismatch: '" + leftCode + "' is '" + leftType.description()
             Errors.raise("type mismatch: '" + leftCode + "' is '" + leftType.description()
                          + "' and cannot be assigned to '" + rightType.description() + "' expression");
                          + "' and cannot be assigned to '" + rightType.description() + "' expression");
         END;
         END;
-        IF isArray & (rightType IS Types.PArray) 
-            & (Types.arrayLength(leftType(Types.PArray)^) = Types.openArrayLength) THEN
+        IF (leftType IS Types.POpenArray) & (rightType IS Types.PArray) THEN
             Errors.raise("'" + leftCode + "' is open '" + leftType.description() + "' and cannot be assigned");
             Errors.raise("'" + leftCode + "' is open '" + leftType.description() + "' and cannot be assigned");
         END;
         END;
         IF isArray OR (rightType IS Types.PRecord) THEN
         IF isArray OR (rightType IS Types.PRecord) THEN
@@ -799,7 +798,7 @@ PROCEDURE CastToUint8.make(rtl: OberonRtl.PType; e: Code.PExpression): Code.PExp
 END CastToUint8.make;
 END CastToUint8.make;
 
 
 BEGIN
 BEGIN
-    openArrayChar := Types.makeArray("", Types.basic.ch, Types.openArrayLength);
+    openArrayChar := Types.makeOpenArray(Types.basic.ch);
 
 
     NEW(castToUint8);
     NEW(castToUint8);
     castOperations.castToUint8 := castToUint8;
     castOperations.castToUint8 := castToUint8;

+ 49 - 30
src/ob/Types.ob

@@ -88,13 +88,21 @@ TYPE
     END;
     END;
 
 
     Array* = RECORD(NamedType)
     Array* = RECORD(NamedType)
+        PROCEDURE length*(): INTEGER;
+
+        elementsType: PType
+    END;
+    PArray* = POINTER TO Array;
+
+    OpenArray* = RECORD(Array)
+    END;
+    POpenArray* = POINTER TO OpenArray;
+
+    StaticArray* = RECORD(Array)
         mInitializer: STRING;
         mInitializer: STRING;
-        elementsType: PType;
         len: INTEGER
         len: INTEGER
     END;
     END;
 
 
-    PArray* = POINTER TO Array;
-
     PRecord* = POINTER TO Record;
     PRecord* = POINTER TO Record;
 
 
     Pointer* = RECORD(NamedType)
     Pointer* = RECORD(NamedType)
@@ -161,7 +169,7 @@ TYPE
 
 
     PModule* = POINTER TO Module;
     PModule* = POINTER TO Module;
 
 
-    ArrayDimensionDescriptionCallback = PROCEDURE(dim: INTEGER): STRING;
+    ArrayDimensionDescriptionCallback = PROCEDURE(VAR a: Array): STRING;
 
 
 VAR
 VAR
     basic*: RECORD
     basic*: RECORD
@@ -463,29 +471,29 @@ PROCEDURE Pointer.initializer(cx: Context.Type; forNew: BOOLEAN): STRING;
     RETURN "null"
     RETURN "null"
 END Pointer.initializer;
 END Pointer.initializer;
 
 
-PROCEDURE foldArrayDimensions(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;
-    IF (a.len # openArrayLength) & (elementsType IS PArray) THEN
+    IF ~(a IS OpenArray) & (elementsType IS PArray) THEN
         foldArrayDimensions(elementsType^, dimToStr, sizes, of);
         foldArrayDimensions(elementsType^, dimToStr, sizes, of);
-        sizes := dimToStr(a.len) + ", " + sizes;
+        sizes := dimToStr(a) + ", " + sizes;
     ELSE
     ELSE
-        sizes := dimToStr(a.len);
+        sizes := dimToStr(a);
         of := a.elementsType.description();
         of := a.elementsType.description();
     END
     END
 END foldArrayDimensions;
 END foldArrayDimensions;
 
 
-PROCEDURE arrayDimensionDescription*(dim: INTEGER): STRING;
+PROCEDURE arrayDimensionDescription*(VAR a: Array): STRING;
 VAR
 VAR
     result: STRING;
     result: STRING;
 BEGIN
 BEGIN
-    IF dim # openArrayLength THEN
-        result := Str.fromInt(dim);
+    IF ~(a IS OpenArray) THEN
+        result := Str.fromInt(a.length());
     END;
     END;
     RETURN result
     RETURN result
 END arrayDimensionDescription;
 END arrayDimensionDescription;
 
 
-PROCEDURE arrayDescription*(a: Array; dimToStr: ArrayDimensionDescriptionCallback): STRING;
+PROCEDURE arrayDescription*(VAR a: Array; dimToStr: ArrayDimensionDescriptionCallback): STRING;
 VAR
 VAR
     result: STRING;
     result: STRING;
     sizes, of: STRING;
     sizes, of: STRING;
@@ -506,17 +514,25 @@ PROCEDURE Array.description(): STRING;
     RETURN arrayDescription(SELF, arrayDimensionDescription)
     RETURN arrayDescription(SELF, arrayDimensionDescription)
 END Array.description;
 END Array.description;
 
 
-PROCEDURE Array.initializer(cx: Context.Type; forNew: BOOLEAN): STRING;
+PROCEDURE OpenArray.initializer(cx: Context.Type; forNew: BOOLEAN): STRING;
+    RETURN ""
+END OpenArray.initializer;
+
+PROCEDURE StaticArray.initializer(cx: Context.Type; forNew: BOOLEAN): STRING;
     RETURN SELF.mInitializer
     RETURN SELF.mInitializer
-END Array.initializer;
+END StaticArray.initializer;
 
 
 PROCEDURE arrayElementsType*(a: Array): PType;
 PROCEDURE arrayElementsType*(a: Array): PType;
     RETURN a.elementsType
     RETURN a.elementsType
 END arrayElementsType;
 END arrayElementsType;
 
 
-PROCEDURE arrayLength*(a: Array): INTEGER;
-    RETURN a.len
-END arrayLength;
+PROCEDURE OpenArray.length(): INTEGER;
+    RETURN openArrayLength
+END OpenArray.length;
+
+PROCEDURE StaticArray.length(): INTEGER;
+    RETURN SELF.len
+END StaticArray.length;
 
 
 PROCEDURE Procedure.initializer(cx: Context.Type; forNew: BOOLEAN): STRING;
 PROCEDURE Procedure.initializer(cx: Context.Type; forNew: BOOLEAN): STRING;
     RETURN "null"
     RETURN "null"
@@ -576,31 +592,34 @@ BEGIN
     RETURN result
     RETURN result
 END makeString;
 END makeString;
 
 
-PROCEDURE initArray*(
-    initializer: STRING;
-    elementsType: PType;
-    len: INTEGER; (* see openArrayLength *)
-    VAR result: Array
-    );
+PROCEDURE initArray*(elementsType: PType; VAR result: Array);
 BEGIN
 BEGIN
-    (*result.name := name;*)
-    result.mInitializer := initializer;
     result.elementsType := elementsType;
     result.elementsType := elementsType;
-    result.len := len;
 END initArray;
 END initArray;
 
 
-PROCEDURE makeArray*(
+PROCEDURE makeOpenArray*(elementsType: PType): PArray;
+VAR
+    result: POpenArray;
+BEGIN
+    NEW(result);
+    initArray(elementsType, result^);
+    RETURN result
+END makeOpenArray;
+
+PROCEDURE makeStaticArray*(
     initializer: STRING;
     initializer: STRING;
     elementsType: PType;
     elementsType: PType;
     len: INTEGER (* see openArrayLength *)
     len: INTEGER (* see openArrayLength *)
     ): PArray;
     ): PArray;
 VAR
 VAR
-    result: PArray;
+    result: POINTER TO StaticArray;
 BEGIN
 BEGIN
     NEW(result);
     NEW(result);
-    initArray(initializer, elementsType, len, result^);
+    initArray(elementsType, result^);
+    result.mInitializer := initializer;
+    result.len := len;
     RETURN result
     RETURN result
-END makeArray;
+END makeStaticArray;
 
 
 PROCEDURE makePointer*(name: STRING; base: PTypeId): PPointer;
 PROCEDURE makePointer*(name: STRING; base: PTypeId): PPointer;
 VAR
 VAR

+ 57 - 0
test/expected/eberon/dynamic_array.js

@@ -1,3 +1,60 @@
+var RTL$ = {
+    extend: function extend(methods){
+        function Type(){
+            for(var m in methods)
+                this[m] = methods[m];
+        }
+        Type.prototype = this.prototype;
+
+        var result = methods.init;
+        result.prototype = new Type(); // inherit this.prototype
+        result.prototype.constructor = result; // to see constructor name in diagnostic
+        
+        result.extend = extend;
+        return result;
+    },
+    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;
+    },
+    copy: function (from, to){
+        for(var prop in to){
+            if (to.hasOwnProperty(prop)){
+                var v = from[prop];
+                if (v !== null && typeof v == "object")
+                    this.copy(v, to[prop]);
+                else
+                    to[prop] = v;
+            }
+        }
+    }
+};
 var m = function (){
 var m = function (){
+var T = RTL$.extend({
+	init: function T(){
+		this.a = [];
+	}
+});
 var a = [];
 var a = [];
+var r = new T();
+
+function assignDynamicArrayFromStatic(){
+	var static$ = RTL$.makeArray(3, 0);
+	var dynamic = [];
+	RTL$.copy(static$, dynamic);
+}
 }();
 }();

+ 14 - 0
test/input/eberon/dynamic_array.ob

@@ -1,4 +1,18 @@
 MODULE m;
 MODULE m;
+TYPE
+    T = RECORD
+        a: ARRAY * OF INTEGER
+    END;
 VAR
 VAR
     a: ARRAY * OF INTEGER;
     a: ARRAY * OF INTEGER;
+    r: T;
+
+PROCEDURE assignDynamicArrayFromStatic();
+VAR 
+    static: ARRAY 3 OF INTEGER;
+    dynamic: ARRAY * OF INTEGER;
+BEGIN
+    dynamic := static;
+END assignDynamicArrayFromStatic;
+
 END m.
 END m.

+ 17 - 0
test/input/eberon/run/dynamic_array.ob

@@ -0,0 +1,17 @@
+MODULE m;
+VAR
+    static: ARRAY 3 OF INTEGER;
+    dynamic: ARRAY * OF INTEGER;
+BEGIN
+    static[0] := 1;
+    static[1] := 2;
+    static[2] := 3;
+    
+    ASSERT(LEN(dynamic) = 0);
+    dynamic := static;
+    (*ASSERT(LEN(dynamic) = 3);
+    ASSERT(dynamic[0] = 1);
+    ASSERT(dynamic[1] = 2);
+    ASSERT(dynamic[2] = 3);*)
+
+END m.

+ 13 - 0
test/test_unit_eberon.js

@@ -759,6 +759,19 @@ exports.suite = {
             pass("paVar(a)",
             pass("paVar(a)",
                  "paVarOpen(a)"),
                  "paVarOpen(a)"),
             fail(["paVar(aStatic)", "type mismatch for argument 1: cannot pass 'ARRAY 3 OF INTEGER' as VAR parameter of type 'ARRAY * OF INTEGER'"])
             fail(["paVar(aStatic)", "type mismatch for argument 1: cannot pass 'ARRAY 3 OF INTEGER' as VAR parameter of type 'ARRAY * OF INTEGER'"])
+        ),
+        "assign": testWithContext(
+            context(grammar.statement, 
+                    "VAR stat: ARRAY 3 OF INTEGER; dynamic: ARRAY * OF INTEGER;"),
+            pass("dynamic := stat"),
+            fail(["stat := dynamic", "type mismatch: 'stat' is 'ARRAY 3 OF INTEGER' and cannot be assigned to 'ARRAY * OF INTEGER' expression"])
+        ),
+        "indexing": testWithContext(
+            context(grammar.expression, 
+                    "VAR a: ARRAY * OF INTEGER;"),
+            pass("a[0]", "a[1]"),
+            fail(["a[-1]", "index is negative: -1"], 
+                 ["a[-2]", "index is negative: -2"])
         )
         )
     }
     }
 };
 };