浏览代码

methods: support export

Vladislav Folts 11 年之前
父节点
当前提交
81599597fb
共有 7 个文件被更改,包括 48 次插入8 次删除
  1. 12 1
      src/eberon/eberon_context.js
  2. 1 1
      src/ob/Types.ob
  3. 3 0
      src/scope.js
  4. 1 1
      test/input/modules.ob
  5. 1 1
      test/input/nodejs/modules.ob
  6. 4 2
      test/make_snapshot.cmd
  7. 26 2
      test/test_unit_eberon.js

+ 12 - 1
src/eberon/eberon_context.js

@@ -67,6 +67,8 @@ var ProcOrMethodId = Context.Chained.extend({
         this.__type = type;
         this.__type = type;
     },
     },
     handleIdentdef: function(id){
     handleIdentdef: function(id){
+        if (this.__type && id.exported())
+            throw new Errors.Error("method implementation cannot be exported: " + id.id());
         this.handleMessage(new MethodOrProcMsg(id, this.__type));
         this.handleMessage(new MethodOrProcMsg(id, this.__type));
     }
     }
 });
 });
@@ -108,11 +110,11 @@ var RecordType = Type.Record.extend({
     init: function EberonContext$RecordType(name, cons, scope){
     init: function EberonContext$RecordType(name, cons, scope){
         Type.Record.prototype.init.call(this, name, cons, scope);
         Type.Record.prototype.init.call(this, name, cons, scope);
         this.__finalized = false;
         this.__finalized = false;
-        scope.addFinalizer(this.finalize.bind(this));
         this.__declaredMethods = {};
         this.__declaredMethods = {};
         this.__definedMethods = [];
         this.__definedMethods = [];
         this.__instantiated = false;
         this.__instantiated = false;
         this.__lazyDefinitions = [];
         this.__lazyDefinitions = [];
+        this.__nonExportedMethods = [];
     },
     },
     initializer: function(context){
     initializer: function(context){
         if (this.__finalized)
         if (this.__finalized)
@@ -145,6 +147,9 @@ var RecordType = Type.Record.extend({
                 : "cannot declare method, record already has field '" + id + "'");
                 : "cannot declare method, record already has field '" + id + "'");
 
 
         this.__declaredMethods[id] = type;
         this.__declaredMethods[id] = type;
+
+        if (!methodId.exported())
+            this.__nonExportedMethods.push(id);
     },
     },
     defineMethod: function(methodId, type){
     defineMethod: function(methodId, type){
         var base = this.baseType();
         var base = this.baseType();
@@ -191,6 +196,12 @@ var RecordType = Type.Record.extend({
         if (this.__instantiated)
         if (this.__instantiated)
             this.__ensureNonAbstract();
             this.__ensureNonAbstract();
         this.__ensureMethodDefinitions(this.__lazyDefinitions);
         this.__ensureMethodDefinitions(this.__lazyDefinitions);
+
+        for(var i = 0; i < this.__nonExportedMethods.length; ++i)
+            delete this.__declaredMethods[this.__nonExportedMethods[i]];
+        delete this.__nonExportedMethods;
+
+        Type.Record.prototype.finalize.call(this);
     },
     },
     __ensureMethodDefinitions: function(ids){
     __ensureMethodDefinitions: function(ids){
         var result = [];
         var result = [];

+ 1 - 1
src/ob/Types.ob

@@ -4,7 +4,7 @@ IMPORT JsString;
 TYPE
 TYPE
     Id = RECORD END;
     Id = RECORD END;
     Type = POINTER TO RECORD(Id)
     Type = POINTER TO RECORD(Id)
-        description: PROCEDURE(): JsString.Type
+        PROCEDURE description(): JsString.Type
     END;
     END;
     TypeId = RECORD(Id)
     TypeId = RECORD(Id)
         type: Type
         type: Type

+ 3 - 0
src/scope.js

@@ -59,6 +59,9 @@ var Scope = Class.extend({
     close: function(){
     close: function(){
         for(var i = 0; i < this.__finalizers.length; ++i)
         for(var i = 0; i < this.__finalizers.length; ++i)
             this.__finalizers[i]();
             this.__finalizers[i]();
+
+        // make second close() call safe and free memory
+        this.__finalizers = []; 
     }
     }
 });
 });
 
 

+ 1 - 1
test/input/modules.ob

@@ -2,7 +2,7 @@ MODULE m1;
 CONST
 CONST
     ci* = 123;
     ci* = 123;
 TYPE
 TYPE
-	Base* = RECORD i: INTEGER END;
+	Base* = RECORD i*: INTEGER END;
 	T* = RECORD(Base) END;
 	T* = RECORD(Base) END;
 	TP* = POINTER TO T;
 	TP* = POINTER TO T;
 	TPA* = POINTER TO RECORD END;
 	TPA* = POINTER TO RECORD END;

+ 1 - 1
test/input/nodejs/modules.ob

@@ -2,7 +2,7 @@ MODULE m1;
 CONST
 CONST
     ci* = 123;
     ci* = 123;
 TYPE
 TYPE
-	Base* = RECORD i: INTEGER END;
+	Base* = RECORD i*: INTEGER END;
 	T* = RECORD(Base) END;
 	T* = RECORD(Base) END;
 	TP* = POINTER TO T;
 	TP* = POINTER TO T;
 	TPA* = POINTER TO RECORD END;
 	TPA* = POINTER TO RECORD END;

+ 4 - 2
test/make_snapshot.cmd

@@ -1,5 +1,7 @@
 del /S /Q ..\snapshot
 del /S /Q ..\snapshot
 mkdir ..\snapshot
 mkdir ..\snapshot
-mkdir ..\snapshot\oberon.js
+mkdir ..\snapshot\eberon
+mkdir ..\snapshot\oberon
 copy ..\src\*.js ..\snapshot
 copy ..\src\*.js ..\snapshot
-copy ..\src\oberon.js\*.js ..\snapshot\oberon.js
+copy ..\src\eberon\*.js ..\snapshot\eberon
+copy ..\src\oberon\*.js ..\snapshot\oberon

+ 26 - 2
test/test_unit_eberon.js

@@ -11,6 +11,10 @@ function testWithContext(context, pass, fail){
     return TestUnitCommon.testWithContext(context, grammar.declarationSequence, pass, fail);
     return TestUnitCommon.testWithContext(context, grammar.declarationSequence, pass, fail);
 }
 }
 
 
+function testWithModule(src, pass, fail){
+    return TestUnitCommon.testWithModule(src, grammar, pass, fail);
+}
+
 exports.suite = {
 exports.suite = {
 "abstract method declaration": testWithContext(
 "abstract method declaration": testWithContext(
     context(grammar.declarationSequence, 
     context(grammar.declarationSequence, 
@@ -28,8 +32,7 @@ exports.suite = {
 "new method declaration": testWithContext(
 "new method declaration": testWithContext(
     context(grammar.declarationSequence, 
     context(grammar.declarationSequence, 
             "TYPE T = RECORD PROCEDURE p(); intField: INTEGER END; A = ARRAY 1 OF INTEGER;"),
             "TYPE T = RECORD PROCEDURE p(); intField: INTEGER END; A = ARRAY 1 OF INTEGER;"),
-    pass("PROCEDURE T.p(); END T.p;",
-         "PROCEDURE T.p*(); END T.p;"
+    pass("PROCEDURE T.p(); END T.p;"
          ),
          ),
         fail(["PROCEDURE TUnk.p(), NEW; END TUnk.p;", "undeclared identifier: 'TUnk'"],
         fail(["PROCEDURE TUnk.p(), NEW; END TUnk.p;", "undeclared identifier: 'TUnk'"],
          ["PROCEDURE A.p(), NEW; END A.p;",
          ["PROCEDURE A.p(), NEW; END A.p;",
@@ -105,5 +108,26 @@ exports.suite = {
          ["PROCEDURE D.pAbstract(); BEGIN SUPER() END D.pAbstract; PROCEDURE D.pAbstract2(); BEGIN SUPER() END D.pAbstract2;",
          ["PROCEDURE D.pAbstract(); BEGIN SUPER() END D.pAbstract; PROCEDURE D.pAbstract2(); BEGIN SUPER() END D.pAbstract2;",
           "cannot use abstract method(s) in SUPER calls: pAbstract, pAbstract2"]
           "cannot use abstract method(s) in SUPER calls: pAbstract, pAbstract2"]
           )
           )
+    ),
+"export method": testWithContext(
+    context(grammar.declarationSequence, 
+            "TYPE T = RECORD PROCEDURE p() END;"
+            ),
+    pass(),
+    fail(["PROCEDURE T.p*(); END T.p;",
+          "method implementation cannot be exported: p"])
+    ),
+"import method": testWithModule(
+      "MODULE test;"
+    + "TYPE T* = RECORD PROCEDURE m*(); PROCEDURE mNotExported() END;"
+    + "PROCEDURE T.m(); END T.m; PROCEDURE T.mNotExported(); END T.mNotExported;"
+    + "END test.",
+    pass("MODULE m; IMPORT test; VAR r: test.T; BEGIN r.m(); END m.",
+         "MODULE m; IMPORT test; TYPE T = RECORD(test.T) END; PROCEDURE T.m(); END T.m; END m."
+        ),
+    fail(["MODULE m; IMPORT test; VAR r: test.T; BEGIN r.mNotExported(); END m.",
+          "type 'T' has no 'mNotExported' field"],
+         ["MODULE m; IMPORT test; TYPE T = RECORD(test.T) END; PROCEDURE T.mNotExported(); END T.mNotExported; END m.",
+          "'T' has no declaration for method 'mNotExported'"])
     )
     )
 };
 };