Răsfoiți Sursa

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

Vladislav Folts 10 ani în urmă
părinte
comite
173a1da6b5

BIN
bin/compiled.zip


+ 14 - 1
src/eberon/EberonCast.ob

@@ -1,5 +1,15 @@
 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;
     RETURN (type IS Types.POpenArray) 
@@ -23,6 +33,7 @@ BEGIN
         IF toVar & ~(from IS EberonDynamicArray.PDynamicArray) THEN
             result := Cast.errVarParameter;
         ELSE
+            op := castOpToDynamicArray;
             result := Cast.errNo;
         END;
     ELSE
@@ -31,4 +42,6 @@ BEGIN
     RETURN result
 END implicit;
 
+BEGIN
+    NEW(castOpToDynamicArray);
 END EberonCast.

+ 48 - 11
src/eberon/EberonDynamicArray.ob

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

+ 5 - 2
src/eberon/eberon_context.js

@@ -326,9 +326,12 @@ var AssignmentOrProcedureCall = Context.Chained.extend({
         var type = d.type();
         var code;
         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());
-            else {
+            }
+            else */{
                 var left = Code.makeExpression(d.code(), type, d);
                 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 "
         + "import super implements interface let package private protected "
         + "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 *)
         ;
 

+ 1 - 1
src/ob/Operator.ob

@@ -517,7 +517,7 @@ BEGIN
         IF (leftType IS Types.POpenArray) & (rightType IS Types.PArray) THEN
             Errors.raise("'" + leftCode + "' is open '" + leftType.description() + "' and cannot be assigned");
         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);
         ELSE
             IF castOperation # NIL THEN

+ 1 - 1
src/ob/Procedure.ob

@@ -151,7 +151,7 @@ BEGIN
     END;
 END checkArgumentsCount;
 
-PROCEDURE processArguments(
+PROCEDURE processArguments*(
     actual: JsArray.Type; 
     expected: JsArray.Type; 
     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(dynamicChar.indexOf(34) != -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 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$(){
 	var i = null;

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

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

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

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

+ 1 - 1
test/input/js_keyword.ob

@@ -6,7 +6,7 @@ VAR
     true, false, null,
     implements, interface, let, package, private, protected, public, static, yield,
     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;
 PROCEDURE function();
 VAR i: throw;

+ 8 - 1
test/test_unit_eberon.js

@@ -920,7 +920,8 @@ exports.suite = {
             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"])
+            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(
             context(grammar.expression, 
@@ -984,6 +985,12 @@ exports.suite = {
                  ["recordArray.indexOf(r)", "cannot search for element of type 'T'"],
                  ["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"])
         )
     }
 };