Bläddra i källkod

dynamic arrays: add 'add' methof

Vladislav Folts 10 år sedan
förälder
incheckning
b14b57f25c

BIN
bin/compiled.zip


+ 21 - 12
src/context.js

@@ -17,7 +17,11 @@ var nullCodeGenerator = Code.nullGenerator();
 var nilType = Type.nil();
 
 var castOperations = op.castOperations();
-
+/*
+function log(s){
+    console.info(s);
+}
+*/
 function getSymbolAndScope(context, id){
     var s = context.findSymbol(id);
     if (!s)
@@ -310,20 +314,23 @@ exports.Designator = ChainedContext.extend({
         this.__scope = found.scope();
         var s = found.symbol();
         var info = s.info();
+        var code = q.code;
         if (info instanceof Type.Type || s.isType())
             this.__currentType = info;
         else if (s.isConst())
             this.__currentType = Type.constType(info);
-        else if (s.isVariable())
+        else if (s.isVariable()){
             this.__currentType = info.type();
-        else if (s.isProcedure())
+            if (q.module)
+                code += "()";
+        }
+        else if (s.isProcedure()){
             this.__currentType = Type.procedureType(info);
+            code = this.__currentType.designatorCode(code);
+        }
         
         this.__info = info;
-        this.__code += q.code;
-        
-        if (q.module && s.isVariable())
-            this.__code += "()";
+        this.__code += code;
     },
     handleIdent: function(id){
         var t = this.__currentType;
@@ -336,9 +343,12 @@ exports.Designator = ChainedContext.extend({
         var field = t.denote(id);
         this.__derefCode = this.__code;
         this.__propCode = "\"" + id + "\"";
-        this.__code += "." + id;
         this.__info = field.asVar(isReadOnly, this);
         this.__currentType = field.type();
+        var code = this.__currentType instanceof Type.Procedure 
+                 ? this.__currentType.designatorCode(id)
+                 : id;
+        this.__code += "." + code;
         this.__scope = undefined;
     },
     _makeDerefVar: function(){
@@ -371,7 +381,7 @@ exports.Designator = ChainedContext.extend({
     _advance: function(type, info, code){
         this.__currentType = type;
         this.__info = info;
-        this.__code = code;
+        this.__code += code;
     },
     _indexSequence: function(type, info){
         var isArray = type instanceof Type.Array;
@@ -1977,15 +1987,14 @@ exports.Context = Class.extend({
     }
 });
 
-function makeProcCall(context, type, info, code){
+function makeProcCall(context, type, info){
     assertProcType(type, info);
     var l = context.language();
     return type.callGenerator(
         { types: l.types, 
           rtl: l.rtl, 
           qualifyScope: context.qualifyScope.bind(context)
-        }, 
-        code);
+        });
 }
 
 exports.AddArgumentMsg = AddArgumentMsg;

+ 91 - 20
src/eberon/EberonTypes.ob

@@ -1,31 +1,43 @@
 MODULE EberonTypes;
-IMPORT Context, JsArray, LanguageContext, Procedure, Types;
+IMPORT Code, Context, JsArray, LanguageContext, Procedure, Types;
 
 TYPE
-    CallGenerator = PROCEDURE(cx: LanguageContext.PType; id: STRING; type: Types.DefinedProcedure): Procedure.PCallGenerator;
+    CallGenerator = PROCEDURE(cx: LanguageContext.PType; type: Types.DefinedProcedure): Procedure.PCallGenerator;
 
     MethodType* = RECORD(Procedure.Std)
         PROCEDURE procType(): Types.PProcedure;
         PROCEDURE args(): JsArray.Type;
         PROCEDURE result(): Types.PType;
         PROCEDURE procDescription(): STRING;
-        PROCEDURE callGenerator(cx: LanguageContext.PType; id: STRING): Procedure.PCallGenerator;
 
         type: Types.PDefinedProcedure;
         call: CallGenerator
     END;
     PMethodType = POINTER TO MethodType;
 
+    MethodVariable* = RECORD(Types.Variable)
+        mType: Types.PType
+    END;
+
     DynamicArray* = RECORD(Types.Array)
     END;
     PDynamicArray* = POINTER TO DynamicArray;
 
-    DynamicArrayMethod = RECORD(Types.Field)
+    DynamicArrayMethodField = RECORD(Types.Field)
+    END;
+    (*
+    DynamicArrayAddCall = RECORD(Procedure.StdCall)
+    END;
+    *)
+    DynamicArrayAddCallGenerator = RECORD(Procedure.CallGenerator)
+        arg: Code.PExpression
     END;
 
+    DynamicArrayMethod = RECORD(Procedure.Std)
+    END;
 VAR
-    dynamicArrayAdd: POINTER TO DynamicArrayMethod;
-    dynamicArrayAddType: Types.PProcedure;
+    dynamicArrayAdd: POINTER TO DynamicArrayMethodField;
+    dynamicArrayAddMethod: POINTER TO DynamicArrayMethod;
 
 PROCEDURE arrayDimensionDescription*(VAR a: Types.Array): STRING;
 VAR
@@ -52,6 +64,10 @@ BEGIN
     RETURN dynamicArrayAdd
 END DynamicArray.denote;
 
+PROCEDURE MethodType.designatorCode(id: STRING): STRING;
+    RETURN id
+END MethodType.designatorCode;
+
 PROCEDURE MethodType.procType(): Types.PProcedure;
     RETURN SELF.type
 END MethodType.procType;
@@ -72,8 +88,8 @@ PROCEDURE MethodType.procDescription(): STRING;
     RETURN SELF.type.description()
 END MethodType.procDescription;
 
-PROCEDURE MethodType.callGenerator(cx: LanguageContext.PType; id: STRING): Procedure.PCallGenerator;
-    RETURN SELF.call(cx, id, SELF.type^)
+PROCEDURE MethodType.callGenerator(cx: LanguageContext.PType): Procedure.PCallGenerator;
+    RETURN SELF.call(cx, SELF.type^)
 END MethodType.callGenerator;
 
 PROCEDURE makeMethodType*(id: STRING; t: Types.PDefinedProcedure; call: CallGenerator): PMethodType;
@@ -87,6 +103,31 @@ BEGIN
     RETURN result
 END makeMethodType;
 
+PROCEDURE MethodVariable.type(): Types.PType;
+    RETURN SELF.mType
+END MethodVariable.type;
+
+PROCEDURE MethodVariable.isReadOnly(): BOOLEAN;
+    RETURN TRUE
+END MethodVariable.isReadOnly;
+
+PROCEDURE MethodVariable.idType(): STRING;
+    RETURN "method"
+END MethodVariable.idType;
+
+PROCEDURE MethodVariable.isReference(): BOOLEAN;
+    RETURN FALSE
+END MethodVariable.isReference;
+
+PROCEDURE makeMethodVariable*(type: Types.PType): Types.PVariable;
+VAR
+    result: POINTER TO MethodVariable;
+BEGIN
+    NEW(result);
+    result.mType := type;
+    RETURN result
+END makeMethodVariable;
+
 PROCEDURE makeDynamicArray*(elementsType: Types.PType): PDynamicArray;
 VAR
     result: PDynamicArray;
@@ -96,24 +137,54 @@ BEGIN
     RETURN result
 END makeDynamicArray;
 
-PROCEDURE DynamicArrayMethod.id(): STRING;
+PROCEDURE DynamicArrayMethodField.id(): STRING;
     RETURN "add"
-END DynamicArrayMethod.id;
+END DynamicArrayMethodField.id;
 
-PROCEDURE DynamicArrayMethod.exported(): BOOLEAN;
+PROCEDURE DynamicArrayMethodField.exported(): BOOLEAN;
     RETURN FALSE
-END DynamicArrayMethod.exported;
+END DynamicArrayMethodField.exported;
+
+PROCEDURE DynamicArrayMethodField.type(): Types.PType;
+    RETURN dynamicArrayAddMethod
+END DynamicArrayMethodField.type;
+
+PROCEDURE DynamicArrayMethodField.asVar(): Types.PId;
+    RETURN makeMethodVariable(dynamicArrayAddMethod)
+END DynamicArrayMethodField.asVar;
+(*
+PROCEDURE DynamicArrayAddCall.make(args: JsArray.Type; cx: LanguageContext.Type): Code.PExpression;
+BEGIN
+    arg <- Procedure.checkSingleArgument(args, SELF, cx.types);
+    RETURN Code.makeSimpleExpression(
+            SELF.varId + ".push(" + arg.code() + ")",
+            NIL)
+END DynamicArrayAddCall.make;
+*)
+PROCEDURE DynamicArrayAddCallGenerator.handleArgument(e: Code.PExpression);
+BEGIN
+    SELF.arg := e;
+END DynamicArrayAddCallGenerator.handleArgument;
+
+PROCEDURE DynamicArrayAddCallGenerator.end(): Code.PExpression;
+    RETURN Code.makeSimpleExpression(
+            "(" + SELF.arg.code() + ")",
+            NIL)
+END DynamicArrayAddCallGenerator.end;
 
-PROCEDURE DynamicArrayMethod.type(): Types.PType;
-    RETURN dynamicArrayAddType
-END DynamicArrayMethod.type;
+PROCEDURE DynamicArrayMethod.designatorCode(id: STRING): STRING;
+    RETURN "push"
+END DynamicArrayMethod.designatorCode;
 
-PROCEDURE DynamicArrayMethod.asVar(): Types.PId;
-    RETURN NIL
-END DynamicArrayMethod.asVar;
+PROCEDURE DynamicArrayMethod.callGenerator(cx: LanguageContext.PType): Procedure.PCallGenerator;
+VAR
+    result: POINTER TO DynamicArrayAddCallGenerator;
+BEGIN
+    NEW(result);
+    RETURN result
+END DynamicArrayMethod.callGenerator;
 
 BEGIN
-    (*dynamicArrayAddType := makeMethodType("add", Procedure.makeStd("add", NIL), Procedure.makeProcCallGenerator);*)
-    dynamicArrayAddType := Procedure.makeStd("add", NIL);
+    NEW(dynamicArrayAddMethod);
     NEW(dynamicArrayAdd);
 END EberonTypes.

+ 11 - 18
src/eberon/eberon_context.js

@@ -21,10 +21,10 @@ function log(s){
 }
 */
 
-function superMethodCallGenerator(context, id, type){
+function superMethodCallGenerator(context, type){
     var args = Procedure.makeArgumentsCode(context);
     args.write(Code.makeExpression("this"));
-    return Procedure.makeProcCallGeneratorWithCustomArgs(context, id, type, args);
+    return Procedure.makeProcCallGeneratorWithCustomArgs(context, type, args);
 }
 
 function MethodOrProcMsg(id, type){
@@ -82,15 +82,6 @@ function getMethodSelf(){}
 function getSelfAsPointerMsg(){}
 function getMethodSuper(){}
 
-var MethodVariable = Type.Variable.extend({
-    init: function(type){
-        this.__type = type;
-    },
-    type: function(){return this.__type;},
-    isReadOnly: function(){return true;},
-    idType: function(){return "method";}
-});
-
 var ResultVariable = Type.Variable.extend({
     init: function(e){
         this.__e = e;
@@ -225,7 +216,7 @@ var Designator = Context.Designator.extend({
             var typeId = Type.makeTypeId(this.handleMessage(getSelfAsPointerMsg));
             var pointerType = Type.makePointer("", typeId);
             var info = Type.makeVariable(pointerType, true);
-            this._advance(pointerType, info, "this");
+            this._advance(pointerType, info, "");
         }
         else if (s == "SUPER"){
             var ms = this.handleMessage(getMethodSuper);
@@ -235,7 +226,7 @@ var Designator = Context.Designator.extend({
             Context.Designator.prototype.handleLiteral.call(this, s);
     },
     __beginCall: function(){
-        this.__procCall = Context.makeProcCall(this, this.__currentType, this.__info, this.__code);
+        this.__procCall = Context.makeProcCall(this, this.__currentType, this.__info);
     },
     __endCall: function(){
         var e = this.__procCall.end();
@@ -307,8 +298,10 @@ var ExpressionProcedureCall = Context.Chained.extend({
     setDesignator: function(d){
         var info = d.info();
         var parent = this.parent();
-        if (info instanceof ResultVariable)
-            parent.handleExpression(info.expression());
+        if (info instanceof ResultVariable){
+            var e = info.expression();
+            parent.handleExpression(Code.makeExpressionWithPrecedence(d.code(), d.type(), undefined, e.constValue(), e.maxPrecedence()));
+        }
         else
             parent.setDesignator(d);
     }
@@ -335,10 +328,10 @@ var AssignmentOrProcedureCall = Context.Chained.extend({
             code = op.assign(left, this.__right, this.language());
         }
         else if (!(d.info() instanceof ResultVariable)){
-            var procCall = Context.makeProcCall(this, d.type(), d.info(), d.code());
+            var procCall = Context.makeProcCall(this, d.type(), d.info());
             var result = procCall.end();
             Context.assertProcStatementResult(result.type());
-            code = result.code();
+            code = d.code() + result.code();
         }
         else{
             Context.assertProcStatementResult(d.type());
@@ -366,7 +359,7 @@ var RecordFieldAsMethod = Context.RecordField.extend({
         Context.RecordField.prototype.init.call(this, field, type);
     },
     asVar: function(){ 
-        return new MethodVariable(this.type()); 
+        return EberonTypes.makeMethodVariable(this.type()); 
     }
 });
 var RecordType = Type.Record.extend({

+ 8 - 3
src/ob/Module.ob

@@ -7,8 +7,9 @@ TYPE
     PType* = POINTER TO Type;
 
     AnyType* = RECORD(Types.StorageType)
-        PROCEDURE callGenerator(cx: LanguageContext.PType; id: STRING): Procedure.PCallGenerator;
+        PROCEDURE callGenerator(cx: LanguageContext.PType): Procedure.PCallGenerator;
         PROCEDURE denote(id: STRING): Types.PField;
+        PROCEDURE designatorCode(id: STRING): STRING;
         asField: POINTER TO AnyField;
         asVar: Types.PId
     END;
@@ -35,14 +36,18 @@ PROCEDURE AnyType.initializer(cx: Context.Type; forNew: BOOLEAN): STRING;
     RETURN "undefined"
 END AnyType.initializer;
 
-PROCEDURE AnyType.callGenerator(cx: LanguageContext.PType; id: STRING): Procedure.PCallGenerator;
-    RETURN Procedure.makeProcCallGenerator(cx, id, anyProc)
+PROCEDURE AnyType.callGenerator(cx: LanguageContext.PType): Procedure.PCallGenerator;
+    RETURN Procedure.makeProcCallGenerator(cx, anyProc)
 END AnyType.callGenerator;
 
 PROCEDURE AnyType.denote(id: STRING): Types.PField;
     RETURN any.asField
 END AnyType.denote;
 
+PROCEDURE AnyType.designatorCode(id: STRING): STRING;
+    RETURN id
+END AnyType.designatorCode;
+
 PROCEDURE AnyField.id(): STRING;
     RETURN "any field"
 END AnyField.id;

+ 14 - 16
src/ob/Procedure.ob

@@ -31,8 +31,8 @@ TYPE
     END;
 
     CallGenerator* = RECORD
-        PROCEDURE handleArgument(e: Code.PExpression);
-        PROCEDURE end(): Code.PExpression;
+        PROCEDURE handleArgument*(e: Code.PExpression);
+        PROCEDURE end*(): Code.PExpression;
 
         args: JsArray.Type;
         cx: LanguageContext.PType;
@@ -40,12 +40,8 @@ TYPE
     END;
     PCallGenerator* = POINTER TO CallGenerator;
 
-    Impl = RECORD(Types.Procedure)
-        PROCEDURE callGenerator(cx: LanguageContext.PType): PCallGenerator
-    END;
-
     Type* = RECORD(Types.DefinedProcedure)
-        PROCEDURE callGenerator(cx: LanguageContext.PType; id: STRING): PCallGenerator;
+        PROCEDURE callGenerator(cx: LanguageContext.PType): PCallGenerator;
         PROCEDURE define(args: JsArray.Type; result: Types.PType);
 
         mArgs: JsArray.Type;
@@ -53,7 +49,9 @@ TYPE
     END;
     PType = POINTER TO Type;
 
-    Std* = RECORD(Impl)
+    Std* = RECORD(Types.Procedure)
+        PROCEDURE callGenerator*(cx: LanguageContext.PType): PCallGenerator;
+
         call: PCall
     END;
 
@@ -232,13 +230,11 @@ END GenArgCode.result;
 
 PROCEDURE makeProcCallGeneratorWithCustomArgs*(
     cx: LanguageContext.PType; 
-    id: STRING; 
     type: Types.DefinedProcedure;
     argumentsCode: PArgumentsCode
     ) : PCallGenerator;
 TYPE
     CallImpl = RECORD(Call)
-        id: STRING;
         args: JsArray.Type;
         result: Types.PType;
         argumentsCode: PArgumentsCode
@@ -262,13 +258,12 @@ VAR
             END;
         END;
         RETURN Code.makeSimpleExpression(
-                SELF.id + "(" + SELF.argumentsCode.result() + ")",
+                "(" + SELF.argumentsCode.result() + ")",
                 SELF.result
                 )
     END CallImpl.make;
 BEGIN
     NEW(call);
-    call.id := id;
     call.args := type.args();
     call.result := type.result();
     call.argumentsCode := argumentsCode;
@@ -286,10 +281,9 @@ END makeArgumentsCode;
 
 PROCEDURE makeProcCallGenerator*(
     cx: LanguageContext.PType; 
-    id: STRING; 
     type: Types.DefinedProcedure
     ) : PCallGenerator;
-    RETURN makeProcCallGeneratorWithCustomArgs(cx, id, type, makeArgumentsCode(cx))
+    RETURN makeProcCallGeneratorWithCustomArgs(cx, type, makeArgumentsCode(cx))
 END makeProcCallGenerator;
 
 PROCEDURE Std.description(): STRING;
@@ -300,6 +294,10 @@ PROCEDURE Std.callGenerator(cx: LanguageContext.PType): PCallGenerator;
     RETURN makeCallGenerator(SELF.call, cx)
 END Std.callGenerator;
 
+PROCEDURE Std.designatorCode(id: STRING): STRING;
+    RETURN ""
+END Std.designatorCode;
+
 PROCEDURE makeSymbol*(p: Types.PProcedure): Symbols.PSymbol;
     RETURN Symbols.makeSymbol(p.name, Types.makeProcedure(p))
 END makeSymbol;
@@ -904,8 +902,8 @@ BEGIN
     RETURN result
 END Type.description;
 
-PROCEDURE Type.callGenerator(cx: LanguageContext.PType; id: STRING): PCallGenerator;
-    RETURN makeProcCallGenerator(cx, id, SELF)
+PROCEDURE Type.callGenerator(cx: LanguageContext.PType): PCallGenerator;
+    RETURN makeProcCallGenerator(cx, SELF)
 END Type.callGenerator;
 
 PROCEDURE Type.define(args: JsArray.Type; result: Types.PType);

+ 5 - 0
src/ob/Types.ob

@@ -121,6 +121,7 @@ TYPE
     PPointer* = POINTER TO Pointer;
 
     Procedure* = RECORD(NamedType)
+        PROCEDURE designatorCode*(id: STRING): STRING
     END;
     PProcedure* = POINTER TO Procedure;
 
@@ -573,6 +574,10 @@ PROCEDURE Procedure.description(): STRING;
     RETURN SELF.name
 END Procedure.description;
 
+PROCEDURE DefinedProcedure.designatorCode(id: STRING): STRING;
+    RETURN id
+END DefinedProcedure.designatorCode;
+
 PROCEDURE ProcedureArgument.description(): STRING;
 VAR
     result: STRING;

+ 7 - 2
src/oberon/oberon_context.js

@@ -27,12 +27,14 @@ var ProcedureCall = Context.Chained.extend({
     init: function ProcedureCallContext(context){
         Context.Chained.prototype.init.call(this, context);
         this.__type = undefined;
+        this.__id = undefined;
         this.__procCall = undefined;
         this.__code = Code.makeSimpleGenerator();
     },
     setDesignator: function(d){
         this.__type = d.type();
-        this.__procCall = Context.makeProcCall(this, this.__type, d.info(), d.code());
+        this.__id = d.code();
+        this.__procCall = Context.makeProcCall(this, this.__type, d.info());
         this.__callExpression = undefined;
     },
     codeGenerator: function(){return this.__code;},
@@ -44,7 +46,10 @@ var ProcedureCall = Context.Chained.extend({
     },
     handleExpression: function(e){this.__procCall.handleArgument(e);},
     callExpression: function(){return this.__callExpression;},
-    endParse: function(){this.__callExpression = this.__procCall.end();}
+    endParse: function(){
+        var e = this.__procCall.end();
+        this.__callExpression = Code.makeExpressionWithPrecedence(this.__id + e.code(), e.type(), undefined, e.constValue(), e.maxPrecedence());
+    }
 });
 
 var StatementProcedureCall = ProcedureCall.extend({

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

@@ -56,5 +56,6 @@ function assignDynamicArrayFromStatic(){
 	var static$ = RTL$.makeArray(3, 0);
 	var dynamic = [];
 	RTL$.copy(static$, dynamic);
+	dynamic.push(3);
 }
 }();

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

@@ -13,6 +13,8 @@ VAR
     dynamic: ARRAY * OF INTEGER;
 BEGIN
     dynamic := static;
+
+    dynamic.add(3);
 END assignDynamicArrayFromStatic;
 
 END m.

+ 1 - 0
test/test_unit.js

@@ -64,6 +64,7 @@ return {
          "1 + 2 + 3",
          "-1",
          "+1",
+         "p1()",
          "p1() + p1()",
          "p2()"),
     fail(["", "not parsed"],

+ 2 - 2
test/test_unit_eberon.js

@@ -921,8 +921,8 @@ exports.suite = {
         "add": testWithContext(
             context(grammar.statement, 
                     "VAR a: ARRAY * OF INTEGER;"),
-            pass(/*"a.add(123)"*/),
-            fail()
+            pass("a.add(123)"),
+            fail(["a.add := a.add", "cannot assign to method"])
         )
     }
 };