浏览代码

New syntax to use SELF as POINTER: SELF(POINTER)

Vladislav Folts 11 年之前
父节点
当前提交
4e56641f44
共有 5 个文件被更改,包括 57 次插入1 次删除
  1. 6 0
      src/eberon/eberon_context.js
  2. 2 1
      src/eberon/eberon_grammar.js
  3. 16 0
      test/expected/eberon/method.js
  4. 21 0
      test/input/eberon/method.ob
  5. 12 0
      test/test_unit_eberon.js

+ 6 - 0
src/eberon/eberon_context.js

@@ -231,6 +231,12 @@ var Designator = Context.Designator.extend({
         if (s == "SELF"){
             var type = this.handleMessage(getMethodSelf);
             this._advance(type, type, "this");
+        } 
+        else if (s == "POINTER"){
+            var typeId = Type.makeTypeId(this.__currentType);
+            var pointerType = Type.makePointer("", typeId);
+            var info = Type.makeVariable(pointerType, true);
+            this._advance(pointerType, info, "this");
         }
         else if (s == "SUPER"){
             var ms = this.handleMessage(getMethodSuper);

+ 2 - 1
src/eberon/eberon_grammar.js

@@ -37,8 +37,9 @@ function makeIdentdef(ident){
 }
 
 function makeDesignator(ident, qualident, selector, actualParameters){
+    var self = and("SELF", optional(and("(", "POINTER", ")")));
     var designator = context(
-        and(or("SELF", "SUPER", qualident), repeat(or(selector, actualParameters))), EbContext.Designator);
+        and(or(self, "SUPER", qualident), repeat(or(selector, actualParameters))), EbContext.Designator);
     return { 
         factor: context(designator, EbContext.ExpressionProcedureCall),
         assignmentOrProcedureCall: function(assignment, expression){

+ 16 - 0
test/expected/eberon/method.js

@@ -32,6 +32,22 @@ T.prototype.p = function(){
 T.prototype.p2 = function(i/*INTEGER*/){
 	return i;
 }
+
+function acceptPointer(p/*PT*/){
+}
+
+function acceptReferenace(p/*VAR T*/){
+}
+
+function acceptConstReferenace(p/*T*/){
+}
+T.prototype.useSelfAsPointer = function(){
+	var pVar = null;
+	pVar = this;
+	acceptPointer(this);
+	acceptReferenace(this);
+	acceptConstReferenace(this);
+}
 D.prototype.p = function(){
 	T.prototype.p.call(this);
 }

+ 21 - 0
test/input/eberon/method.ob

@@ -3,8 +3,10 @@ TYPE
     T = RECORD
         PROCEDURE p();
         PROCEDURE p2(i: INTEGER): INTEGER;
+        PROCEDURE useSelfAsPointer();
 		i: INTEGER
 	END;
+    PT = POINTER TO T;
     D = RECORD(T) END;
 VAR
     d: D;
@@ -18,6 +20,25 @@ PROCEDURE T.p2(i: INTEGER): INTEGER;
     RETURN i
 END T.p2;
 
+PROCEDURE acceptPointer(p: PT);
+END acceptPointer;
+
+PROCEDURE acceptReferenace(VAR p: T);
+END acceptReferenace;
+
+PROCEDURE acceptConstReferenace(p: T);
+END acceptConstReferenace;
+
+PROCEDURE T.useSelfAsPointer();
+VAR
+    pVar: PT;
+BEGIN
+    pVar := SELF(POINTER);
+    acceptPointer(SELF(POINTER));
+    acceptReferenace(SELF(POINTER)^);
+    acceptConstReferenace(SELF(POINTER)^);
+END T.useSelfAsPointer;
+
 PROCEDURE D.p();
 BEGIN
     SUPER()

+ 12 - 0
test/test_unit_eberon.js

@@ -155,6 +155,18 @@ exports.suite = {
     fail(["PROCEDURE p(); BEGIN SELF.i := 0; END p;",
           "SELF can be used only in methods"])
     ),
+"SELF as pointer": testWithContext(
+    context(grammar.declarationSequence, 
+            "TYPE T = RECORD PROCEDURE method() END; PT = POINTER TO T;"
+            + "VAR pVar: PT;"
+            + "PROCEDURE refProc(VAR p: PT); END refProc;"
+            ),
+    pass("PROCEDURE T.method(); BEGIN pVar := SELF(POINTER) END T.method;"),
+    fail(["PROCEDURE T.method(); BEGIN refProc(SELF(POINTER)) END T.method;", 
+          "read-only variable cannot be used as VAR parameter"],
+         ["PROCEDURE T.method(); BEGIN SELF(POINTER) := pVar; END T.method;", 
+          "cannot assign to read-only variable"])
+    ),
 "method call": testWithContext(
     context(grammar.expression,
               "TYPE T = RECORD PROCEDURE p(); PROCEDURE f(): INTEGER END;"