Przeglądaj źródła

tune up error diagnostic in case of referencing unknown fields

Vladislav Folts 11 lat temu
rodzic
commit
b2cff498f9
2 zmienionych plików z 16 dodań i 7 usunięć
  1. 10 4
      src/context.js
  2. 6 3
      test/test_unit.js

+ 10 - 4
src/context.js

@@ -293,9 +293,11 @@ exports.Designator = ChainedContext.extend({
     },
     setIdent: function(id){
         var t = this.__currentType;
+        var pointerType;
         var isReadOnly = this.__info instanceof Type.Variable 
                       && this.__info.isReadOnly();
         if (t instanceof Type.Pointer){
+            pointerType = t;
             this.__handleDeref();
             isReadOnly = false;
         }
@@ -304,7 +306,7 @@ exports.Designator = ChainedContext.extend({
                 || t instanceof Module.AnyType))
             throw new Errors.Error("cannot designate '" + t.description() + "'");
 
-        this.__denote(id);
+        this.__denote(id, pointerType);
         this.__info = new Type.Variable(this.__currentType, isReadOnly);
         this.__scope = undefined;
     },
@@ -378,11 +380,15 @@ exports.Designator = ChainedContext.extend({
 
         this.__currentType = type;
     },
-    __denote: function(id){
+    __denote: function(id, pointerType){
         var t = this.__currentType;
         var fieldType = t.findSymbol(id);
-        if (!fieldType)
-            throw new Errors.Error("Type '" + t.name() + "' has no '" + id + "' field");
+        if (!fieldType){
+            var typeDesc = !t.name() && pointerType && pointerType.name()
+                ? pointerType.name()
+                : t.description();
+            throw new Errors.Error("type '" + typeDesc + "' has no '" + id + "' field");
+        }
         this.__derefCode = this.__code.result();
         this.__propCode = "\"" + id + "\"";
         this.__code.write("." + id);

+ 6 - 3
test/test_unit.js

@@ -380,11 +380,14 @@ var testSuite = {
     ),
 "POINTER dereference": testWithContext(
     context(Grammar.statement,
-            "VAR p: POINTER TO RECORD field: INTEGER END; i: INTEGER; r: RECORD END;"),
+            "TYPE PT = POINTER TO RECORD END;"
+            + "VAR pt: PT; p: POINTER TO RECORD field: INTEGER END; i: INTEGER; r: RECORD END;"),
     pass("p^.field := 1",
          "p.field := 0"),
     fail(["i^", "POINTER TO type expected, got 'INTEGER'"],
-         ["r^", "POINTER TO type expected, got 'anonymous RECORD'"])
+         ["r^", "POINTER TO type expected, got 'anonymous RECORD'"],
+         ["p.unknown := 0", "type 'anonymous RECORD' has no 'unknown' field"],
+         ["pt.unknown := 0", "type 'PT' has no 'unknown' field"])
     ),
 "POINTER assignment": testWithContext(
     context(Grammar.statement,
@@ -958,7 +961,7 @@ var testSuite = {
          ["TYPE T = RECORD field: INTEGER END; VAR v: T; BEGIN v := 1 END",
           "type mismatch: 'v' is 'T' and cannot be assigned to 'INTEGER' expression"],
          ["TYPE T = RECORD field: INTEGER END; VAR v: T; BEGIN v.unknown := 1 END",
-          "Type 'T' has no 'unknown' field"],
+          "type 'T' has no 'unknown' field"],
          ["TYPE T1 = RECORD field1: INTEGER END; T2 = RECORD (T1) field1: INTEGER END; END",
           "base record already has field: 'field1'"])
     ),