Vladislav Folts před 9 roky
rodič
revize
b0f535a9ae

binární
bin/compiled.zip


+ 33 - 8
src/eberon/EberonContextExpression.ob

@@ -1,8 +1,8 @@
 MODULE EberonContextExpression;
 IMPORT
-    Cast, CodePrecedence,
+    Cast, CodePrecedence, ConstValue,
     Context, ContextExpression, ContextHierarchy, 
-    EberonContextDesignator, 
+    EberonArray, EberonContextDesignator, 
     EberonMap, EberonOperator, EberonString, EberonTypePromotion, 
     Errors, Expression, ExpressionTree, LanguageContext,
     JS,
@@ -23,14 +23,13 @@ TYPE
         PROCEDURE RelationExpression(parent: PExpressionNode);
     END;
 
-    SimpleExpression* = RECORD(ContextExpression.SimpleExpression)
+    Array* = RECORD(ContextExpression.ExpressionHandler)
+        size: INTEGER;
+        type: Types.PStorageType;
+        code: STRING;
     END;
 
-    Term* = RECORD(ContextExpression.Term)
-    END;
-    PTerm = POINTER TO Term;
-
-    Factor* = RECORD(ContextExpression.Factor)
+    ArrayConst = RECORD(ConstValue.Type)
     END;
 
     Ops = RECORD(ExpressionTree.Ops)
@@ -237,6 +236,32 @@ PROCEDURE RelationExpression.RelationExpression(parent: PExpressionNode)
     | SUPER(parent, parent.currentNode);
 END;
 
+PROCEDURE Array.handleExpression(e: Expression.PType);
+BEGIN
+    type <- e.type();
+    IF SELF.type = NIL THEN
+        IF type IS Types.PStorageType THEN
+            SELF.type := type;
+        ELSE
+            Errors.raise("array's element cannot be '" + type.description() + "'");
+        END;
+        SELF.code := "[" + e.code();
+    ELSIF SELF.type = type THEN
+        SELF.code := SELF.code + ", " + e.code();
+    ELSE
+        Errors.raise("array's elements should have the same type: expected '" + SELF.type.description() + "', got '" + type.description() + "'");
+    END;
+    INC(SELF.size);
+END;
+
+PROCEDURE Array.endParse(): BOOLEAN;
+BEGIN
+    SELF.code := SELF.code + "]";
+    SELF.parent()(ContextExpression.PExpressionHandler).handleExpression(
+        Expression.make(SELF.code, NEW EberonArray.StaticArray("", SELF.type, SELF.size), NIL, NEW ArrayConst()));
+    RETURN TRUE;
+END;
+
 PROCEDURE Ops.in(left, right: Types.PType; cx: ContextHierarchy.Node): ExpressionTree.BinaryOperatorCx;
 VAR
     result: ExpressionTree.BinaryOperatorCx;

+ 7 - 3
src/eberon/eberon_grammar.js

@@ -144,6 +144,12 @@ function makeReturn(base){
     return and(base, optional(";"));
 }
 
+function makeSet(expression){
+    var array = context(and("[", expression, repeat(and(",", expression)), "]"),
+                        EberonContextExpression.Array);
+    return or(Grammar.makeSet(expression), array);
+}
+
 exports.language = {
     grammar: Grammar.make(
         makeIdentdef,
@@ -160,17 +166,15 @@ exports.language = {
         makeFormalArray,
         makeFormalResult,
         makeReturn,
+        makeSet,
         { 
             constDeclaration:   EberonContext.ConstDeclaration, 
             typeDeclaration:    EberonContextType.Declaration,
             recordDecl:         EberonContextType.Record,
             variableDeclaration: EberonContextVar.Declaration,
             ArrayDecl:          EberonContextType.Array,
-            Factor:             EberonContextExpression.Factor,
             FormalParameters:   EberonContextProcedure.FormalParameters,
             FormalType:         EberonContextType.FormalType,
-            Term:               EberonContextExpression.Term,
-            SimpleExpression:   EberonContextExpression.SimpleExpression, 
             For:                EberonContextLoop.For,
             While:              EberonContextLoop.While,
             If:                 EberonContextIf.Type,

+ 11 - 6
src/grammar.js

@@ -40,6 +40,7 @@ function make(makeIdentdef,
               makeFormalArray,
               makeFormalResult,
               makeReturn,
+              makeSet,
               contexts,
               reservedWords
               ){
@@ -90,23 +91,21 @@ var factor = context(
        and("~", function(stream, context){
                     return factor(stream, context);}) // break recursive declaration of factor
      )
-    , contexts.Factor);
+    , ContextExpression.Factor);
 
 var addOperator = context(or("+", "-", "OR"), ContextExpression.AddOperator);
 var mulOperator = context(or("*", "/", "DIV", "MOD", "&"), ContextExpression.MulOperator);
-var term = context(and(factor, repeat(and(mulOperator, required(factor, "invalid operand")))), contexts.Term);
+var term = context(and(factor, repeat(and(mulOperator, required(factor, "invalid operand")))), ContextExpression.Term);
 var simpleExpression = context(
         and(optional(or("+", "-"))
           , term
           , repeat(and(addOperator, required(term, "invalid operand"))))
-      , contexts.SimpleExpression);
+      , ContextExpression.SimpleExpression);
 var relation = or("=", "#", "<=", "<", ">=", ">", "IN", "IS");
 var expression = makeExpression(and(simpleExpression, optional(and(relation, required(simpleExpression, "invalid operand")))));
 var constExpression = expression;
 
-var element = context(and(expression, optional(and("..", expression))), ContextExpression.SetElement);
-var set = and("{", context(optional(and(element, repeat(and(",", element)))), ContextExpression.Set)
-            , "}");
+var set = makeSet(expression);
 
 var expList = and(expression, repeat(and(",", expression)));
 var actualParameters = and("(", context(optional(expList), ContextDesignator.ActualParameters), ")");
@@ -232,5 +231,11 @@ result.module
 return result;
 }
 
+function makeSet(expression){
+    var element = context(and(expression, optional(and("..", expression))), ContextExpression.SetElement);
+    return and("{", context(optional(and(element, repeat(and(",", element)))), ContextExpression.Set), "}");
+}
+
 exports.make = make;
 exports.reservedWords = reservedWords;
+exports.makeSet = makeSet;

+ 1 - 3
src/oberon/oberon_grammar.js

@@ -121,17 +121,15 @@ exports.language = {
         makeFormalArray,
         makeFormalResult,
         makeReturn,
+        Grammar.makeSet,
         {
             constDeclaration:   ContextConst.Type, 
             typeDeclaration:    ContextType.Declaration,
             recordDecl:         OberonContextType.Record,
             variableDeclaration: OberonContextVar.Declaration,
             ArrayDecl:          ContextType.Array,
-            Factor:             ContextExpression.Factor,
             FormalParameters:   ContextProcedure.FormalParameters,
             FormalType:         ContextType.FormalType,
-            Term:               ContextExpression.Term,
-            SimpleExpression:   ContextExpression.SimpleExpression, 
             For:                ContextLoop.For,
             While:              ContextLoop.While,
             If:                 ContextIf.Type,

+ 19 - 0
test/expected/eberon/init_array.js

@@ -0,0 +1,19 @@
+<rtl code>
+var m = function (){
+var a1 = [1];
+var a2 = [1, 2];
+var a3 = [true, false];
+var a4 = [1 + 2 | 0, 3];
+
+function passArray(a/*ARRAY OF INTEGER*/){
+}
+passArray(a1);
+for (var i = 0; i <= a1.length; ++i){
+	RTL$.assert(a1[i] != 0);
+}
+var $seq1 = a1;
+for(var $key2 = 0; $key2 < $seq1.length; ++$key2){
+	var e = $seq1[$key2];
+	RTL$.assert(e != 0);
+}
+}();

+ 22 - 0
test/input/eberon/init_array.ob

@@ -0,0 +1,22 @@
+MODULE m;
+
+CONST 
+	a1 = [1];
+	a2 = [1, 2];
+	a3 = [TRUE, FALSE];
+	a4 = [1 + 2, 3];
+
+PROCEDURE passArray(a: ARRAY OF INTEGER);
+END;
+
+BEGIN
+	passArray(a1);
+
+	FOR i <- 0 TO LEN(a1) DO
+		ASSERT(a1[i] # 0);
+	END;
+
+	FOR e IN a1 DO
+		ASSERT(e # 0);
+	END;
+END m.

+ 31 - 0
test/test_unit_eberon.js

@@ -1566,5 +1566,36 @@ exports.suite = {
              ["passPDerived(b ? pb : NIL)", "type mismatch for argument 1: 'PBase' cannot be converted to 'PDerived'"],
              ["passRef(b ? i1 : i2)", "ternary operator result cannot be passed as VAR actual parameter"]
              )
+    ),
+"array expression": testWithGrammar(
+    grammar.expression,
+    pass("[1]",
+         "[1, 2]",
+         "[FALSE, TRUE]"
+         ),
+    fail(["[]", "not parsed"],
+         ["[1, TRUE]", "array's elements should have the same type: expected 'INTEGER', got 'BOOLEAN'"],
+         ["[NIL]", "array's element cannot be 'NIL'"],
+         ["[1, NIL]", "array's elements should have the same type: expected 'INTEGER', got 'NIL'"]
+        )
+    ),
+"CONST array": testWithGrammar(
+    grammar.declarationSequence,
+    pass("CONST a = [1];",
+         "CONST a = [1, 2];",
+         "CONST a = [FALSE, TRUE];"
+         )
+    ),
+"CONST array pass to procedure": testWithContext(
+    context(grammar.expression,
+            "CONST a = [1, 2, 3];"
+            + "PROCEDURE intArray(a: ARRAY OF INTEGER): BOOLEAN; RETURN FALSE; END;"
+            + "PROCEDURE intVarArray(VAR a: ARRAY OF INTEGER): BOOLEAN; RETURN FALSE; END;"
+            + "PROCEDURE charArray(a: ARRAY OF CHAR): BOOLEAN; RETURN FALSE; END;"
+            ),
+    pass("intArray(a)"
+         ),
+    fail(["intVarArray(a)", "constant cannot be passed as VAR actual parameter"],
+         ["charArray(a)", "type mismatch for argument 1: 'ARRAY 3 OF INTEGER' cannot be converted to 'ARRAY OF CHAR'"])
     )
 };