Ver Fonte

js -> eberon transition + bug fixes

Vladislav Folts há 10 anos atrás
pai
commit
c1f196a127

BIN
bin/compiled.zip


+ 1 - 1
build.py

@@ -130,7 +130,7 @@ def recompile(bin):
     sources = ['ContextAssignment.ob', 'ContextCase.ob', 'ContextConst.ob', 
                'ContextIdentdef.ob', 'ContextLoop.ob', 'ContextModule.ob', 'ContextProcedure.ob', 
                'ContextVar.ob', 'EberonSymbols.ob', 'EberonCast.ob', 
-               'EberonContextExpression.ob', 'EberonContextIdentdef.ob', 'EberonContextType.ob', 'EberonOperatorScopes.ob',
+               'EberonContextExpression.ob', 'EberonContextIdentdef.ob', 'EberonContextInPlace.ob', 'EberonContextType.ob', 'EberonOperatorScopes.ob',
                'OberonContext.ob', 'OberonContextType.ob', 'OberonContextVar.ob',
                'OberonSymbols.ob', 'Lexer.ob', 'Module.ob']
     

+ 1 - 1
src/eberon/EberonContextDesignator.ob

@@ -31,7 +31,7 @@ TYPE
         readOnly: BOOLEAN;
         code: STRING;
     END;
-    PTypeNarrowVariable = POINTER TO TypeNarrowVariable;
+    PTypeNarrowVariable* = POINTER TO TypeNarrowVariable;
 
     DereferencedTypeNarrowVariable = RECORD(EberonTypePromotion.Variable)
         PROCEDURE DereferencedTypeNarrowVariable(var: PTypeNarrowVariable);

+ 96 - 0
src/eberon/EberonContextInPlace.ob

@@ -0,0 +1,96 @@
+MODULE EberonContextInPlace;
+IMPORT
+    CodeGenerator, 
+    ContextExpression, ContextHierarchy, 
+    EberonContextDesignator, EberonRecord,
+    Errors, Expression, LanguageContext, Symbols, Types;
+TYPE
+    VariableInit* = RECORD(ContextExpression.ExpressionHandler)
+        PROCEDURE onParsed();
+
+        id: STRING;
+        code: STRING;
+        symbol: Symbols.PSymbol;
+    END;
+
+    For = RECORD(ContextHierarchy.Node)
+        PROCEDURE handleInPlaceInit(symbol: Symbols.PSymbol; code: STRING);
+    END;
+    PFor = POINTER TO For;
+
+    VariableInitFor* = RECORD(VariableInit)
+        PROCEDURE VariableInitFor(cx: PFor);
+
+        parentFor: PFor;
+    END;
+
+PROCEDURE VariableInit.codeGenerator(): CodeGenerator.PIGenerator;
+    RETURN CodeGenerator.nullGenerator;
+END;
+
+PROCEDURE VariableInit.handleIdent(id: STRING);
+BEGIN
+    SELF.id := id;
+END;
+
+PROCEDURE VariableInit.handleLiteral(s: STRING);
+BEGIN
+    SELF.code := "var " + SELF.id + " = ";
+END;
+
+PROCEDURE VariableInit.handleExpression(e: Expression.PType);
+VAR
+    cloneOp: LanguageContext.PCastOp;
+BEGIN
+    type <- e.type();
+    IF ~(type IS Types.PStorageType) THEN
+        Errors.raise("cannot use " + type.description() + " to initialize variable");
+    ELSIF type IS Types.POpenArray THEN
+        Errors.raise("cannot initialize variable '" + SELF.id + "' with open array");
+    ELSE
+        v <- NEW EberonContextDesignator.TypeNarrowVariable(type, FALSE, FALSE, SELF.id);
+        SELF.symbol := NEW Symbols.Symbol(SELF.id, v);
+
+        IF type IS EberonRecord.PRecord THEN
+            EberonRecord.ensureCanBeInstantiated(SELF, type, EberonRecord.instantiateForCopy);
+            IF e.designator() # NIL THEN
+                l <- SELF.root().language();
+                SELF.code := SELF.code + l.rtl.clone(e.code(), l.types.typeInfo(type), "undefined");
+            ELSE (* do not clone if it is temporary, e.g. constructor call *)
+                SELF.code := SELF.code + e.code();
+            END;
+        ELSE
+            l <- SELF.root().language();
+            void <- l.types.implicitCast(type, type, FALSE, cloneOp);
+            SELF.code := SELF.code + cloneOp.clone(ContextHierarchy.makeLanguageContext(SELF(POINTER)), e);
+        END;
+    END;
+END;
+
+PROCEDURE VariableInit.onParsed();
+BEGIN
+    SELF.parent().codeGenerator().write(SELF.code);
+END;
+
+PROCEDURE VariableInit.endParse(): BOOLEAN;
+BEGIN
+    result <- FALSE;
+    IF SELF.symbol # NIL THEN
+        SELF.root().currentScope().addSymbol(SELF.symbol, FALSE);
+        SELF.onParsed();
+        result := TRUE;
+    END;
+    RETURN result;
+END;
+
+PROCEDURE VariableInitFor.VariableInitFor(cx: PFor)
+    | SUPER(cx),
+      parentFor(cx);
+END;
+
+PROCEDURE VariableInitFor.onParsed();
+BEGIN
+    SELF.parentFor.handleInPlaceInit(SELF.symbol, SELF.code);
+END;
+
+END EberonContextInPlace.

+ 14 - 3
src/eberon/EberonOperator.ob

@@ -1,5 +1,8 @@
 MODULE EberonOperator;
-IMPORT Cast, CodePrecedence, ConstValue, EberonMap, Expression, LanguageContext, OberonRtl, Operator, Record, Types;
+IMPORT 
+    Cast, CodePrecedence, ConstValue, 
+    EberonMap, EberonString, Expression, LanguageContext, 
+    OberonRtl, Operator, Record, Types;
 TYPE
     CastOpRecord = RECORD(Cast.CastOpRecord)
     END;
@@ -42,8 +45,16 @@ PROCEDURE opGraterEqualStr(left, right: ConstValue.PType): ConstValue.PType;
 END opGraterEqualStr;
 
 PROCEDURE addStr*(left, right: Expression.PType): Expression.PType;
-    RETURN Operator.binaryWithCode(left, right, opAddStr, " + ", CodePrecedence.addSub)
-END addStr;
+BEGIN
+    result <- Operator.binaryWithCode(left, right, opAddStr, " + ", CodePrecedence.addSub);
+    l <- left.type();
+    r <- right.type();
+    IF (l # r) & ((l = EberonString.string) OR (r = EberonString.string)) THEN
+        (* change expression type to STRING *)
+        result := NEW Expression.Type(result.code(), EberonString.string, result.designator(), result.constValue(), result.maxPrecedence());
+    END;
+    RETURN result;
+END;
 
 PROCEDURE equalStr*(left, right: Expression.PType; cx: LanguageContext.PType): Expression.PType;
     RETURN Operator.equal(left, right, opEqualStr, Operator.equalCode)

+ 0 - 72
src/eberon/eberon_context.js

@@ -52,13 +52,6 @@ var ChainedContext = ContextHierarchy.Node;
 ChainedContext.extend = Class.extend;
 ChainedContext.prototype.init = ContextHierarchy.Node;
 
-var InPlaceStringLiteral = Class.extend.call(EberonContextDesignator.TypeNarrowVariable, {
-    init: function(type){
-        EberonContextDesignator.TypeNarrowVariable.call(this, type, false, true);
-    },
-    idType: function(){return "string literal";}
-});
-
 var ForEachVariable = Class.extend.call(EberonContextDesignator.TypeNarrowVariable, {
     init: function(type){
         EberonContextDesignator.TypeNarrowVariable.call(this, type, false, true);
@@ -111,69 +104,6 @@ var OperatorNew = ChainedContext.extend({
     }
 });
 
-var InPlaceVariableInit = ChainedContext.extend({
-    init: function EberonContext$InPlaceVariableInit(context){
-        ChainedContext.prototype.init.call(this, context);
-        this.__id = undefined;
-        this._symbol = undefined;
-        this._code = undefined;
-    },
-    codeGenerator: function(){return CodeGenerator.nullGenerator();},
-    handleIdent: function(id){
-        this.__id = id;
-    },
-    handleLiteral: function(){
-        this._code = "var " + this.__id + " = ";
-    },
-    handleExpression: function(e){
-        var type = e.type();
-        var isString = Type.isString(type);
-        if (!isString && !(type instanceof Type.StorageType))
-            throw new Errors.Error("cannot use " + type.description() + " to initialize variable");
-        var v = isString ? new InPlaceStringLiteral(type) 
-                         : new EberonContextDesignator.TypeNarrowVariable(type, false, false, this.__id);
-        this._symbol = new Symbol.Symbol(this.__id, v);
-        if (type instanceof Type.Record){
-            EberonRecord.ensureCanBeInstantiated(this, type, EberonRecord.instantiateForCopy);
-            if (e.designator()){
-                var l = this.root().language();
-                this._code += l.rtl.clone(e.code(), l.types.typeInfo(type));
-            }
-            else // do not clone if it is temporary, e.g. constructor call
-                this._code += e.code();
-        }
-        else {
-            if (type instanceof Type.OpenArray)
-                throw new Errors.Error("cannot initialize variable '" + this.__id + "' with open array");
-          
-            var language = this.root().language();
-            var cloneOp;
-            language.types.implicitCast(type, type, false, {set: function(v){cloneOp = v;}, get:function(){return cloneOp;}});
-            this._code += cloneOp.clone(ContextHierarchy.makeLanguageContext(this), e);
-        }
-    },
-    _onParsed: function(){
-        this.parent().codeGenerator().write(this._code);
-    },
-    endParse: function(){
-        if (!this._symbol)
-            return false;
-
-        this.root().currentScope().addSymbol(this._symbol);
-        this._onParsed();
-        return true;
-    }
-});
-
-var InPlaceVariableInitFor = InPlaceVariableInit.extend({
-    init: function EberonContext$InPlaceVariableInitFor(context){
-        InPlaceVariableInit.prototype.init.call(this, context);
-    },
-    _onParsed: function(){
-        this.parent().handleInPlaceInit(this._symbol, this._code);
-    }
-});
-
 var ExpressionProcedureCall = ChainedContext.extend({
     init: function EberonContext$init(context){
         ChainedContext.prototype.init.call(this, context);
@@ -522,8 +452,6 @@ exports.ModuleDeclaration = ModuleDeclaration;
 exports.AssignmentOrProcedureCall = AssignmentOrProcedureCall;
 exports.MapDecl = MapDecl;
 exports.Repeat = Repeat;
-exports.InPlaceVariableInit = InPlaceVariableInit;
-exports.InPlaceVariableInitFor = InPlaceVariableInitFor;
 exports.OperatorNew = OperatorNew;
 exports.VariableDeclaration = VariableDeclaration;
 exports.While = While;

+ 3 - 2
src/eberon/eberon_grammar.js

@@ -8,6 +8,7 @@ var EbContext = require("eberon/eberon_context.js");
 var EberonContextDesignator = require("js/EberonContextDesignator.js");
 var EberonContextExpression = require("js/EberonContextExpression.js");
 var EberonContextIdentdef = require("js/EberonContextIdentdef.js");
+var EberonContextInPlace = require("js/EberonContextInPlace.js");
 var EberonContextProcedure = require("js/EberonContextProcedure.js");
 var EberonContextType = require("js/EberonContextType.js");
 var Grammar = require("grammar.js");
@@ -50,7 +51,7 @@ function makeInPlaceInit(ident, expression, inPlaceContext){
 
 function makeAssignmentOrProcedureCall(ident, designator, assignment, expression){
     return or(
-        makeInPlaceInit(ident, expression, EbContext.InPlaceVariableInit),
+        makeInPlaceInit(ident, expression, EberonContextInPlace.VariableInit),
         context(and(designator, optional(assignment)), EbContext.AssignmentOrProcedureCall)
         );
 }
@@ -100,7 +101,7 @@ function makeFieldListSequence(base){
 }
 
 function makeForInit(ident, expression, assignment){
-    return or(makeInPlaceInit(ident, expression, EbContext.InPlaceVariableInitFor), 
+    return or(makeInPlaceInit(ident, expression, EberonContextInPlace.VariableInitFor), 
               and(ident, assignment));
 }
 

+ 3 - 18
test/expected/eberon/in_place_variables.js

@@ -21,40 +21,25 @@ function void$(){
 }
 
 function valueArgs(r/*Derived*/, i/*INTEGER*/, a/*ARRAY 10 OF INTEGER*/){
-	var v1 = RTL$.clone(r, {record: {derivedField: null}});
+	var v1 = RTL$.clone(r, {record: {derivedField: null}}, undefined);
 	var v2 = i;
 	var v3 = a.slice();
 }
 
 function varArgs(r/*VAR Derived*/, i/*VAR INTEGER*/, a/*ARRAY 10 OF INTEGER*/){
-	var v1 = RTL$.clone(r, {record: {derivedField: null}});
+	var v1 = RTL$.clone(r, {record: {derivedField: null}}, undefined);
 	var v2 = i.get();
 	var v3 = a.slice();
 }
-
-function pChar(c/*CHAR*/){
-}
-
-function pCharArray(a/*ARRAY OF CHAR*/){
-}
-
-function pString(s/*STRING*/){
-}
 var v1 = 0;
 var v2 = 1.23;
-var v3 = "abc";
-var vs = "\"";
-pChar(vs.charCodeAt(0));
-pChar(34);
-pCharArray(vs);
-pString(vs);
 var v4 = true;
 var v5 = i;
 var v6 = i + i | 0;
 var v7 = p();
 var v8 = void$;
 var do$ = 0;
-var tempRecord = RTL$.clone(r, {record: {derivedField: null}});
+var tempRecord = RTL$.clone(r, {record: {derivedField: null}}, undefined);
 var tempArray = a.slice();
 pdVar = new Derived();
 pbVar = pdVar;

+ 4 - 4
test/input/eberon/in_place_variables.ob

@@ -35,7 +35,7 @@ BEGIN
     v2 <- i;
     v3 <- a;
 END varArgs;
-
+(*
 PROCEDURE pChar(c: CHAR);
 END pChar;
 
@@ -44,17 +44,17 @@ END pCharArray;
 
 PROCEDURE pString(s: STRING);
 END pString;
-
+*)
 BEGIN
     v1 <- 0;
     v2 <- 1.23;
-    v3 <- "abc";
+    (*v3 <- "abc";
     
     vs <- 22X;
     pChar(vs[0]);
     pChar(vs);
     pCharArray(vs);
-    pString(vs);
+    pString(vs);*)
     
     v4 <- TRUE;
     v5 <- i;

+ 7 - 9
test/test_unit_eberon.js

@@ -654,28 +654,26 @@ exports.suite = {
 "in place variables": {
     "initialization": testWithContext(
         context(grammar.statement,
-                "VAR i: INTEGER;"
+                "VAR i: INTEGER; s: STRING;"
                 + "PROCEDURE p(): BOOLEAN; RETURN FALSE END p;"
                 + "PROCEDURE void(); END void;"
                ),
         pass("v <- 0",
              "v <- 1.23",
-             "v <- \"abc\"",
              "v <- TRUE",
              "v <- i",
              "v <- i + i",
+             "v <- \"abc\" + s",
+             "v <- s + \"abc\"",
              "v <- p()",
              "v <- void" // procedure type
             ),
         fail(["v <-", "initialization expression expected"],
              ["v <- void()", "procedure returning no result cannot be used in an expression"],
-             ["v <- NIL", "cannot use NIL to initialize variable"])
-        ),
-    "read-only if initialized with string literal": testWithContext(
-        context(grammar.declarationSequence, ""),
-        pass(),
-        fail(["PROCEDURE p(); BEGIN s <- \"abc\"; s := \"def\"; END p;", "cannot assign to string literal"],
-             ["PROCEDURE p(); BEGIN s <- \"abc\"; s[0] := \"d\"; END p;", "cannot assign to read-only array's element"])
+             ["v <- NIL", "cannot use NIL to initialize variable"],
+             ["v <- \"abc\"", "cannot use multi-character string to initialize variable"],
+             ["v <- \"abc\" + \"def\"", "cannot use multi-character string to initialize variable"]
+             )
         ),
     "scope": testWithContext(
         temporaryValues.context,