Explorar o código

move eberon-specific code to separate file

Vladislav Folts %!s(int64=10) %!d(string=hai) anos
pai
achega
37fc981097

BIN=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 = ['EberonSymbols.ob', 'EberonCast.ob', 'EberonOperator.ob', 'EberonScope.ob',
+    sources = ['EberonSymbols.ob', 'EberonCast.ob', 'EberonCodeGenerator.ob', 'EberonOperator.ob', 'EberonScope.ob',
                'OberonSymbols.ob', 'Lexer.ob', 'Module.ob']
     
     result = os.path.join(root, 'bin.recompile')

+ 99 - 0
src/eberon/EberonCodeGenerator.ob

@@ -0,0 +1,99 @@
+MODULE EberonCodeGenerator;
+IMPORT CodeGenerator, String;
+TYPE
+    IGenerator = RECORD(CodeGenerator.IGenerator)
+        PROCEDURE makeInsertion(): INTEGER;
+        PROCEDURE insert(insertion: INTEGER; code: STRING);
+    END;
+
+    NullGenerator = RECORD(IGenerator)
+    END;
+
+    Insertion = RECORD
+        pos: INTEGER;
+        indent: INTEGER;
+        code: STRING;
+    END;
+
+    Generator = RECORD(IGenerator)
+        indent: CodeGenerator.Indent;
+        insertions: ARRAY * OF Insertion;
+    END;
+    PGenerator = POINTER TO Generator;
+
+VAR
+    nullGenerator*: NullGenerator;
+
+PROCEDURE NullGenerator.write(s: STRING); END;
+
+PROCEDURE NullGenerator.openScope(); END;
+
+PROCEDURE NullGenerator.closeScope(ending: STRING); END;
+
+PROCEDURE NullGenerator.result(): STRING;
+    RETURN "";
+END;
+
+PROCEDURE NullGenerator.makeInsertion(): INTEGER;
+    RETURN 0;
+END;
+
+PROCEDURE NullGenerator.insert(insertion: INTEGER; code: STRING);
+END;
+
+PROCEDURE Generator.makeInsertion(): INTEGER;
+VAR
+    insertion: Insertion;
+BEGIN
+    insertion.pos := LEN(SELF.indent.result);
+    insertion.indent := SELF.indent.indent;
+    result <- LEN(SELF.insertions);
+    SELF.insertions.add(insertion);
+    RETURN result;
+END;
+
+PROCEDURE Generator.insert(insertion: INTEGER; code: STRING);
+BEGIN
+    SELF.insertions[insertion].code := code;
+END;
+
+PROCEDURE Generator.write(s: STRING);
+BEGIN
+    CodeGenerator.addIndentedText(s, SELF.indent);
+END;
+
+PROCEDURE Generator.openScope();
+BEGIN
+    CodeGenerator.openScope(SELF.indent);
+END;
+
+PROCEDURE Generator.closeScope(ending: STRING);
+BEGIN
+    CodeGenerator.closeScope(ending, SELF.indent);
+END;
+
+PROCEDURE Generator.result(): STRING;
+VAR
+    result: STRING;
+BEGIN
+    pos <- 0;
+    FOR i <- 0 TO LEN(SELF.insertions) - 1 DO
+        nextPos <- SELF.insertions[i].pos;
+        result := result 
+                + String.substr(SELF.indent.result, pos, nextPos - pos)
+                + CodeGenerator.indentText(SELF.insertions[i].code, SELF.insertions[i].indent);
+        pos := nextPos;
+    END;
+    result := result + String.substr(SELF.indent.result, pos, LEN(SELF.indent.result) - pos);
+    RETURN result
+END;
+
+PROCEDURE makeGenerator*(): PGenerator;
+VAR
+    result: PGenerator;
+BEGIN
+    NEW(result);
+    RETURN result;
+END;
+
+END EberonCodeGenerator.

+ 5 - 0
src/eberon/eberon_grammar.js

@@ -3,6 +3,7 @@
 var Cast = require("js/EberonCast.js");
 var Context = require("context.js");
 var EbArray = require("js/EberonArray.js");
+var EbCodeGenerator = require("js/EberonCodeGenerator.js");
 var EbContext = require("eberon/eberon_context.js");
 var Grammar = require("grammar.js");
 var Parser = require("parser.js");
@@ -135,5 +136,9 @@ exports.language = {
         implicitCast: Cast.implicit,
         makeStaticArray: EbArray.makeStaticArray,
         makeOpenArray: EbArray.makeOpenArray
+    },
+    codeGenerator: {
+        make: EbCodeGenerator.makeGenerator,
+        nil: EbCodeGenerator.nullGenerator()
     }
 };

+ 1 - 2
src/nodejs.js

@@ -2,7 +2,6 @@
 
 var Class = require("rtl.js").Class;
 var Code = require("js/Code.js");
-var CodeGenerator = require("js/CodeGenerator.js");
 var Context = require("context.js");
 var oc = require("oc.js");
 var RTL = require("rtl_code.js").RTL;
@@ -81,7 +80,7 @@ function compile(sources, language, handleErrors, includeDirs, outDir, importDir
             },
             language.grammar,
             function(moduleResolver){return new Context.Context(
-                { codeGenerator: CodeGenerator.makeGenerator(),
+                { codeGenerator: language.codeGenerator.make(),
                   moduleGenerator: moduleCode,
                   rtl: rtl,
                   types: language.types,

+ 41 - 69
src/ob/CodeGenerator.ob

@@ -4,14 +4,11 @@ IMPORT
 CONST
     kTab* = 09X;
 TYPE
-    IGenerator = RECORD
-        PROCEDURE write(s: STRING);
-        PROCEDURE openScope();
-        PROCEDURE closeScope(ending: STRING);
-        PROCEDURE result(): STRING;
-
-        PROCEDURE makeInsertion(): INTEGER;
-        PROCEDURE insert(insertion: INTEGER; code: STRING);
+    IGenerator* = RECORD
+        PROCEDURE write*(s: STRING);
+        PROCEDURE openScope*();
+        PROCEDURE closeScope*(ending: STRING);
+        PROCEDURE result*(): STRING;
     END;
 
     PIGenerator = POINTER TO IGenerator;
@@ -23,48 +20,36 @@ TYPE
         mResult: STRING
     END;
 
-    Insertion = RECORD
-        pos: INTEGER;
-        indent: INTEGER;
-        code: STRING;
+    Indent* = RECORD
+        indent*: INTEGER;
+        result*: STRING;
     END;
 
-    Generator = RECORD(SimpleGenerator)
-        indent: INTEGER;
-        insertions: ARRAY * OF Insertion;
+    Generator = RECORD(IGenerator)
+        indent: Indent;
     END;
 
 VAR
     nullGenerator*: NullGenerator;
 
-PROCEDURE NullGenerator.write(s: STRING);
-END NullGenerator.write;
+PROCEDURE NullGenerator.write(s: STRING); END;
 
-PROCEDURE NullGenerator.openScope();
-END NullGenerator.openScope;
+PROCEDURE NullGenerator.openScope(); END;
 
-PROCEDURE NullGenerator.closeScope(ending: STRING);
-END NullGenerator.closeScope;
-
-PROCEDURE NullGenerator.makeInsertion(): INTEGER;
-    RETURN 0;
-END;
-
-PROCEDURE NullGenerator.insert(insertion: INTEGER; code: STRING);
-END;
+PROCEDURE NullGenerator.closeScope(ending: STRING); END;
 
 PROCEDURE NullGenerator.result(): STRING;
     RETURN "";
-END NullGenerator.result;
+END;
 
 PROCEDURE SimpleGenerator.write(s: STRING);
 BEGIN
     SELF.mResult := SELF.mResult + s;
-END SimpleGenerator.write;
+END;
 
 PROCEDURE SimpleGenerator.result(): STRING;
     RETURN SELF.mResult
-END SimpleGenerator.result;
+END;
 
 PROCEDURE makeIndent(count: INTEGER): STRING;
 VAR
@@ -76,7 +61,7 @@ BEGIN
     RETURN result
 END;
 
-PROCEDURE indentText(s: STRING; indent: INTEGER): STRING;
+PROCEDURE indentText*(s: STRING; indent: INTEGER): STRING;
 VAR
     result: STRING;
 BEGIN
@@ -91,59 +76,46 @@ BEGIN
     RETURN result + String.substr(s, pos, LEN(s) - pos);
 END;
 
-PROCEDURE Generator.write(s: STRING);
+PROCEDURE addIndentedText*(s: STRING; VAR indent: Indent);
 BEGIN
-    SELF.mResult := SELF.mResult + indentText(s, SELF.indent);
+    indent.result := indent.result + indentText(s, indent.indent);
 END;
 
-PROCEDURE Generator.openScope();
+PROCEDURE openScope*(VAR indent: Indent);
 BEGIN
-    INC(SELF.indent);
-    SELF.mResult := SELF.mResult + "{" + Stream.kCR + makeIndent(SELF.indent);
-END Generator.openScope;
+    INC(indent.indent);
+    indent.result := indent.result + "{" + Stream.kCR + makeIndent(indent.indent);
+END;
 
-PROCEDURE Generator.closeScope(ending: STRING);
+PROCEDURE closeScope*(ending: STRING; VAR indent: Indent);
 BEGIN
-    DEC(SELF.indent);
-    SELF.mResult := String.substr(SELF.mResult, 0, LEN(SELF.mResult) - 1) + "}";
+    DEC(indent.indent);
+    indent.result := String.substr(indent.result, 0, LEN(indent.result) - 1) + "}";
     IF LEN(ending) # 0 THEN
-        SELF.write(ending);
+        addIndentedText(ending, indent);
     ELSE
-        SELF.mResult := SELF.mResult + Stream.kCR + makeIndent(SELF.indent);
+        indent.result := indent.result + Stream.kCR + makeIndent(indent.indent);
     END;
-END Generator.closeScope;
+END;
 
-PROCEDURE Generator.makeInsertion(): INTEGER;
-VAR
-    insertion: Insertion;
+PROCEDURE Generator.write(s: STRING);
 BEGIN
-    insertion.pos := LEN(SELF.mResult);
-    insertion.indent := SELF.indent;
-    result <- LEN(SELF.insertions);
-    SELF.insertions.add(insertion);
-    RETURN result;
+    addIndentedText(s, SELF.indent);
 END;
 
-PROCEDURE Generator.insert(insertion: INTEGER; code: STRING);
+PROCEDURE Generator.openScope();
 BEGIN
-    SELF.insertions[insertion].code := code;
+    openScope(SELF.indent);
 END;
 
-PROCEDURE Generator.result(): STRING;
-VAR
-    result: STRING;
+PROCEDURE Generator.closeScope(ending: STRING);
 BEGIN
-    pos <- 0;
-    FOR i <- 0 TO LEN(SELF.insertions) - 1 DO
-        nextPos <- SELF.insertions[i].pos;
-        result := result 
-                + String.substr(SELF.mResult, pos, nextPos - pos) 
-                + indentText(SELF.insertions[i].code, SELF.insertions[i].indent);
-        pos := nextPos;
-    END;
-    result := result + String.substr(SELF.mResult, pos, LEN(SELF.mResult) - pos);
-    RETURN result
-END Generator.result;
+    closeScope(ending, SELF.indent);
+END;
+
+PROCEDURE Generator.result(): STRING;
+    RETURN SELF.indent.result
+END;
 
 PROCEDURE makeSimpleGenerator*(): PIGenerator;
 VAR
@@ -159,6 +131,6 @@ VAR
 BEGIN
     NEW(result);
     RETURN result
-END makeGenerator;
+END;
 
 END CodeGenerator.

+ 5 - 0
src/oberon/oberon_grammar.js

@@ -1,6 +1,7 @@
 "use strict";
 
 var Cast = require("js/Cast.js");
+var CodeGenerator = require("js/CodeGenerator.js");
 var Context = require("context.js");
 var Grammar = require("grammar.js");
 var ObContext = require("oberon/oberon_context.js");
@@ -113,6 +114,10 @@ exports.language = {
         implicitCast: Cast.implicit,
         makeStaticArray: Types.makeStaticArray,
         makeOpenArray: Types.makeOpenArray
+    },
+    codeGenerator: {
+        make: CodeGenerator.makeGenerator,
+        nil: CodeGenerator.nullGenerator()
     }
 };
 

+ 1 - 2
src/oc.js

@@ -2,7 +2,6 @@
 
 var Class = require("rtl.js").Class;
 var Code = require("js/Code.js");
-var CodeGenerator = require("js/CodeGenerator.js");
 var Context = require("context.js");
 var Errors = require("js/Errors.js");
 var Lexer = require("js/Lexer.js");
@@ -129,7 +128,7 @@ function compile(text, language, handleErrors){
             language.grammar,
             function(moduleResolver){
                 return new Context.Context(
-                    { codeGenerator: CodeGenerator.makeGenerator(),
+                    { codeGenerator: language.codeGenerator.make(),
                       moduleGenerator: moduleCode,
                       rtl: rtl,
                       types: language.types,

+ 1 - 34
test/test_unit.js

@@ -1432,46 +1432,13 @@ return {
     };
 }
 
-function makeCodeSuite(){
-    return {
-        "insertion": pass(
-            function(){
-                var g = CodeGenerator.makeGenerator();
-                g.write("a");
-                var i = g.makeInsertion();
-                g.write("b");
-                g.insert(i, "c");
-                assert(g.result() == "acb");
-            },
-            function(){
-                var g = CodeGenerator.makeGenerator();
-                g.write("ab");
-                var i1 = g.makeInsertion();
-                var i2 = g.makeInsertion();
-                g.write("cd");
-                g.insert(i1, "123");
-                g.insert(i2, "345");
-                assert(g.result() == "ab123345cd");
-            },
-            function(){
-                var g = CodeGenerator.makeGenerator();
-                g.write("ab");
-                var i = g.makeInsertion();
-                g.write("cd");
-                assert(g.result() == "abcd");
-            }
-        )
-    };
-}
-
 var result = Test.run({
     "common": {
         "oberon": makeSuiteForGrammar(oberon),
         "eberon": makeSuiteForGrammar(eberon)
     },
     "eberon": TestUnitEberon.suite,
-    "oberon": TestUnitOberon.suite,
-    "code":   makeCodeSuite()
+    "oberon": TestUnitOberon.suite
 });
 if (typeof process != "undefined")
     process.exit(result ? 0 : -1);

+ 1 - 2
test/test_unit_common.js

@@ -2,7 +2,6 @@
 
 var Class = require("rtl.js").Class;
 var Code = require("js/Code.js");
-var CodeGenerator = require("js/CodeGenerator.js");
 var Context = require("context.js");
 var Errors = require("js/Errors.js");
 var oc = require("oc.js");
@@ -31,7 +30,7 @@ var TestContext = Context.Context.extend({
     init: function TestContext(language){
         Context.Context.prototype.init.call(
                 this,
-                { codeGenerator: CodeGenerator.nullGenerator(),
+                { codeGenerator: language.codeGenerator.nil,
                   moduleGenerator: function(){return new TestModuleGenerator();},
                   rtl: new RTL(),
                   types: language.types,

+ 35 - 1
test/test_unit_eberon.js

@@ -1,6 +1,7 @@
 "use strict";
 
 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");
@@ -75,7 +76,40 @@ var TestVar = Class.extend({
     setType: function(type){this.__type = type;}
 });
 
+function makeCodeSuite(){
+    return {
+        "insertion": pass(
+            function(){
+                var g = EberonCodeGenerator.makeGenerator();
+                g.write("a");
+                var i = g.makeInsertion();
+                g.write("b");
+                g.insert(i, "c");
+                assert(g.result() == "acb");
+            },
+            function(){
+                var g = EberonCodeGenerator.makeGenerator();
+                g.write("ab");
+                var i1 = g.makeInsertion();
+                var i2 = g.makeInsertion();
+                g.write("cd");
+                g.insert(i1, "123");
+                g.insert(i2, "345");
+                assert(g.result() == "ab123345cd");
+            },
+            function(){
+                var g = EberonCodeGenerator.makeGenerator();
+                g.write("ab");
+                var i = g.makeInsertion();
+                g.write("cd");
+                assert(g.result() == "abcd");
+            }
+        )
+    };
+}
+
 exports.suite = {
+"code": makeCodeSuite(),
 "arithmetic operators": testWithContext(
     context(grammar.statement, "VAR b1: BOOLEAN;"),
     pass(),
@@ -1056,4 +1090,4 @@ exports.suite = {
          ["TYPE T = RECORD END; PROCEDURE T(); END T.T;", "mismatched method names: expected 'T' at the end (or nothing), got 'T.T'"]
          )
     )
-};
+};

+ 1 - 1
test/test_unit_oberon.js

@@ -112,4 +112,4 @@ exports.suite = {
     fail(["TYPE T = RECORD field: INTEGER; END;", "not parsed"],
          ["PROCEDURE p(): INTEGER; RETURN 0; END;", "END expected (PROCEDURE)"])
     )
-};
+};