Browse Source

Merge branch 'release'(export pointer types fixes)

Conflicts:
	src/context.js
Vladislav Folts 11 years ago
parent
commit
d6969ff6eb
9 changed files with 87 additions and 22 deletions
  1. 2 1
      src/code.js
  2. 2 2
      src/context.js
  3. 1 1
      src/procedure.js
  4. 0 6
      src/scope.js
  5. 16 3
      src/type.js
  6. 17 2
      test/expected/modules.js
  7. 0 1
      test/expected/nodejs/modules/m1.js
  8. 12 0
      test/input/modules.ob
  9. 37 6
      test/test_unit.js

+ 2 - 1
src/code.js

@@ -88,7 +88,8 @@ function genExport(symbol){
         return "function(){return " + symbol.id() + ";}";
         return "function(){return " + symbol.id() + ";}";
     if (symbol.isType()){
     if (symbol.isType()){
         var type = symbol.info().type();
         var type = symbol.info().type();
-        if (!(type instanceof Type.Record || type instanceof Type.Pointer))
+        if (!(type instanceof Type.Record 
+              || (type instanceof Type.Pointer && !type.baseType().name())))
             return undefined;
             return undefined;
     }
     }
     return symbol.id();
     return symbol.id();

+ 2 - 2
src/context.js

@@ -343,8 +343,8 @@ exports.Designator = ChainedContext.extend({
             throw new Errors.Error("POINTER TO type expected, got '"
             throw new Errors.Error("POINTER TO type expected, got '"
                                  + this.__currentType.description() + "'");
                                  + this.__currentType.description() + "'");
         this.__currentType = this.__currentType.baseType();
         this.__currentType = this.__currentType.baseType();
-        if (!this.__currentType)
-            throw new Errors.Error("non-exported RECORD type cannot be dereferenced");
+        if (this.__currentType instanceof Type.NonExportedRecord)
+            throw new Errors.Error("POINTER TO non-exported RECORD type cannot be dereferenced");
     },
     },
     handleTypeCast: function(type){
     handleTypeCast: function(type){
         if (this.__currentType instanceof Type.Record){
         if (this.__currentType instanceof Type.Record){

+ 1 - 1
src/procedure.js

@@ -307,7 +307,7 @@ exports.predefined = [
                     throw new Errors.Error("POINTER variable expected, got '"
                     throw new Errors.Error("POINTER variable expected, got '"
                                          + type.name() + "'");
                                          + type.name() + "'");
                 this.__baseType = type.baseType();
                 this.__baseType = type.baseType();
-                if (this.__baseType === undefined)
+                if (this.__baseType instanceof Type.NonExportedRecord)
                     throw new Errors.Error("non-exported RECORD type cannot be used in NEW");
                     throw new Errors.Error("non-exported RECORD type cannot be used in NEW");
                 return new CheckArgumentResult(type, false);
                 return new CheckArgumentResult(type, false);
             },
             },

+ 0 - 6
src/scope.js

@@ -77,12 +77,6 @@ var ProcedureScope = Scope.extend({
     }
     }
 });
 });
 
 
-var TypeRef = Class.extend({
-    init: function(type){this.__type = type;},
-    get: function(){return this.__type;},
-    reset: function(){this.__type = undefined;}
-});
-
 var CompiledModule = Type.Module.extend({
 var CompiledModule = Type.Module.extend({
     init: function Scope$CompiledModule(id){
     init: function Scope$CompiledModule(id){
         Type.Module.prototype.init.call(this, id);
         Type.Module.prototype.init.call(this, id);

+ 16 - 3
src/type.js

@@ -20,7 +20,11 @@ var TypeId = Id.extend({
     },
     },
     type: function(){return this._type;},
     type: function(){return this._type;},
     description: function(){return 'type ' + this._type.description();},
     description: function(){return 'type ' + this._type.description();},
-    strip: function(){this._type = undefined;}
+    strip: function(){
+        this._type = this._type instanceof Record 
+                   ? new NonExportedRecord(this._type.cons(), this._type.scope(), this._type.baseType())
+                   : undefined;
+    }
 });
 });
 
 
 var ForwardTypeId = TypeId.extend({
 var ForwardTypeId = TypeId.extend({
@@ -107,8 +111,8 @@ exports.Pointer = BasicType.extend({
     baseType: function(){return this.__base.type();}
     baseType: function(){return this.__base.type();}
 });
 });
 
 
-exports.Record = BasicType.extend({
-    init: function RecordType(name, cons, scope){
+var Record = BasicType.extend({
+    init: function Type$Record(name, cons, scope){
         BasicType.prototype.init.call(this, name);
         BasicType.prototype.init.call(this, name);
         this.__cons = cons;        
         this.__cons = cons;        
         this.__scope = scope;
         this.__scope = scope;
@@ -142,6 +146,13 @@ exports.Record = BasicType.extend({
     }
     }
 });
 });
 
 
+var NonExportedRecord = Record.extend({
+    init: function Scope$NonExportedRecord(cons, scope, base){
+        Record.prototype.init.call(this, undefined, cons, scope);
+        this.setBaseType(base);
+    }
+});
+
 var NilType = Type.extend({
 var NilType = Type.extend({
     init: function NilType(){Type.prototype.init.call(this);},
     init: function NilType(){Type.prototype.init.call(this);},
     idType: function(){return "NIL";},
     idType: function(){return "NIL";},
@@ -215,6 +226,8 @@ exports.Variable = Variable;
 exports.VariableRef = VariableRef;
 exports.VariableRef = VariableRef;
 exports.ExportedVariable = ExportedVariable;
 exports.ExportedVariable = ExportedVariable;
 exports.Module = Module;
 exports.Module = Module;
+exports.NonExportedRecord = NonExportedRecord;
+exports.Record = Record;
 exports.Type = Type;
 exports.Type = Type;
 exports.TypeId = TypeId;
 exports.TypeId = TypeId;
 exports.ForwardTypeId = ForwardTypeId;
 exports.ForwardTypeId = ForwardTypeId;

+ 17 - 2
test/expected/modules.js

@@ -57,6 +57,11 @@ var TPA = RTL$.extend({
 	init: function TPA(){
 	init: function TPA(){
 	}
 	}
 });
 });
+var TPB = Base.extend({
+	init: function TPB(){
+		Base.prototype.init.call(this);
+	}
+});
 var i = 0;
 var i = 0;
 var anonymous$1 = RTL$.extend({
 var anonymous$1 = RTL$.extend({
 	init: function anonymous$1(){
 	init: function anonymous$1(){
@@ -74,18 +79,25 @@ function makeTPA(){
 	result = new TPA();
 	result = new TPA();
 	return result;
 	return result;
 }
 }
+
+function makeTPB(){
+	var result = null;
+	result = new TPB();
+	return result;
+}
 pr = new anonymous$1();
 pr = new anonymous$1();
 return {
 return {
 	ci: ci,
 	ci: ci,
 	Base: Base,
 	Base: Base,
 	T: T,
 	T: T,
-	TP: TP,
 	TPA: TPA,
 	TPA: TPA,
+	TPB: TPB,
 	i: function(){return i;},
 	i: function(){return i;},
 	pr: function(){return pr;},
 	pr: function(){return pr;},
 	pr2: function(){return pr2;},
 	pr2: function(){return pr2;},
 	p: p,
 	p: p,
-	makeTPA: makeTPA
+	makeTPA: makeTPA,
+	makeTPB: makeTPB
 }
 }
 }();
 }();
 var m2 = function (m1){
 var m2 = function (m1){
@@ -113,8 +125,11 @@ var r = new m2.T();
 var a = RTL$.makeArray(3, function(){return new m2.Base();});
 var a = RTL$.makeArray(3, function(){return new m2.Base();});
 var ptr = null;
 var ptr = null;
 var pb = null;
 var pb = null;
+var pTPB = null;
 ptr = new m2.T();
 ptr = new m2.T();
 pb = ptr;
 pb = ptr;
 RTL$.typeGuard(pb, m2.T).i = 123;
 RTL$.typeGuard(pb, m2.T).i = 123;
+pb = m2.makeTPB();
+pTPB = RTL$.typeGuard(pb, m2.TPB);
 m2.p();
 m2.p();
 }(m2, m1);
 }(m2, m1);

+ 0 - 1
test/expected/nodejs/modules/m1.js

@@ -35,7 +35,6 @@ pr = new anonymous$1();
 exports.ci = ci;
 exports.ci = ci;
 exports.Base = Base;
 exports.Base = Base;
 exports.T = T;
 exports.T = T;
-exports.TP = TP;
 exports.TPA = TPA;
 exports.TPA = TPA;
 exports.i = function(){return i;};
 exports.i = function(){return i;};
 exports.pr = function(){return pr;};
 exports.pr = function(){return pr;};

+ 12 - 0
test/input/modules.ob

@@ -6,6 +6,7 @@ TYPE
 	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;
+    TPB* = POINTER TO RECORD(Base) END;
 VAR
 VAR
     i*: INTEGER;
     i*: INTEGER;
     pr*: POINTER TO RECORD i: INTEGER END;
     pr*: POINTER TO RECORD i: INTEGER END;
@@ -21,6 +22,13 @@ BEGIN
     RETURN result
     RETURN result
 END makeTPA;
 END makeTPA;
 
 
+PROCEDURE makeTPB*(): TPB;
+VAR result: TPB;
+BEGIN
+    NEW(result);
+    RETURN result
+END makeTPB;
+
 BEGIN
 BEGIN
     NEW(pr);
     NEW(pr);
 END m1.
 END m1.
@@ -60,10 +68,14 @@ VAR
     a: ARRAY 3 OF m2.Base;
     a: ARRAY 3 OF m2.Base;
     ptr: m2.TP;
     ptr: m2.TP;
     pb: POINTER TO m2.Base;
     pb: POINTER TO m2.Base;
+    pTPB: m2.TPB;
 BEGIN
 BEGIN
     NEW(ptr);
     NEW(ptr);
     pb := ptr;
     pb := ptr;
     pb(m2.TP).i := 123;
     pb(m2.TP).i := 123;
 
 
+    pb := m2.makeTPB();
+    pTPB := pb(m2.TPB);
+
     m2.p();
     m2.p();
 END m3.
 END m3.

+ 37 - 6
test/test_unit.js

@@ -388,11 +388,20 @@ var testSuite = {
     ),
     ),
 "POINTER assignment": testWithContext(
 "POINTER assignment": testWithContext(
     context(Grammar.statement,
     context(Grammar.statement,
-            "TYPE Base = RECORD END; Derived = RECORD (Base) END;"
-            + "VAR p1, p2: POINTER TO RECORD END; pBase: POINTER TO Base; pDerived: POINTER TO Derived;"),
+            "TYPE Base = RECORD END;"
+                + "Derived = RECORD (Base) END;"
+                + "PDerivedAnonymous = POINTER TO RECORD(Base) END;"
+            + "VAR p1, p2: POINTER TO RECORD END;"
+                + "pBase: POINTER TO Base; pDerived: POINTER TO Derived;"
+                + "pDerivedAnonymous: PDerivedAnonymous;"
+                + "pDerivedAnonymous2: POINTER TO RECORD(Base) END;"
+                ),
     pass("p1 := NIL",
     pass("p1 := NIL",
          "p1 := p2",
          "p1 := p2",
-         "pBase := pDerived"),
+         "pBase := pDerived",
+         "pBase := pDerivedAnonymous",
+         "pBase := pDerivedAnonymous2"
+         ),
     fail(["p1 := pBase",
     fail(["p1 := pBase",
           "type mismatch: 'p1' is 'POINTER TO anonymous RECORD' and cannot be assigned to 'POINTER TO Base' expression"],
           "type mismatch: 'p1' is 'POINTER TO anonymous RECORD' and cannot be assigned to 'POINTER TO Base' expression"],
           ["pDerived := pBase",
           ["pDerived := pBase",
@@ -1336,8 +1345,17 @@ var testSuite = {
         )
         )
     ),
     ),
 "import pointer type": testWithModule(
 "import pointer type": testWithModule(
-    "MODULE test; TYPE TP* = POINTER TO RECORD END; END test.",
-    pass("MODULE m; IMPORT test; VAR p: test.TP; END m.")
+    "MODULE test;"
+    + "TYPE TPAnonymous1* = POINTER TO RECORD END; TPAnonymous2* = POINTER TO RECORD END;"
+        + "Base* = RECORD END; TPDerived* = POINTER TO RECORD(Base) END;"
+    + "END test.",
+    pass("MODULE m; IMPORT test; VAR p1: test.TPAnonymous1; p2: test.TPAnonymous2; END m.",
+         "MODULE m; IMPORT test;"
+            + "VAR pb: POINTER TO test.Base; pd: test.TPDerived;"
+            + "BEGIN pb := pd; END m."),
+    fail(["MODULE m; IMPORT test; VAR p1: test.TPAnonymous1; p2: test.TPAnonymous2; BEGIN p1 := p2; END m.",
+          "type mismatch: 'p1' is 'TPAnonymous1' and cannot be assigned to 'TPAnonymous2' expression"]
+         )
     ),
     ),
 "import array type": testWithModule(
 "import array type": testWithModule(
     "MODULE test; TYPE TA* = ARRAY 3 OF INTEGER; END test.",
     "MODULE test; TYPE TA* = ARRAY 3 OF INTEGER; END test.",
@@ -1357,11 +1375,24 @@ var testSuite = {
          ["MODULE m; IMPORT test; VAR p: test.TP; BEGIN NEW(p) END m.",
          ["MODULE m; IMPORT test; VAR p: test.TP; BEGIN NEW(p) END m.",
           "non-exported RECORD type cannot be used in NEW"])
           "non-exported RECORD type cannot be used in NEW"])
     ),
     ),
+"imported pointer type cannot be dereferenced if base type is not exported (even if base of base type is exported)": testWithModule(
+    "MODULE test;"
+    + "TYPE B* = RECORD i: INTEGER END; T = RECORD(B) END; TP* = POINTER TO T;"
+    + "TPAnonymous* = POINTER TO RECORD(B) END;"
+    + "PROCEDURE makeTP*(): TP; VAR result: TP; BEGIN NEW(result); RETURN result END makeTP;"
+    + "PROCEDURE makeTPA*(): TPAnonymous; VAR result: TPAnonymous; BEGIN NEW(result); RETURN result END makeTPA;"
+    + "END test.",
+    pass(),
+    fail(["MODULE m; IMPORT test; VAR p: test.TPAnonymous; BEGIN p := test.makeTPA(); p.i := 123; END m.",
+          "POINTER TO non-exported RECORD type cannot be dereferenced"],
+         ["MODULE m; IMPORT test; VAR p: test.TP; BEGIN p := test.makeTP(); p.i := 123; END m.",
+          "POINTER TO non-exported RECORD type cannot be dereferenced"])
+    ),
 "imported pointer variable: anonymous record field cannot be used": testWithModule(
 "imported pointer variable: anonymous record field cannot be used": testWithModule(
     "MODULE test; VAR p*: POINTER TO RECORD i: INTEGER END; END test.",
     "MODULE test; VAR p*: POINTER TO RECORD i: INTEGER END; END test.",
     pass(),
     pass(),
     fail(["MODULE m; IMPORT test; BEGIN ASSERT(test.p.i = 0) END m.",
     fail(["MODULE m; IMPORT test; BEGIN ASSERT(test.p.i = 0) END m.",
-          "non-exported RECORD type cannot be dereferenced"])
+          "POINTER TO non-exported RECORD type cannot be dereferenced"])
     ),
     ),
 "syntax errors": testWithGrammar(
 "syntax errors": testWithGrammar(
     Grammar.module,
     Grammar.module,