Răsfoiți Sursa

js -> eberon transition

Vladislav Folts 10 ani în urmă
părinte
comite
030a9a114b

BIN
bin/compiled.zip


+ 1 - 1
build.py

@@ -127,7 +127,7 @@ def run_tests(bin, unit_test=None, code_test=None):
 def recompile(bin):
     print('recompile oberon sources using "%s"...' % bin)
     compiler = os.path.join(root, 'src', 'oc_nodejs.js')
-    sources = ['ContextDesignator', 'ContextHierarchy.ob', 'EberonSymbols.ob', 'EberonCast.ob', 
+    sources = ['ContextDesignator', 'ContextType.ob', 'EberonSymbols.ob', 'EberonCast.ob', 
                'EberonConstructor.ob', 'EberonOperator.ob', 'EberonScope.ob',
                'OberonSymbols.ob', 'Lexer.ob', 'Module.ob']
     

+ 4 - 96
src/context.js

@@ -6,6 +6,7 @@ var CodeGenerator = require("js/CodeGenerator.js");
 var ConstValue = require("js/ConstValue.js");
 var ContextExpression = require("js/ContextExpression.js");
 var ContextHierarchy = require("js/ContextHierarchy.js");
+var ContextType = require("js/ContextType.js");
 var Designator = require("js/Designator.js");
 var Errors = require("js/Errors.js");
 var Expression = require("js/Expression.js");
@@ -104,41 +105,9 @@ exports.Identdef = ChainedContext.extend({
     }
 });
 
-exports.Type = ChainedContext.extend({
-    init: function Context$Type(context){
-        ChainedContext.prototype.init.call(this, context);
-    },
-    handleQIdent: function(q){
-        this.parent().handleQIdent(q);
-    }
-});
-
-var HandleSymbolAsType = ChainedContext.extend({
-    init: function Context$HandleSymbolAsType(context){
-        ChainedContext.prototype.init.call(this, context);
-    },
-    handleQIdent: function(q){
-        var s = ContextHierarchy.getQIdSymbolAndScope(this.root(), q);
-        this.setType(ContextExpression.unwrapType(s.symbol().info()));
-    }
-});
-
-exports.FormalType = HandleSymbolAsType.extend({
-    init: function FormalType(context){
-        HandleSymbolAsType.prototype.init.call(this, context);
-        this.__arrayDimension = 0;
-    },
-    setType: function(type){           
-        for(var i = 0; i < this.__arrayDimension; ++i)
-            type = new (this.root().language().types.OpenArray)(type);
-        this.parent().setType(type);
-
-    },
-    handleLiteral: function(s){
-        if (s == "ARRAY")
-            ++this.__arrayDimension;
-    }
-});
+var HandleSymbolAsType = ContextType.HandleSymbolAsType;
+HandleSymbolAsType.extend = Class.extend;
+HandleSymbolAsType.prototype.init = ContextType.HandleSymbolAsType;
 
 var ProcArg = Class.extend({
     init: function(type, isVar){
@@ -381,67 +350,6 @@ exports.PointerDecl = ChainedContext.extend({
     }
 });
 
-exports.ArrayDecl = HandleSymbolAsType.extend({
-    init: function Context$ArrayDecl(context){
-        HandleSymbolAsType.prototype.init.call(this, context);
-        this.__dimensions = undefined;
-    },
-    handleDimensions: function(dimensions){this.__dimensions = dimensions;},
-    setType: function(elementsType){
-        var type = elementsType;
-        var dimensions = "";
-        for(var i = this.__dimensions.length; i-- ;){
-            var length = this.__dimensions[i];
-            dimensions = length + (dimensions.length ? ", " + dimensions : "");
-            var arrayInit = i ? undefined
-                              : this._makeInit(elementsType, dimensions, length);
-            type = this._makeType(type, arrayInit, length);
-        }
-
-        this.__type = type;
-    },
-    isAnonymousDeclaration: function(){return true;},
-    endParse: function(){this.parent().setType(this.__type);},
-    _makeInit: function(type, dimensions, length){
-        var rtl = this.root().language().rtl();
-        if (type == basicTypes.ch)
-            return rtl.makeCharArray(dimensions);
-
-        var initializer = type instanceof Type.Array || type instanceof Type.Record
-            ? "function(){return " + type.initializer(this) + ";}"
-            : type.initializer(this);
-        return rtl.makeArray(dimensions + ", " + initializer);
-    },
-    _makeType: function(elementsType, init, length){
-        return new (this.root().language().types.StaticArray)(init, elementsType, length);
-    }
-});
-
-exports.ArrayDimensions = ChainedContext.extend({
-    init: function ArrayDimensionsContext(context){
-        ChainedContext.prototype.init.call(this, context);
-        this.__dimensions = [];
-    },
-    codeGenerator: function(){return nullCodeGenerator;},
-    handleExpression: function(e){
-        var type = e.type();
-        if (type !== basicTypes.integer)
-            throw new Errors.Error("'INTEGER' constant expression expected, got '" + type.description() + "'");
-        var value = e.constValue();
-        if (!value)
-            throw new Errors.Error("constant expression expected as ARRAY size");
-        if (value.value <= 0)
-            throw new Errors.Error("array size must be greater than 0, got " + value.value);
-        this._addDimension(value.value);
-    },
-    endParse: function(){
-        this.parent().handleDimensions(this.__dimensions);
-    },
-    _addDimension: function(size){
-        this.__dimensions.push(size);
-    }
-});
-
 function handleIfExpression(e){
     var type = e.type();
     if (type !== basicTypes.bool)

+ 17 - 14
src/eberon/eberon_context.js

@@ -8,6 +8,7 @@ var Context = require("context.js");
 var ContextDesignator = require("js/ContextDesignator.js");
 var ContextExpression = require("js/ContextExpression.js");
 var ContextHierarchy = require("js/ContextHierarchy.js");
+var ContextType = require("js/ContextType.js");
 var EberonConstructor= require("js/EberonConstructor.js");
 var EberonContext= require("js/EberonContext.js");
 var EberonDynamicArray = require("js/EberonDynamicArray.js");
@@ -1226,15 +1227,15 @@ var For = Context.For.extend({
 
 var dynamicArrayLength = -1;
 
-var ArrayDimensions = Context.ArrayDimensions.extend({
+var ArrayDimensions = Class.extend.call(ContextType.ArrayDimensions, {
     init: function EberonContext$ArrayDimensions(context){
-        Context.ArrayDimensions.prototype.init.call(this, context);
+        ContextType.ArrayDimensions.call(this, context);
     },
     handleLiteral: function(s){
         if ( s == "*" )
-            this._addDimension(dynamicArrayLength);
+            this.doAddDimension(dynamicArrayLength);
         else
-            Context.ArrayDimensions.prototype.handleLiteral.call(this, s);
+            ContextType.ArrayDimensions.prototype.handleLiteral.call(this, s);
     }
 });
 
@@ -1311,23 +1312,23 @@ var ForEach = Context.Chained.extend({
     }
 });
 
-var ArrayDecl = Context.ArrayDecl.extend({
+var ArrayDecl = Class.extend.call(ContextType.Array, {
     init: function EberonContext$ArrayDecl(context){
-        Context.ArrayDecl.prototype.init.call(this, context);
+        ContextType.Array.call(this, context);
     },
-    _makeInit: function(type, dimensions, length){
+    doMakeInit: function(type, dimensions, length){
         if (length == dynamicArrayLength)
             return '[]';
 
         if (type instanceof EberonRecord.Record && EberonRecord.hasParameterizedConstructor(type))
             throw new Errors.Error("cannot use '" + Type.typeName(type) + "' as an element of static array because it has constructor with parameters");
 
-        return Context.ArrayDecl.prototype._makeInit.call(this, type, dimensions, length);
+        return ContextType.Array.prototype.doMakeInit.call(this, type, dimensions, length);
     },
-    _makeType: function(elementsType, init, length){
+    doMakeType: function(elementsType, init, length){
         return length == dynamicArrayLength
             ? new EberonDynamicArray.DynamicArray(elementsType)
-            : Context.ArrayDecl.prototype._makeType.call(this, elementsType, init, length);
+            : ContextType.Array.prototype.doMakeType.call(this, elementsType, init, length);
     }
 });
 
@@ -1367,11 +1368,13 @@ var FormalType = Context.HandleSymbolAsType.extend({
         this.__dynamicDimension = false;
     },
     setType: function(type){           
+        function makeDynamic(type){return new EberonDynamicArray.DynamicArray(type); }
+
         for(var i = this.__arrayDimensions.length; i--;){
-            var Cons = this.__arrayDimensions[i]
-                ? EberonDynamicArray.DynamicArray
-                : this.root().language().types.OpenArray;
-            type = new Cons(type);
+            var cons = this.__arrayDimensions[i]
+                ? makeDynamic
+                : this.root().language().types.makeOpenArray;
+            type = cons(type);
         }
         this.parent().setType(type);
     },

+ 2 - 2
src/eberon/eberon_grammar.js

@@ -167,8 +167,8 @@ exports.language = {
             return Cast.implicit(from, to, toVar, EbOperator.castOperations(), op);
         },
         typeInfo: function(type){return EbOperator.generateTypeInfo(type);},
-        StaticArray: EbArray.StaticArray,
-        OpenArray: EbArray.OpenArray
+        makeStaticArray: function(type, init, length){ return new EbArray.StaticArray(init, type, length); },
+        makeOpenArray: function(type){return new EbArray.OpenArray(type); }
     },
     codeGenerator: {
         make: CodeGenerator.makeGenerator,

+ 1 - 1
src/grammar.js

@@ -59,7 +59,7 @@ var designator = makeDesignator(
         // break recursive declaration of actualParameters
         function(stream, context){return actualParameters(stream, context);}
         );
-var type = or(context(qualident, Context.Type),
+var type = or(qualident,
               function(stream, context){return strucType(stream, context);} // break recursive declaration of strucType
              );
 var identList = and(identdef, repeat(and(",", identdef)));

+ 5 - 5
src/ob/ContextExpression.ob

@@ -4,10 +4,8 @@ IMPORT
     Designator, Errors, Expression, JS, LanguageContext, Operator, 
     Procedure, Record, Scope, String, TypeId, Types;
 TYPE
-    ExpressionHandler = RECORD(ContextHierarchy.Node)
-        PROCEDURE handleExpression(e: Expression.PType);
-
-        expression: Expression.PType;
+    ExpressionHandler* = RECORD(ContextHierarchy.Node)
+        PROCEDURE handleExpression*(e: Expression.PType);
     END;
     PExpressionHandler = POINTER TO ExpressionHandler;
 
@@ -66,6 +64,7 @@ TYPE
         PROCEDURE handleConst(type: Types.PType; value: ConstValue.PType; code: STRING);
         PROCEDURE handleLogicalNot();
 
+        expression: Expression.PType;
         logicalNot: BOOLEAN;
     END;
 
@@ -73,6 +72,7 @@ TYPE
         PROCEDURE type(): Types.PType;
         PROCEDURE handleOperator(op: BinaryOperator);
 
+        expression: Expression.PType;
         operator: BinaryOperator;
     END;
     PTerm = POINTER TO Term;
@@ -219,7 +219,7 @@ BEGIN
     RETURN result;
 END;
 
-PROCEDURE unwrapType*(id: Types.PId): Types.PType;
+PROCEDURE unwrapType*(id: Types.PId): Types.PStorageType;
     RETURN unwrapTypeId(id).type();
 END;
 

+ 154 - 0
src/ob/ContextType.ob

@@ -0,0 +1,154 @@
+MODULE ContextType;
+IMPORT
+    CodeGenerator, ConstValue, ContextExpression, ContextHierarchy, 
+    Errors, Expression, String, Types;
+TYPE
+    HandleSymbolAsType* = RECORD(ContextHierarchy.Node)
+        PROCEDURE handleQIdent(q: ContextHierarchy.QIdent);
+        PROCEDURE setType(type: Types.PStorageType);
+    END;
+    PHandleSymbolAsType = POINTER TO HandleSymbolAsType;
+
+    FormalType* = RECORD(HandleSymbolAsType)
+        PROCEDURE FormalType(parent: PHandleSymbolAsType);
+
+        handleType: PHandleSymbolAsType;
+        dimensionCount: INTEGER;
+    END;
+
+    Array* = RECORD(HandleSymbolAsType)
+        PROCEDURE Array(parent: PHandleSymbolAsType);
+
+        PROCEDURE isAnonymousDeclaration(): BOOLEAN;
+        PROCEDURE doMakeInit(type: Types.PStorageType; dimensions: STRING; length: INTEGER): STRING;
+        PROCEDURE doMakeType(elementsType: Types.PType; init: STRING; length: INTEGER): Types.PStorageType;
+
+        handleType: PHandleSymbolAsType;
+        dimensions: POINTER TO ArrayDimensions;
+        type: Types.PStorageType;
+    END;
+
+    ArrayDimensions* = RECORD(ContextExpression.ExpressionHandler) 
+        PROCEDURE doAddDimension(size: INTEGER);
+
+        dimensions: ARRAY * OF INTEGER;
+    END;
+
+PROCEDURE HandleSymbolAsType.handleQIdent(q: ContextHierarchy.QIdent);
+BEGIN
+    s <- ContextHierarchy.getQIdSymbolAndScope(SELF.root()^, q);
+    SELF.setType(ContextExpression.unwrapType(s.symbol().info()));
+END;
+
+PROCEDURE FormalType.FormalType(parent: PHandleSymbolAsType)
+    | SUPER(parent),
+      handleType(parent);
+END;
+
+PROCEDURE FormalType.setType(type: Types.PStorageType);
+BEGIN
+    result <- type;
+    types <- SELF.root().language().types;
+    FOR i <- 0 TO SELF.dimensionCount - 1 DO
+        result := types.makeOpenArray(result);
+    END;
+    SELF.handleType.setType(result);
+END;
+
+PROCEDURE FormalType.handleLiteral(s: STRING);
+BEGIN
+    IF s = "ARRAY" THEN
+        INC(SELF.dimensionCount);
+    END;
+END;
+
+PROCEDURE Array.Array(parent: PHandleSymbolAsType)
+    | SUPER(parent),
+      handleType(parent);
+END;
+
+PROCEDURE Array.setType(elementsType: Types.PStorageType);
+VAR
+    dimensions: STRING;
+    arrayInit: STRING;
+BEGIN
+    type <- elementsType;
+    FOR i <- LEN(SELF.dimensions.dimensions) - 1 TO 0 BY -1 DO
+        IF LEN(dimensions) # 0 THEN
+            dimensions := ", " + dimensions;
+        END;
+        length <- SELF.dimensions.dimensions[i];
+        dimensions := String.fromInt(length) + dimensions;
+        IF i = 0 THEN
+            arrayInit := SELF.doMakeInit(elementsType, dimensions, length);
+        END;
+        type := SELF.doMakeType(type, arrayInit, length);
+    END;
+
+    SELF.type := type;
+END;
+
+PROCEDURE Array.isAnonymousDeclaration(): BOOLEAN;
+    RETURN TRUE;
+END;
+
+PROCEDURE Array.doMakeInit(type: Types.PStorageType; dimensions: STRING; length: INTEGER): STRING;
+VAR
+    result: STRING;
+    initializer: STRING;
+BEGIN
+    rtl <- SELF.root().language().rtl();
+    IF type = Types.basic.ch THEN
+        result := rtl.makeCharArray(dimensions);
+    ELSE
+        IF (type IS Types.PArray) OR (type IS Types.PRecord) THEN
+            initializer := "function(){return " + type.initializer(SELF) + ";}";
+        ELSE
+            initializer := type.initializer(SELF);
+        END;
+        result := rtl.makeArray(dimensions + ", " + initializer);
+    END;
+    RETURN result;
+END;
+
+PROCEDURE Array.doMakeType(elementsType: Types.PType; init: STRING; length: INTEGER): Types.PStorageType;
+    RETURN SELF.root().language().types.makeStaticArray(elementsType, init, length);
+END;
+
+PROCEDURE Array.endParse();
+BEGIN
+    SELF.handleType.setType(SELF.type);
+END;
+
+PROCEDURE ArrayDimensions.handleExpression(e: Expression.PType);
+BEGIN
+    type <- e.type();
+    IF type # Types.basic.integer THEN
+        Errors.raise("'INTEGER' constant expression expected, got '" + type.description() + "'");
+    END;
+    value <- e.constValue();
+    IF value = NIL THEN
+        Errors.raise("constant expression expected as ARRAY size");
+    END;
+    dimension <- value(ConstValue.PInt).value;
+    IF dimension <= 0 THEN
+        Errors.raise("array size must be greater than 0, got " + String.fromInt(dimension));
+    END;
+    SELF.doAddDimension(dimension);
+END;
+
+PROCEDURE ArrayDimensions.doAddDimension(size: INTEGER);
+BEGIN
+    SELF.dimensions.add(size);
+END;
+
+PROCEDURE ArrayDimensions.codeGenerator(): CodeGenerator.PIGenerator;
+    RETURN CodeGenerator.nullGenerator;
+END;
+
+PROCEDURE ArrayDimensions.endParse();
+BEGIN
+    SELF.parent()^(Array).dimensions := SELF(POINTER);
+END;
+
+END ContextType.

+ 2 - 0
src/ob/LanguageContext.ob

@@ -15,6 +15,8 @@ TYPE
     Types* = RECORD         
         PROCEDURE implicitCast*(from, to: T.PType; toVar: BOOLEAN; VAR op: PCastOp): INTEGER;
         PROCEDURE typeInfo*(type: T.PType): STRING;
+        PROCEDURE makeOpenArray*(type: T.PType): T.PStorageType;
+        PROCEDURE makeStaticArray*(type: T.PType; init: STRING; length: INTEGER): T.PStorageType;
     END;
     PTypes* = POINTER TO Types;
 

+ 2 - 0
src/ob/OberonRtl.ob

@@ -10,6 +10,8 @@ TYPE
         setInclR*: PROCEDURE(l, r: STRING): STRING;
         assertId*: PROCEDURE(): STRING;
         makeRef*: PROCEDURE(derefCode, propCode: STRING): STRING;
+        PROCEDURE makeArray*(dimensions: STRING): STRING;
+        PROCEDURE makeCharArray*(dimensions: STRING): STRING;
         PROCEDURE typeGuard*(from, to: STRING): STRING;
     END;
     PType* = POINTER TO Type;

+ 10 - 10
src/ob/TypeId.ob

@@ -4,16 +4,16 @@ IMPORT
 TYPE
     PType* = POINTER TO Type;
     Type* = RECORD(Types.Id)
-        PROCEDURE Type*(type: Types.PType);
+        PROCEDURE Type*(type: Types.PStorageType);
 
-        PROCEDURE type*(): Types.PType;
-        PROCEDURE reset*(type: Types.PType);
+        PROCEDURE type*(): Types.PStorageType;
+        PROCEDURE reset*(type: Types.PStorageType);
         PROCEDURE description*(): STRING;
 
-        mType: Types.PType
+        mType: Types.PStorageType;
     END;
 
-    ResolveTypeCallback = PROCEDURE(): Types.PType;
+    ResolveTypeCallback = PROCEDURE(): Types.PStorageType;
 
     Forward* = RECORD(Type)
         PROCEDURE Forward(resolve: ResolveTypeCallback);
@@ -33,11 +33,11 @@ PROCEDURE Type.description(): STRING;
     RETURN "type " + SELF.type().description()
 END;
 
-PROCEDURE Type.type(): Types.PType;
+PROCEDURE Type.type(): Types.PStorageType;
     RETURN SELF.mType
 END;
 
-PROCEDURE Type.reset(type: Types.PType);
+PROCEDURE Type.reset(type: Types.PStorageType);
 BEGIN
     SELF.mType := type;
 END;
@@ -47,7 +47,7 @@ PROCEDURE Forward.Forward(resolve: ResolveTypeCallback)
       resolve(resolve);
 END;
 
-PROCEDURE Forward.type(): Types.PType;
+PROCEDURE Forward.type(): Types.PStorageType;
 BEGIN
     IF SELF.mType = NIL THEN
         SELF.mType := SELF.resolve();
@@ -55,7 +55,7 @@ BEGIN
     RETURN SELF.mType
 END;
 
-PROCEDURE define*(VAR tId: Lazy; t: Types.PType);
+PROCEDURE define*(VAR tId: Lazy; t: Types.PStorageType);
 BEGIN
     tId.mType := t;
 END;
@@ -64,7 +64,7 @@ PROCEDURE Type.idType(): STRING;
     RETURN "type"
 END Type.idType;
 
-PROCEDURE Type.Type(type: Types.PType)
+PROCEDURE Type.Type(type: Types.PStorageType)
     | mType(type);
 END;
 

+ 6 - 5
src/oberon/oberon_grammar.js

@@ -5,6 +5,7 @@ var CodeGenerator = require("js/CodeGenerator.js");
 var Context = require("context.js");
 var ContextDesignator = require("js/ContextDesignator.js");
 var ContextExpression = require("js/ContextExpression.js");
+var ContextType = require("js/ContextType.js");
 var Grammar = require("grammar.js");
 var ObContext = require("oberon/oberon_context.js");
 var ObRtl = require("js/OberonRtl.js");
@@ -78,7 +79,7 @@ function makeForInit(ident, expression, assignment){
 
 function makeArrayDimensions(constExpression){
     return context(and(constExpression, repeat(and(",", constExpression))), 
-                   Context.ArrayDimensions);
+                   ContextType.ArrayDimensions);
 }
 
 function makeFormalArray(){
@@ -111,10 +112,10 @@ exports.language = {
             typeDeclaration:    Context.TypeDeclaration,
             recordDecl:         ObContext.RecordDecl,
             variableDeclaration: ObContext.VariableDeclaration,
-            ArrayDecl:          Context.ArrayDecl,
+            ArrayDecl:          ContextType.Array,
             Factor:             ContextExpression.Factor,
             FormalParameters:   Context.FormalParameters,
-            FormalType:         Context.FormalType,
+            FormalType:         ContextType.FormalType,
             Term:               ContextExpression.Term,
             AddOperator:        ContextExpression.AddOperator,
             MulOperator:        ContextExpression.MulOperator,
@@ -136,8 +137,8 @@ exports.language = {
             return Cast.implicit(from, to, toVar, Operator.castOperations(), op);
         },
         typeInfo: function(type){return Record.generateTypeInfo(type);},
-        StaticArray: Types.StaticArray,
-        OpenArray: Types.OpenArray
+        makeStaticArray: function(type, init, length){ return new Types.StaticArray(init, type, length); },
+        makeOpenArray: function(type){return new Types.OpenArray(type); }
     },
     codeGenerator: {
         make: CodeGenerator.makeGenerator,