2
0
Эх сурвалжийг харах

dynamic array: method "clear"
fix type check for dynamic array assignment

Vladislav Folts 10 жил өмнө
parent
commit
173a1da6b5

BIN
bin/compiled.zip


+ 14 - 1
src/eberon/EberonCast.ob

@@ -1,5 +1,15 @@
 MODULE EberonCast;
 MODULE EberonCast;
-IMPORT Cast, EberonString, EberonDynamicArray, Types;
+IMPORT Cast, Code, EberonString, EberonDynamicArray, OberonRtl, Types;
+TYPE
+    CastOpToDynamicArray = RECORD (Cast.CastOp)
+    END;
+
+VAR
+    castOpToDynamicArray: POINTER TO CastOpToDynamicArray;
+
+PROCEDURE CastOpToDynamicArray.make(rtl: OberonRtl.PType; e: Code.PExpression): Code.PExpression;
+    RETURN Code.makeSimpleExpression(rtl.clone(e.code()), NIL)
+END CastOpToDynamicArray.make;
 
 
 PROCEDURE isOpenCharArray(type: Types.PType): BOOLEAN;
 PROCEDURE isOpenCharArray(type: Types.PType): BOOLEAN;
     RETURN (type IS Types.POpenArray) 
     RETURN (type IS Types.POpenArray) 
@@ -23,6 +33,7 @@ BEGIN
         IF toVar & ~(from IS EberonDynamicArray.PDynamicArray) THEN
         IF toVar & ~(from IS EberonDynamicArray.PDynamicArray) THEN
             result := Cast.errVarParameter;
             result := Cast.errVarParameter;
         ELSE
         ELSE
+            op := castOpToDynamicArray;
             result := Cast.errNo;
             result := Cast.errNo;
         END;
         END;
     ELSE
     ELSE
@@ -31,4 +42,6 @@ BEGIN
     RETURN result
     RETURN result
 END implicit;
 END implicit;
 
 
+BEGIN
+    NEW(castOpToDynamicArray);
 END EberonCast.
 END EberonCast.

+ 48 - 11
src/eberon/EberonDynamicArray.ob

@@ -2,8 +2,9 @@ MODULE EberonDynamicArray;
 IMPORT Code, Context, EberonTypes, Errors, JsArray, LanguageContext, Procedure, Types;
 IMPORT Code, Context, EberonTypes, Errors, JsArray, LanguageContext, Procedure, Types;
 CONST
 CONST
     methodNameAdd = "add";
     methodNameAdd = "add";
-    methodNameRemove = "remove";
+    methodNameClear = "clear";
     methodNameIndexOf = "indexOf";
     methodNameIndexOf = "indexOf";
+    methodNameRemove = "remove";
 TYPE
 TYPE
     DynamicArray* = RECORD(Types.Array)
     DynamicArray* = RECORD(Types.Array)
     END;
     END;
@@ -27,13 +28,19 @@ TYPE
         elementsType: Types.PType
         elementsType: Types.PType
     END;
     END;
 
 
-    MethodRemove = RECORD(Method)
+    MethodClear = RECORD(Method)
     END;
     END;
 
 
     MethodIndexOf = RECORD(Method)
     MethodIndexOf = RECORD(Method)
         elementsType: Types.PType
         elementsType: Types.PType
     END;
     END;
 
 
+    MethodRemove = RECORD(Method)
+    END;
+
+    MethodCallClear = RECORD(Procedure.StdCall)
+    END;
+
     MethodCallRemove = RECORD(Procedure.StdCall)
     MethodCallRemove = RECORD(Procedure.StdCall)
     END;
     END;
 
 
@@ -70,16 +77,16 @@ BEGIN
     RETURN result
     RETURN result
 END makeAddField;
 END makeAddField;
 
 
-PROCEDURE makeRemoveField(): PMethod;
+PROCEDURE makeClearMethod(): PMethod;
 VAR
 VAR
-    result: POINTER TO MethodRemove;
+    result: POINTER TO MethodClear;
 BEGIN
 BEGIN
     NEW(result);
     NEW(result);
-    result.name := methodNameRemove;
+    result.name := methodNameClear;
     RETURN result
     RETURN result
-END makeRemoveField;
+END makeClearMethod;
 
 
-PROCEDURE makeIndexOfField(elementsType: Types.PType): PMethod;
+PROCEDURE makeIndexOfMethod(elementsType: Types.PType): PMethod;
 VAR
 VAR
     result: POINTER TO MethodIndexOf;
     result: POINTER TO MethodIndexOf;
 BEGIN
 BEGIN
@@ -87,7 +94,16 @@ BEGIN
     result.name := methodNameIndexOf;
     result.name := methodNameIndexOf;
     result.elementsType := elementsType;
     result.elementsType := elementsType;
     RETURN result
     RETURN result
-END makeIndexOfField;
+END makeIndexOfMethod;
+
+PROCEDURE makeRemoveMethod(): PMethod;
+VAR
+    result: POINTER TO MethodRemove;
+BEGIN
+    NEW(result);
+    result.name := methodNameRemove;
+    RETURN result
+END makeRemoveMethod;
 
 
 PROCEDURE DynamicArray.denote(id: STRING): Types.PField;
 PROCEDURE DynamicArray.denote(id: STRING): Types.PField;
 VAR
 VAR
@@ -97,10 +113,12 @@ VAR
 BEGIN
 BEGIN
     IF      id = methodNameAdd THEN
     IF      id = methodNameAdd THEN
         method := makeAddField(SELF.elementsType);
         method := makeAddField(SELF.elementsType);
-    ELSIF   id = methodNameRemove THEN
-        method := makeRemoveField();
+    ELSIF   id = methodNameClear THEN
+        method := makeClearMethod();
     ELSIF   id = methodNameIndexOf THEN
     ELSIF   id = methodNameIndexOf THEN
-        method := makeIndexOfField(SELF.elementsType);
+        method := makeIndexOfMethod(SELF.elementsType);
+    ELSIF   id = methodNameRemove THEN
+        method := makeRemoveMethod();
     END;
     END;
     IF method # NIL THEN
     IF method # NIL THEN
         NEW(field);
         NEW(field);
@@ -186,6 +204,16 @@ BEGIN
     RETURN result
     RETURN result
 END MethodAdd.callGenerator;
 END MethodAdd.callGenerator;
 
 
+PROCEDURE MethodClear.designatorCode(id: STRING): STRING;
+    RETURN "splice"
+END MethodClear.designatorCode;
+
+PROCEDURE MethodCallClear.make(args: JsArray.Type; cx: LanguageContext.PType): Code.PExpression;
+BEGIN
+    Procedure.processArguments(args, SELF.args, NIL, cx.types);
+    RETURN Code.makeSimpleExpression("(0, Number.MAX_VALUE)", NIL)
+END MethodCallClear.make;
+
 PROCEDURE MethodCallRemove.make(args: JsArray.Type; cx: LanguageContext.PType): Code.PExpression;
 PROCEDURE MethodCallRemove.make(args: JsArray.Type; cx: LanguageContext.PType): Code.PExpression;
 BEGIN
 BEGIN
     argCode <- Procedure.makeArgumentsCode(cx);
     argCode <- Procedure.makeArgumentsCode(cx);
@@ -215,6 +243,15 @@ PROCEDURE MethodIndexOf.designatorCode(id: STRING): STRING;
     RETURN "indexOf"
     RETURN "indexOf"
 END MethodIndexOf.designatorCode;
 END MethodIndexOf.designatorCode;
 
 
+PROCEDURE MethodClear.callGenerator(cx: LanguageContext.PType): Procedure.PCallGenerator;
+VAR
+    call: POINTER TO MethodCallClear;
+BEGIN
+    NEW(call);
+    Procedure.initStdCall(call);
+    RETURN Procedure.makeCallGenerator(call, cx)
+END MethodClear.callGenerator;
+
 PROCEDURE MethodRemove.callGenerator(cx: LanguageContext.PType): Procedure.PCallGenerator;
 PROCEDURE MethodRemove.callGenerator(cx: LanguageContext.PType): Procedure.PCallGenerator;
 VAR
 VAR
     a: Types.PProcedureArgument;
     a: Types.PProcedureArgument;

+ 5 - 2
src/eberon/eberon_context.js

@@ -326,9 +326,12 @@ var AssignmentOrProcedureCall = Context.Chained.extend({
         var type = d.type();
         var type = d.type();
         var code;
         var code;
         if (this.__right){
         if (this.__right){
-            if (type instanceof EberonDynamicArray.DynamicArray)
+        /*    if (type instanceof EberonDynamicArray.DynamicArray){
+                if (!(this.__right.type() instanceof Type.Array))
+                    throw new Errors.Error("type mismatch");
                 code = d.code() + " = " + this.language().rtl.clone(this.__right.code());
                 code = d.code() + " = " + this.language().rtl.clone(this.__right.code());
-            else {
+            }
+            else */{
                 var left = Code.makeExpression(d.code(), type, d);
                 var left = Code.makeExpression(d.code(), type, d);
                 code = op.assign(left, this.__right, this.language());
                 code = op.assign(left, this.__right, this.language());
             } 
             } 

+ 1 - 1
src/ob/Lexer.ob

@@ -12,7 +12,7 @@ CONST
         + "var void while with false true null class enum export extends "
         + "var void while with false true null class enum export extends "
         + "import super implements interface let package private protected "
         + "import super implements interface let package private protected "
         + "public static yield "
         + "public static yield "
-        + "Math" (* Math is used in generated code for some functions so it is 
+        + "Math Number" (* Math and Number are used in generated code for some functions so it is 
                     reserved word from code generator standpoint *)
                     reserved word from code generator standpoint *)
         ;
         ;
 
 

+ 1 - 1
src/ob/Operator.ob

@@ -517,7 +517,7 @@ BEGIN
         IF (leftType IS Types.POpenArray) & (rightType IS Types.PArray) 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 (castOperation = NIL) & (isArray OR (rightType IS Types.PRecord)) THEN
             result := cx.rtl.copy(rightCode, leftCode);
             result := cx.rtl.copy(rightCode, leftCode);
         ELSE
         ELSE
             IF castOperation # NIL THEN
             IF castOperation # NIL THEN

+ 1 - 1
src/ob/Procedure.ob

@@ -151,7 +151,7 @@ BEGIN
     END;
     END;
 END checkArgumentsCount;
 END checkArgumentsCount;
 
 
-PROCEDURE processArguments(
+PROCEDURE processArguments*(
     actual: JsArray.Type; 
     actual: JsArray.Type; 
     expected: JsArray.Type; 
     expected: JsArray.Type; 
     code: PArgumentsCode;
     code: PArgumentsCode;

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

@@ -124,4 +124,5 @@ dynamicArrayOfStaticArrayInt.push(RTL$.clone(a));
 RTL$.assert(dynamicInt.indexOf(i) != -1);
 RTL$.assert(dynamicInt.indexOf(i) != -1);
 RTL$.assert(dynamicChar.indexOf(34) != -1);
 RTL$.assert(dynamicChar.indexOf(34) != -1);
 dynamicInt.splice(i, 1);
 dynamicInt.splice(i, 1);
+dynamicInt.splice(0, Number.MAX_VALUE);
 }();
 }();

+ 1 - 1
test/expected/js_keyword.js

@@ -1,5 +1,5 @@
 var do$ = function (){
 var do$ = function (){
-var break$ = 0;var case$ = 0;var catch$ = 0;var continue$ = 0;var debugger$ = 0;var default$ = 0;var delete$ = 0;var else$ = 0;var class$ = 0;var const$ = 0;var enum$ = 0;var export$ = 0;var extends$ = 0;var import$ = 0;var super$ = 0;var true$ = 0;var false$ = 0;var null$ = 0;var implements$ = 0;var interface$ = 0;var let$ = 0;var package$ = 0;var private$ = 0;var protected$ = 0;var public$ = 0;var static$ = 0;var yield$ = 0;var finally$ = 0;var for$ = 0;var if$ = 0;var in$ = 0;var instanceof$ = 0;var new$ = 0;var return$ = 0;var switch$ = 0;var this$ = 0;var try$ = 0;var typeof$ = 0;var var$ = 0;var void$ = 0;var while$ = 0;var with$ = 0;var Math$ = 0;
+var break$ = 0;var case$ = 0;var catch$ = 0;var continue$ = 0;var debugger$ = 0;var default$ = 0;var delete$ = 0;var else$ = 0;var class$ = 0;var const$ = 0;var enum$ = 0;var export$ = 0;var extends$ = 0;var import$ = 0;var super$ = 0;var true$ = 0;var false$ = 0;var null$ = 0;var implements$ = 0;var interface$ = 0;var let$ = 0;var package$ = 0;var private$ = 0;var protected$ = 0;var public$ = 0;var static$ = 0;var yield$ = 0;var finally$ = 0;var for$ = 0;var if$ = 0;var in$ = 0;var instanceof$ = 0;var new$ = 0;var return$ = 0;var switch$ = 0;var this$ = 0;var try$ = 0;var typeof$ = 0;var var$ = 0;var void$ = 0;var while$ = 0;var with$ = 0;var Math$ = 0;var Number$ = 0;
 
 
 function function$(){
 function function$(){
 	var i = null;
 	var i = null;

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

@@ -53,4 +53,5 @@ BEGIN
     ASSERT(dynamicChar.indexOf(22X) # -1);
     ASSERT(dynamicChar.indexOf(22X) # -1);
 
 
     dynamicInt.remove(i);
     dynamicInt.remove(i);
+    dynamicInt.clear();
 END m.
 END m.

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

@@ -22,6 +22,9 @@ BEGIN
     ASSERT(LEN(a) = 2);
     ASSERT(LEN(a) = 2);
     ASSERT(a[0] = 1);
     ASSERT(a[0] = 1);
     ASSERT(a[1] = 3);
     ASSERT(a[1] = 3);
+
+    a.clear();
+    ASSERT(LEN(a) = 0);
 END testAddRemove;
 END testAddRemove;
 
 
 PROCEDURE testArrayReturn();
 PROCEDURE testArrayReturn();

+ 1 - 1
test/input/js_keyword.ob

@@ -6,7 +6,7 @@ VAR
     true, false, null,
     true, false, null,
     implements, interface, let, package, private, protected, public, static, yield,
     implements, interface, let, package, private, protected, public, static, yield,
     finally, for, if, in, instanceof, new, return, switch, this, 
     finally, for, if, in, instanceof, new, return, switch, this, 
-    try, typeof, var, void, while, with, Math
+    try, typeof, var, void, while, with, Math, Number
     : INTEGER;
     : INTEGER;
 PROCEDURE function();
 PROCEDURE function();
 VAR i: throw;
 VAR i: throw;

+ 8 - 1
test/test_unit_eberon.js

@@ -920,7 +920,8 @@ exports.suite = {
             context(grammar.statement, 
             context(grammar.statement, 
                     "VAR stat: ARRAY 3 OF INTEGER; dynamic: ARRAY * OF INTEGER;"),
                     "VAR stat: ARRAY 3 OF INTEGER; dynamic: ARRAY * OF INTEGER;"),
             pass("dynamic := stat"),
             pass("dynamic := stat"),
-            fail(["stat := dynamic", "type mismatch: 'stat' is 'ARRAY 3 OF INTEGER' and cannot be assigned to 'ARRAY * OF INTEGER' expression"])
+            fail(["stat := dynamic", "type mismatch: 'stat' is 'ARRAY 3 OF INTEGER' and cannot be assigned to 'ARRAY * OF INTEGER' expression"],
+                 ["dynamic := NIL", "type mismatch: 'dynamic' is 'ARRAY * OF INTEGER' and cannot be assigned to 'NIL' expression"])
         ),
         ),
         "indexing": testWithContext(
         "indexing": testWithContext(
             context(grammar.expression, 
             context(grammar.expression, 
@@ -984,6 +985,12 @@ exports.suite = {
                  ["recordArray.indexOf(r)", "cannot search for element of type 'T'"],
                  ["recordArray.indexOf(r)", "cannot search for element of type 'T'"],
                  ["arrayOfArray.indexOf(intArray)", "cannot search for element of type 'ARRAY * OF INTEGER'"]
                  ["arrayOfArray.indexOf(intArray)", "cannot search for element of type 'ARRAY * OF INTEGER'"]
                 )
                 )
+        ),
+        "clear": testWithContext(
+            context(grammar.statement, 
+                    "VAR a: ARRAY * OF INTEGER;"),
+            pass("a.clear()"),
+            fail(["a.clear(0)", "0 argument(s) expected, got 1"])
         )
         )
     }
     }
 };
 };