Selaa lähdekoodia

js -> eberon transition

Vladislav Folts 10 vuotta sitten
vanhempi
commit
bec7f17f96

BIN
bin/compiled.zip


+ 1 - 0
build.py

@@ -131,6 +131,7 @@ def recompile(bin):
                'ContextIdentdef.ob', 'ContextLoop.ob', 'ContextModule.ob', 'ContextProcedure.ob', 
                'ContextVar.ob', 'EberonSymbols.ob', 'EberonCast.ob', 
                'EberonConstructor.ob', 'EberonOperator.ob', 'EberonScope.ob',
+               'EberonTypePromotion.ob',
                'OberonContext.ob', 'OberonContextType.ob', 'OberonContextVar.ob',
                'OberonSymbols.ob', 'Lexer.ob', 'Module.ob']
     

+ 215 - 0
src/eberon/EberonTypePromotion.ob

@@ -0,0 +1,215 @@
+MODULE EberonTypePromotion;
+IMPORT
+    Types;
+TYPE
+    Variable = RECORD
+        PROCEDURE type(): Types.PType;
+        PROCEDURE setType(type: Types.PType);
+    END;
+    PVariable = POINTER TO Variable;
+
+    Type = RECORD
+        PROCEDURE and();
+        PROCEDURE or();
+        PROCEDURE reset();
+    END;
+    PType = POINTER TO Type;
+
+    ForVariable* = RECORD(Type)
+        PROCEDURE ForVariable(v: PVariable; type: Types.PType; inverted: BOOLEAN);
+
+        PROCEDURE invert();
+
+        v: PVariable;
+        type, originalType: Types.PType;
+        inverted: BOOLEAN;
+    END;
+
+    Operation = PROCEDURE(p: Type);
+    PMaybe = POINTER TO Maybe;
+
+    Combined = RECORD(Type)
+        PROCEDURE Combined(op, invertedOp: Operation; inverted: BOOLEAN);
+
+        PROCEDURE clear();
+        PROCEDURE next(): PMaybe;
+
+        op, invertedOp: Operation;
+        inverted: BOOLEAN;
+        promotions: ARRAY * OF PType;
+        current: PType;
+        count: INTEGER;
+    END;
+    PCombined = POINTER TO Combined;
+
+    And* = RECORD(Combined)
+        PROCEDURE And(inverted: BOOLEAN);
+    END;
+
+    Or* = RECORD(Combined)
+        PROCEDURE Or(inverted: BOOLEAN);
+    END;
+
+    Maybe = RECORD
+        PROCEDURE Maybe(handler: PCombined);
+
+        PROCEDURE promote(v: PVariable; type: Types.PType);
+        PROCEDURE invert();
+        PROCEDURE makeOr(): PCombined;
+        PROCEDURE makeAnd(): PCombined;
+
+        inverted: BOOLEAN;
+        handler: PCombined;
+    END;
+
+PROCEDURE ForVariable.ForVariable(v: PVariable; type: Types.PType; inverted: BOOLEAN)
+    | v(v),
+      type(type),
+      originalType(v.type()),
+      inverted(inverted);
+END;
+
+PROCEDURE ForVariable.and();
+BEGIN
+    IF ~SELF.inverted THEN
+        SELF.v.setType(SELF.type);
+    END;
+END;
+
+PROCEDURE ForVariable.or();
+BEGIN
+    IF SELF.inverted THEN
+        SELF.v.setType(SELF.type);
+    END;
+END;
+
+PROCEDURE ForVariable.reset();
+BEGIN
+    SELF.v.setType(SELF.originalType);
+END;
+
+PROCEDURE ForVariable.invert();
+BEGIN
+    SELF.inverted := ~SELF.inverted;
+END;
+
+PROCEDURE Maybe.Maybe(handler: PCombined)
+    | handler(handler);
+END;
+
+PROCEDURE handlePromotion(VAR handler: Combined; p: PType);
+BEGIN
+    ASSERT(handler.current = NIL);
+    handler.promotions.add(p);
+    handler.current := p;
+END;
+
+PROCEDURE Maybe.promote(v: PVariable; type: Types.PType);
+BEGIN
+    handlePromotion(SELF.handler^, NEW ForVariable(v, type, SELF.inverted));
+END;
+
+PROCEDURE Maybe.invert();
+BEGIN
+    SELF.inverted := ~SELF.inverted;
+END;
+
+PROCEDURE Maybe.makeOr(): PCombined;
+BEGIN
+    result <- NEW Or(SELF.inverted);
+    handlePromotion(SELF.handler^, result);
+    RETURN result;
+END;
+
+PROCEDURE Maybe.makeAnd(): PCombined;
+BEGIN
+    result <- NEW And(SELF.inverted);
+    handlePromotion(SELF.handler^, result);
+    RETURN result;
+END;
+
+PROCEDURE applyForAll(p: Combined);
+BEGIN
+    FOR i <- 0 TO LEN(p.promotions) - 1 DO
+        p.op(p.promotions[i]^);
+    END;
+END;
+
+PROCEDURE applyIfSingle(p: Combined);
+BEGIN
+    IF p.count > 1 THEN
+        p.reset();
+    ELSIF p.current # NIL THEN
+        p.invertedOp(p.current^);
+    END;
+END;
+
+PROCEDURE Combined.Combined(op, invertedOp: Operation; inverted: BOOLEAN)
+    | op(op),
+      invertedOp(invertedOp),
+      inverted(inverted);
+END;
+
+PROCEDURE Combined.and();
+BEGIN
+    IF SELF.inverted THEN
+        applyForAll(SELF);
+    ELSE
+        applyIfSingle(SELF);
+    END;
+END;
+
+PROCEDURE Combined.or();
+BEGIN
+    IF SELF.inverted THEN
+        applyIfSingle(SELF);
+    ELSE
+        applyForAll(SELF);
+    END;
+END;
+
+PROCEDURE Combined.reset();
+BEGIN
+    FOR i <- LEN(SELF.promotions) - 1 TO 0 BY -1 DO
+        p <- SELF.promotions[i];
+        p.reset();
+    END;
+END;
+
+PROCEDURE Combined.clear();
+BEGIN
+    SELF.reset();
+    SELF.promotions.clear();
+    SELF.current := NIL;
+    SELF.count := 0;
+END;
+
+PROCEDURE Combined.next(): PMaybe;
+BEGIN
+    IF SELF.current # NIL THEN
+        SELF.op(SELF.current^);
+        SELF.current := NIL;
+    END;
+    INC(SELF.count);
+    RETURN NEW Maybe(SELF(POINTER));
+END;
+
+PROCEDURE and(p: Type);
+BEGIN
+    p.and();
+END;
+
+PROCEDURE or(p: Type);
+BEGIN
+    p.or();
+END;
+
+PROCEDURE And.And(inverted: BOOLEAN)
+    | SUPER(and, or, ~inverted);
+END;
+
+PROCEDURE Or.Or(inverted: BOOLEAN)
+    | SUPER(or, and, inverted);
+END;
+
+END EberonTypePromotion.

+ 4 - 4
src/eberon/eberon_context.js

@@ -34,7 +34,7 @@ var Procedure = require("js/Procedure.js");
 var Record = require("js/Record.js");
 var Type = require("js/Types.js");
 var TypeId = require("js/TypeId.js");
-var TypePromotion = require("eberon/eberon_type_promotion.js");
+var TypePromotion = require("js/EberonTypePromotion.js");
 var Variable = require("js/Variable.js");
 
 /*
@@ -610,7 +610,7 @@ function handleTypePromotionMadeInSeparateStatement(msg){
     if (breakTypePromotion(msg))
         return true;
     if (msg instanceof BeginTypePromotionOrMsg){
-        msg.result = new TypePromotion.OrPromotions();
+        msg.result = new TypePromotion.Or();
         return true;
     }
     return false;
@@ -1085,12 +1085,12 @@ var OperatorScopes = Class.extend({
         if (msg instanceof TransferPromotedTypesMsg)
             return true;
         if (msg instanceof PromoteTypeMsg){
-            this.__typePromotion = new TypePromotion.Promotion(msg.info, msg.type);
+            this.__typePromotion = new TypePromotion.ForVariable(msg.info, msg.type);
             this.__typePromotions.push(this.__typePromotion);
             return true;
         }
         if (msg instanceof BeginTypePromotionOrMsg){
-            this.__typePromotion = new TypePromotion.OrPromotions();
+            this.__typePromotion = new TypePromotion.Or();
             this.__typePromotions.push(this.__typePromotion);
             msg.result = this.__typePromotion;
             return true;

+ 0 - 140
src/eberon/eberon_type_promotion.js

@@ -1,140 +0,0 @@
-"use strict";
-
-var Class = require("rtl.js").Class;
-
-function log(s){
-    //console.info(s);
-}
-
-function assert(condition){
-    if (!condition)
-        throw new Error("assertion failed");
-}
-
-var Promotion = Class.extend({
-    init: function EberonTypePromotion$Promotion(v, type, inverted){
-        this.__v = v;
-        this.__type = type;
-        this.__originalType = v.type();
-        this.__inverted = inverted;
-    },
-    and: function(){
-        if (!this.__inverted)
-            this.__v.setType(this.__type);
-    },
-    or: function(){
-        if (this.__inverted)
-            this.__v.setType(this.__type);
-    },
-    reset: function(){
-        this.__v.setType(this.__originalType);
-    },
-    invert: function(){
-        this.__inverted = !this.__inverted;
-    }
-});
-
-var MaybePromotion = Class.extend({
-    init: function EberonTypePromotion$Promotion(handle){
-        this.__inverted = false;
-        this.__handle = handle;
-    },
-    promote: function(v, type){
-        log("promote: " + type.name);
-        this.__handle(new Promotion(v, type, this.__inverted));
-    },
-    invert: function(){
-        this.__inverted = !this.__inverted;
-    },
-    makeOr: function(){
-        var result = new OrPromotions(this.__inverted);
-        this.__handle(result);
-        return result;
-    },
-    makeAnd: function(){
-        var result = new AndPromotions(this.__inverted);
-        this.__handle(result);
-        return result;
-    }
-});
-
-var CombinedPromotion = Class.extend({
-    init: function EberonTypePromotion$CombinedPromotion(op, invertedOp, inverted){
-        this.__op = op;
-        this.__invertedOp = invertedOp;
-        this.__inverted = inverted;
-        this.__promotions = [];
-        this.__current = undefined;
-        this.__count = 0;
-    },
-    and: function(){
-        log("combined and(" + this.__op + "), inverted: " + this.__inverted);
-        if (this.__inverted)
-            this.__applyForAll();
-        else
-            this.__applyIfSingle();
-    },
-    or: function(){
-        log("combined or(" + this.__op + "), inverted: " + this.__inverted);
-        if (this.__inverted)
-            this.__applyIfSingle();
-        else
-            this.__applyForAll();
-    },
-    reset: function(){
-        for(var i = this.__promotions.length; i--;){
-            var p = this.__promotions[i];
-            p.reset();
-        }
-    },
-    clear: function(){
-        this.reset();
-        this.__promotions = [];
-        this.__current = undefined;
-        this.__count = 0;
-    },
-    next: function(p){
-        log("next " + this.__op + ": " + this.__current);
-        if (this.__current)
-            this.__current[this.__op]();
-
-        this.__current = undefined;
-        ++this.__count;
-
-        return new MaybePromotion(this.__handlePromotion.bind(this));
-    },
-    __applyForAll: function(){
-        for(var i = 0; i < this.__promotions.length; ++i)
-            this.__promotions[i][this.__op]();
-    },
-    __applyIfSingle: function(op){
-        log("applyIfSingle: " + this.__count);
-        if (this.__count > 1)
-            this.reset();
-        else if (this.__current)
-            this.__current[this.__invertedOp]();
-    },
-    __handlePromotion: function(p){
-        assert(!this.__current);
-        this.__promotions.push(p);
-        this.__current = p;
-    }
-});
-
-var AndPromotions = CombinedPromotion.extend({
-    init: function EberonTypePromotion$AndPromotions(inverted){
-        log("AndPromotions");
-        CombinedPromotion.prototype.init.call(this, "and", "or", !inverted);
-    }
-});
-
-var OrPromotions = CombinedPromotion.extend({
-    init: function EberonTypePromotion$OrPromotions(inverted){
-        log("OrPromotions");
-        CombinedPromotion.prototype.init.call(this, "or", "and", inverted);
-    }
-});
-
-exports.Promotion = Promotion;
-exports.AndPromotions = AndPromotions;
-exports.OrPromotions = OrPromotions;

+ 10 - 10
test/test_unit_eberon.js

@@ -4,7 +4,7 @@ var Class = require("rtl.js").Class;
 //var EberonCodeGenerator = require("js/EberonCodeGenerator.js");
 var language = require("eberon/eberon_grammar.js").language;
 var TestUnitCommon = require("test_unit_common.js");
-var TypePromotion = require("eberon/eberon_type_promotion.js");
+var TypePromotion = require("js/EberonTypePromotion.js");
 
 var assert = TestUnitCommon.assert;
 var pass = TestUnitCommon.pass;
@@ -532,7 +532,7 @@ exports.suite = {
 "type promotion": {
     "or" : pass(
         function(){
-            var or = new TypePromotion.OrPromotions();
+            var or = new TypePromotion.Or();
             var a = new TestVar();
             var p = or.next();
             assert(a.type() == "type");
@@ -545,7 +545,7 @@ exports.suite = {
             assert(a.type() == "type");
         },
         function(){
-            var or = new TypePromotion.OrPromotions();
+            var or = new TypePromotion.Or();
             var a = new TestVar();
             var p = or.next(p);
             p.promote(a, "type1");
@@ -553,7 +553,7 @@ exports.suite = {
             assert(a.type() == "type");
         },
         function(){
-            var or = new TypePromotion.OrPromotions();
+            var or = new TypePromotion.Or();
             var a = new TestVar();
             var p1 = or.next();
             p1.promote(a, "type1");
@@ -570,7 +570,7 @@ exports.suite = {
     ),
     "and": pass(
         function(){
-            var and = new TypePromotion.AndPromotions();
+            var and = new TypePromotion.And();
             var a = new TestVar();
             var p = and.next();
             p.promote(a, "type1");
@@ -580,7 +580,7 @@ exports.suite = {
             assert(a.type() == "type");
         },
         function(){ // (a IS type1) & (v OR (a IS type2)) & v
-            var and = new TypePromotion.AndPromotions();
+            var and = new TypePromotion.And();
             var a = new TestVar();
             var p = and.next();
             p.promote(a, "type1");
@@ -593,7 +593,7 @@ exports.suite = {
             assert(a.type() == "type");
         },
         function(){ // (a IS type1) & ~(v OR ~(a IS type2)) & v
-            var and = new TypePromotion.AndPromotions();
+            var and = new TypePromotion.And();
             var a = new TestVar();
             and.next().promote(a, "type1");
             var subOr = and.next();
@@ -609,7 +609,7 @@ exports.suite = {
             assert(a.type() == "type");
         },
         function(){ // (a IS type1) & (v & (a IS type2))
-            var and = new TypePromotion.AndPromotions();
+            var and = new TypePromotion.And();
             var a = new TestVar();
             and.next().promote(a, "type1");
             var sub = and.next().makeAnd();
@@ -624,7 +624,7 @@ exports.suite = {
         },
         function(){ // (~(~(a IS type1)) & v) OR v
             var a = new TestVar();
-            var or = new TypePromotion.OrPromotions();
+            var or = new TypePromotion.Or();
             var and = or.next().makeAnd();
             var p1 = and.next();
             p1.invert();
@@ -638,7 +638,7 @@ exports.suite = {
         },
         function(){ // (v OR (a IS type1)) & v)
             var a = new TestVar();
-            var and = new TypePromotion.AndPromotions();
+            var and = new TypePromotion.And();
             var or = and.next().makeOr();
             or.next();
             or.next().makeAnd().next().promote(a, "type1");