Browse Source

array fixes + corrections to confirm report

Vladislav Folts 11 years ago
parent
commit
f139f12a34
6 changed files with 83 additions and 28 deletions
  1. 2 1
      src/cast.js
  2. 3 3
      src/context.js
  3. 0 9
      src/operator.js
  4. 21 2
      src/type.js
  5. 2 2
      test/expected/array.js
  6. 55 11
      test/test_unit.js

+ 2 - 1
src/cast.js

@@ -75,7 +75,8 @@ function implicitCast(from, to){
             };
     }
     else if (from instanceof ArrayType && to instanceof ArrayType)
-        return implicitCast(from.elementsType(), to.elementsType());
+        return (to.length() === undefined || to.length() === from.length())
+            && implicitCast(from.elementsType(), to.elementsType());
     else if (from instanceof PointerType && to instanceof PointerType){
         if (findPointerBaseType(to, from))
             return doNoting;

+ 3 - 3
src/context.js

@@ -625,10 +625,10 @@ exports.ArrayDecl = ChainedContext.extend({
             ? "function(){return " + type.initializer(this) + ";}"
             : type.initializer(this);
         var dimensions = "";
-        for(var i = 0; i < this.__dimensions.length; ++i){
+        for(var i = this.__dimensions.length; i-- ;){
             var length = this.__dimensions[i];
-            dimensions += (dimensions.length ? ", " : "") + length;
-            var arrayInit = i == this.__dimensions.length - 1
+            dimensions = length + (dimensions.length ? ", " + dimensions : "");
+            var arrayInit = !i
                 ? this.rtl().makeArray(dimensions + ", " + initializer)
                 : undefined;
             type = new Type.Array("ARRAY OF " + type.name()

+ 0 - 9
src/operator.js

@@ -97,15 +97,6 @@ function assign(left, right, context){
             throw new Errors.Error("'" + leftCode
                                  + "' is open '" + leftType.description()
                                  + "' and cannot be assigned");
-        if (rightType.length() === undefined)
-            throw new Errors.Error("'" + leftCode
-                                 + "' cannot be assigned to open '"
-                                 + rightType.description() + "'");
-        if (leftType.length() != rightType.length())
-            throw new Errors.Error("array size mismatch: '" + leftCode
-                                 + "' has size " + leftType.length()
-                                 + " and cannot be copied to the array with size "
-                                 + rightType.length());
     }
     
     if (isArray || rightType instanceof Type.Record)

+ 21 - 2
src/type.js

@@ -55,14 +55,32 @@ var BasicType = Type.extend({
 
 exports.Basic = BasicType;
 
-exports.Array = BasicType.extend({
+function foldArrayDimensions(a){
+    var result = a.length();
+    var next = a.elementsType();
+    if (result !== undefined
+        && next instanceof ArrayType){
+        var r = foldArrayDimensions(next);
+        return [result + ", " + r[0], r[1]];
+    }
+    return [result, next.description()];
+}
+
+var ArrayType = BasicType.extend({
     init: function ArrayType(name, initializer, elementsType, size){
         BasicType.prototype.init.call(this, name, initializer);
         this.__elementsType = elementsType;
         this.__size = size;
     },
     elementsType: function(){return this.__elementsType;},
-    length: function(){return this.__size;}
+    length: function(){return this.__size;},
+    description: function(){
+        if (this.__elementsType === undefined) // special arrays, see procedure "LEN"
+            return this.name();
+        var desc = foldArrayDimensions(this);
+        var sizes = (desc[0] === undefined ? "" : " " + desc[0]);
+        return "ARRAY" + sizes + " OF " + desc[1];
+    }
 });
 
 exports.Pointer = BasicType.extend({
@@ -191,6 +209,7 @@ var Module = Id.extend({
     name: function(){return this.__name;}
 });
 
+exports.Array = ArrayType;
 exports.Variable = Variable;
 exports.VariableRef = VariableRef;
 exports.ExportedVariable = ExportedVariable;

+ 2 - 2
test/expected/array.js

@@ -60,10 +60,10 @@ function p(){
 	a3[0] = 1;
 }
 
-function p1(a/*ARRAY OF INTEGER*/){
+function p1(a/*ARRAY 10 OF INTEGER*/){
 }
 
-function p2(a/*VAR ARRAY OF INTEGER*/){
+function p2(a/*VAR ARRAY 10 OF INTEGER*/){
 	p1(a);
 }
 a1[0] = 1;

+ 55 - 11
test/test_unit.js

@@ -298,7 +298,8 @@ var testSuite = {
          "T = ARRAY 10 OF BOOLEAN",
          "T = ARRAY 1 + 2 OF INTEGER",
          "T = ARRAY c1 OF INTEGER",
-         "T = ARRAY ORD({0..5} <= {0..8}) OF INTEGER"
+         "T = ARRAY ORD({0..5} <= {0..8}) OF INTEGER",
+         "T = ARRAY 1, 2 OF ARRAY 3, 4 OF INTEGER"
          ),
     fail(["T = ARRAY 0 OF INTEGER",
           "array size must be greater than 0, got 0"],
@@ -585,7 +586,7 @@ var testSuite = {
         ),
     fail(["COPY(ac3, \"abc\")", "expression cannot be used as VAR parameter"],
          ["COPY(\"abcd\", ac3)", "3-character ARRAY is too small for 4-character string"],
-         ["COPY(ac3, ac4)", "array size mismatch: 'ac4' has size 4 and cannot be copied to the array with size 3"]
+         ["COPY(ac3, ac4)", "type mismatch: 'ac4' is 'ARRAY 4 OF CHAR' and cannot be assigned to 'ARRAY 3 OF CHAR' expression"]
          )
 ),
 "PACK": testWithContext(
@@ -650,7 +651,7 @@ var testSuite = {
          ["VAR a: ARRAY 10 OF BOOLEAN; BEGIN a[0,0] := TRUE END",
           "ARRAY expected, got 'BOOLEAN'"],
          ["VAR a: ARRAY 10, 20 OF BOOLEAN; BEGIN a[0] := TRUE END",
-          "type mismatch: 'a[0]' is 'ARRAY OF BOOLEAN' and cannot be assigned to 'BOOLEAN' expression"],
+          "type mismatch: 'a[0]' is 'ARRAY 20 OF BOOLEAN' and cannot be assigned to 'BOOLEAN' expression"],
          ["VAR a: ARRAY 10 OF INTEGER; BEGIN a[10] := 0 END",
           "index out of bounds: maximum possible index is 9, got 10"],
          ["CONST c1 = 5; VAR a: ARRAY 10 OF INTEGER; BEGIN a[10 + c1] := 0 END",
@@ -1081,7 +1082,7 @@ var testSuite = {
          "ch1 := 22X"),
     fail(["a1 := \"abcd\"", "3-character ARRAY is too small for 4-character string"],
          ["intArray := \"abcd\"",
-          "type mismatch: 'intArray' is 'ARRAY OF INTEGER' and cannot be assigned to 'multi-character string' expression"])
+          "type mismatch: 'intArray' is 'ARRAY 10 OF INTEGER' and cannot be assigned to 'multi-character string' expression"])
     ),
 "string relations": testWithContext(
     context(Grammar.expression,
@@ -1099,14 +1100,25 @@ var testSuite = {
             + "intArray: ARRAY 10 OF INTEGER;"
             + "intArray2: ARRAY 10 OF INTEGER;"
             + "intArray3: ARRAY 5 OF INTEGER;"
+            + "intArray23m1: ARRAY 2 OF ARRAY 3 OF INTEGER;"
+            + "intArray23m2: ARRAY 2, 3 OF INTEGER;"
+            + "intArray24m: ARRAY 2, 4 OF INTEGER;"
+            + "intArray43m: ARRAY 4, 3 OF INTEGER;"
             ),
-    pass("intArray := intArray2"),
+    pass("intArray := intArray2",
+         "intArray23m1 := intArray23m2",
+         "intArray23m2 := intArray23m1",
+         "intArray43m[0] := intArray23m1[0]"
+         ),
     fail(["intArray := charArray",
-         "type mismatch: 'intArray' is 'ARRAY OF INTEGER' and cannot be assigned to 'ARRAY OF CHAR' expression"],
+         "type mismatch: 'intArray' is 'ARRAY 10 OF INTEGER' and cannot be assigned to 'ARRAY 3 OF CHAR' expression"],
          ["intArray2 := intArray3",
-          "array size mismatch: 'intArray2' has size 10 and cannot be copied to the array with size 5"],
+          "type mismatch: 'intArray2' is 'ARRAY 10 OF INTEGER' and cannot be assigned to 'ARRAY 5 OF INTEGER' expression"],
          ["intArray3 := charArray",
-          "type mismatch: 'intArray3' is 'ARRAY OF INTEGER' and cannot be assigned to 'ARRAY OF CHAR' expression"])
+          "type mismatch: 'intArray3' is 'ARRAY 5 OF INTEGER' and cannot be assigned to 'ARRAY 3 OF CHAR' expression"],
+         ["intArray24m := intArray23m1",
+          "type mismatch: 'intArray24m' is 'ARRAY 2, 4 OF INTEGER' and cannot be assigned to 'ARRAY 2, 3 OF INTEGER' expression"]
+          )
     ),
 "record assignment": testWithContext(
     context(Grammar.statement,
@@ -1120,7 +1132,7 @@ var testSuite = {
     fail(["r1 := r2", "type mismatch: 'r1' is 'T1' and cannot be assigned to 'T2' expression"],
          ["r1 := b1", "type mismatch: 'r1' is 'T1' and cannot be assigned to 'Base1' expression"])
     ),
-"open Array assignment fails": testWithGrammar(
+"open array assignment fails": testWithGrammar(
     Grammar.procedureDeclaration,
     pass(),
     fail(["PROCEDURE p(s1, s2: ARRAY OF CHAR); BEGIN s1 := s2 END p",
@@ -1128,7 +1140,39 @@ var testSuite = {
          ["PROCEDURE p(VAR s1, s2: ARRAY OF CHAR); BEGIN s1 := s2 END p",
           "'s1' is open 'ARRAY OF CHAR' and cannot be assigned"],
          ["PROCEDURE p(s1: ARRAY OF CHAR); VAR s2: ARRAY 10 OF CHAR; BEGIN s2 := s1 END p",
-          "'s2' cannot be assigned to open 'ARRAY OF CHAR'"])
+          "type mismatch: 's2' is 'ARRAY 10 OF CHAR' and cannot be assigned to 'ARRAY OF CHAR' expression"])
+    ),
+"open array type as procedure parameter": testWithContext(
+    context(Grammar.procedureDeclaration,
+            "TYPE A = ARRAY 3 OF INTEGER;"
+            ),
+    pass("PROCEDURE p(a: ARRAY OF INTEGER); BEGIN END p",
+         "PROCEDURE p(a: ARRAY OF ARRAY OF INTEGER); BEGIN END p",
+         "PROCEDURE p(a: ARRAY OF A); BEGIN END p"
+        ),
+    fail(["PROCEDURE p(a: ARRAY OF ARRAY 3 OF INTEGER); BEGIN END p",
+          "not parsed"]
+        )
+    ),
+"non-open array type as procedure parameter": testWithContext(
+    context(Grammar.procedureDeclaration,
+            "TYPE A = ARRAY 2 OF INTEGER;"
+            + "VAR a: A;"
+            + "PROCEDURE pa(a: A); BEGIN END pa;"
+            ),
+    pass("PROCEDURE p(a: A); BEGIN END p",
+         "PROCEDURE p(); VAR a: A; BEGIN pa(a) END p",
+         "PROCEDURE p(); VAR a: ARRAY 2 OF INTEGER; BEGIN pa(a) END p"
+         ),
+    fail(["PROCEDURE p(a: ARRAY 3 OF INTEGER); BEGIN END p",
+          "not parsed"],
+         ["PROCEDURE p(a: A): INTEGER; BEGIN RETURN a[2] END p",
+          "index out of bounds: maximum possible index is 1, got 2"],
+         ["PROCEDURE p(); VAR a: ARRAY 1 OF INTEGER; BEGIN pa(a) END p",
+          "type mismatch for argument 1: 'ARRAY 1 OF INTEGER' cannot be converted to 'ARRAY 2 OF INTEGER'"],
+         ["PROCEDURE p(a: ARRAY OF INTEGER); BEGIN pa(a) END p",
+          "type mismatch for argument 1: 'ARRAY OF INTEGER' cannot be converted to 'ARRAY 2 OF INTEGER'"]
+        )
     ),
 "string assignment to open array fails": testWithGrammar(
     Grammar.procedureDeclaration,
@@ -1202,7 +1246,7 @@ var testSuite = {
          ["MODULE m; IMPORT JS; BEGIN JS.do(\"a\", \"b\") END m.",
           "1 argument(s) expected, got 2"],
          ["MODULE m; IMPORT JS; VAR s: ARRAY 10 OF CHAR; BEGIN JS.do(s) END m.",
-          "string is expected as an argument of JS predefined procedure 'do', got ARRAY OF CHAR"]
+          "string is expected as an argument of JS predefined procedure 'do', got ARRAY 10 OF CHAR"]
           )
     ),
 "import unknown module": testWithGrammar(