Browse Source

indexOf() for open arrays

Vladislav Folts 10 years ago
parent
commit
a6eeccb46c

BIN
bin/compiled.zip


+ 1 - 1
src/context.js

@@ -489,7 +489,7 @@ exports.FormalType = HandleSymbolAsType.extend({
     },
     setType: function(type){           
         for(var i = 0; i < this.__arrayDimension; ++i)
-            type = Type.makeOpenArray(type);
+            type = this.language().types.makeOpenArray(type);
         this.parent().setType(type);
 
     },

+ 45 - 11
src/eberon/EberonArray.ob

@@ -7,8 +7,8 @@ TYPE
     END;
     PMethod* = POINTER TO Method;
 
-    MethodField* = RECORD(Types.Field)
-        method*: PMethod
+    MethodField = RECORD(Types.Field)
+        method: PMethod
     END;
 
     MethodIndexOf = RECORD(Method)
@@ -21,12 +21,15 @@ TYPE
     StaticArray = RECORD(Types.StaticArray)
     END;
 
+    OpenArray = RECORD(Types.OpenArray)
+    END;
+
 PROCEDURE Method.description(): STRING;
     RETURN "array method '" + SELF.name + "'"
 END Method.description;
 
 PROCEDURE MethodField.id(): STRING;
-    RETURN "add"
+    RETURN SELF.method.name
 END MethodField.id;
 
 PROCEDURE MethodField.exported(): BOOLEAN;
@@ -86,24 +89,46 @@ BEGIN
     RETURN result
 END denoteMethod;
 
-PROCEDURE StaticArray.denote(id: STRING): Types.PField;
+PROCEDURE makeMethodField*(method: PMethod): Types.PField;
+VAR
+    result: POINTER TO MethodField;
+BEGIN
+    NEW(result);
+    result.method := method;
+    RETURN result
+END makeMethodField;
+
+PROCEDURE denote(id: STRING; a: Types.Array): Types.PField;
 VAR
-    field: POINTER TO MethodField;
     result: Types.PField;
 BEGIN
     IF id = methodNameIndexOf THEN
-        IF (SELF.elementsType IS Types.PRecord) OR (SELF.elementsType IS Types.PArray) THEN
-            Errors.raise("'" + methodNameIndexOf + "' is not defined for array of '" + SELF.elementsType.description() + "'");
+        IF (a.elementsType IS Types.PRecord) OR (a.elementsType IS Types.PArray) THEN
+            Errors.raise("'" + methodNameIndexOf + "' is not defined for array of '" + a.elementsType.description() + "'");
         END;
-        NEW(field);
-        field.method := makeIndexOfMethod(SELF.elementsType);
-        result := field;
-    ELSE
+        result := makeMethodField(makeIndexOfMethod(a.elementsType));
+    END;
+    RETURN result
+END denote;
+
+PROCEDURE StaticArray.denote(id: STRING): Types.PField;
+BEGIN
+    result <- denote(id, SELF);
+    IF result = NIL THEN
         result := SUPER(id);
     END;
     RETURN result
 END StaticArray.denote;
 
+PROCEDURE OpenArray.denote(id: STRING): Types.PField;
+BEGIN
+    result <- denote(id, SELF);
+    IF result = NIL THEN
+        result := SUPER(id);
+    END;
+    RETURN result
+END OpenArray.denote;
+
 PROCEDURE makeStaticArray*(
     initializer: STRING;
     elementsType: Types.PType;
@@ -117,4 +142,13 @@ BEGIN
     RETURN result
 END makeStaticArray;
 
+PROCEDURE makeOpenArray*(elementsType: Types.PType): Types.PArray;
+VAR
+    result: POINTER TO OpenArray;
+BEGIN
+    NEW(result);
+    Types.initArray(elementsType, result^);
+    RETURN result
+END makeOpenArray;
+
 END EberonArray.

+ 1 - 4
src/eberon/EberonDynamicArray.ob

@@ -84,7 +84,6 @@ END makeRemoveMethod;
 
 PROCEDURE DynamicArray.denote(id: STRING): Types.PField;
 VAR
-    field: POINTER TO EberonArray.MethodField;
     method: EberonArray.PMethod;
     result: Types.PField;
 BEGIN
@@ -98,9 +97,7 @@ BEGIN
         method := EberonArray.denoteMethod(id, SELF.elementsType);
     END;
     IF method # NIL THEN
-        NEW(field);
-        field.method := method;
-        result := field;
+        result := EberonArray.makeMethodField(method);
     ELSE
         result := SUPER(id);
     END;

+ 1 - 1
src/eberon/eberon_context.js

@@ -1186,7 +1186,7 @@ var FormalType = Context.HandleSymbolAsType.extend({
         for(var i = this.__arrayDimensions.length; i--;){
             type = this.__arrayDimensions[i] 
                 ? EberonDynamicArray.makeDynamicArray(type)
-                : Type.makeOpenArray(type);
+                : this.language().types.makeOpenArray(type);
         }
         this.parent().setType(type);
     },

+ 2 - 1
src/eberon/eberon_grammar.js

@@ -123,6 +123,7 @@ exports.language = {
     stdSymbols: Symbols.makeStd(),
     types: {
         implicitCast: Cast.implicit,
-        makeStaticArray: EbArray.makeStaticArray
+        makeStaticArray: EbArray.makeStaticArray,
+        makeOpenArray: EbArray.makeOpenArray
     }
 };

+ 2 - 1
src/oberon/oberon_grammar.js

@@ -103,7 +103,8 @@ exports.language = {
     stdSymbols: Symbols.makeStd(),
     types: {
         implicitCast: Cast.implicit,
-        makeStaticArray: Types.makeStaticArray
+        makeStaticArray: Types.makeStaticArray,
+        makeOpenArray: Types.makeOpenArray
     }
 };
 

+ 13 - 1
test/test_unit_eberon.js

@@ -871,7 +871,7 @@ exports.suite = {
             )
     ),
     "array": {
-            "indexOf": testWithContext(
+            "static array indexOf": testWithContext(
                 context(grammar.expression, 
                         "TYPE "
                         + "T = RECORD END;"
@@ -891,6 +891,11 @@ exports.suite = {
                      ["intArray.indexOf", "array method 'indexOf' cannot be referenced"]                
                     )
             ),
+            "open array indexOf": testWithGrammar(
+                grammar.declarationSequence,
+                pass("PROCEDURE p(a: ARRAY OF INTEGER): INTEGER; RETURN a.indexOf(123) END p;"
+                    )
+            ),
         "dynamic": {
             "declaration": testWithContext(
                 context(grammar.declarationSequence, 
@@ -974,6 +979,13 @@ exports.suite = {
                 fail(["a[-1]", "index is negative: -1"], 
                      ["a[-2]", "index is negative: -2"])
             ),
+            "indexOf": testWithContext(
+                context(grammar.expression, 
+                        "VAR intArray: ARRAY * OF INTEGER;"
+                        ),
+                pass("intArray.indexOf(0)"),
+                fail()
+            ),
             "add": testWithContext(
                 context(grammar.statement, 
                         "VAR a: ARRAY * OF INTEGER;"

+ 6 - 0
test/test_unit_oberon.js

@@ -43,6 +43,12 @@ exports.suite = {
     pass(),
     fail(["s: STRING", "undeclared identifier: 'STRING'"])
     ),
+"array does not have indexOf() method": testWithContext(
+    context(grammar.expression,
+            "VAR a: ARRAY 3 OF INTEGER;"),
+    pass(),
+    fail(["a.indexOf(123)", "selector '.indexOf' cannot be applied to 'ARRAY 3 OF INTEGER'"])
+    ),
 "cannot designate call result in expression": testWithContext(
     context(grammar.expression,
             "TYPE PT = POINTER TO RECORD field: INTEGER END;"