瀏覽代碼

Require declarion for constructors.

Vladislav Folts 10 年之前
父節點
當前提交
04b356273b

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

+ 0 - 99
src/eberon/EberonCodeGenerator.ob

@@ -1,99 +0,0 @@
-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.

+ 27 - 5
src/eberon/EberonRecord.ob

@@ -3,8 +3,9 @@ IMPORT
     Cast, Context, EberonContext, EberonTypes, Errors, JS, JsMap, ScopeBase, Object, String, Types;
 TYPE
     Record* = RECORD(Types.Record)
-        PROCEDURE defineConstructor(type: Types.PDefinedProcedure): STRING;
+        PROCEDURE declareConstructor(type: Types.PDefinedProcedure);
         PROCEDURE addMethod(methodId: Context.PIdentdefInfo; type: Types.PProcedure);
+        PROCEDURE defineConstructor(type: Types.PDefinedProcedure);
         PROCEDURE defineMethod(methodId: Context.PIdentdefInfo; type: EberonTypes.PMethodType);
         PROCEDURE requireNewOnly();
         PROCEDURE setBaseConstructorCallCode(code: STRING);
@@ -12,6 +13,7 @@ TYPE
         PROCEDURE setRecordInitializationCode(baseConstructorCallCode, fieldsInitializationCode, inheritanceCode: STRING);
 
         customConstructor-: Types.PDefinedProcedure;
+        customConstructorDefined: BOOLEAN;
         customInitedfields-: ARRAY * OF STRING;
         finalized: BOOLEAN;
         declaredMethods: JsMap.Type;
@@ -22,7 +24,7 @@ TYPE
         declaredAsVariable: BOOLEAN;
         lazyDefinitions: JsMap.Type;
         nonExportedMethods: ARRAY * OF STRING;
-        inheritanceCode, baseConstructorCallCode-, fieldsInitializationCode-: STRING;
+        inheritanceCode-, baseConstructorCallCode-, fieldsInitializationCode-: STRING;
         fieldsInit: JsMap.Strings;
     END;
     PRecord* = POINTER TO Record;
@@ -326,17 +328,32 @@ BEGIN
     SELF.inheritanceCode := inheritanceCode;
 END;
 
-PROCEDURE Record.defineConstructor(type: Types.PDefinedProcedure): STRING;
+PROCEDURE Record.declareConstructor(type: Types.PDefinedProcedure);
 BEGIN
     IF SELF.customConstructor # NIL THEN
-        Errors.raise("constructor '" + SELF.name + "' already defined");
+        Errors.raise("constructor '" + SELF.name + "' already declared");
     END;
     IF type.result() # NIL THEN
         Errors.raise("constructor '" + SELF.name + "' cannot have result type specified");
     END;
 
     SELF.customConstructor := type;
-    RETURN SELF.inheritanceCode;
+END;
+
+PROCEDURE Record.defineConstructor(type: Types.PDefinedProcedure);
+BEGIN
+    IF SELF.customConstructor = NIL THEN
+        Errors.raise("constructor was not declared for '" + SELF.name +"'");
+    END;
+    IF SELF.customConstructorDefined THEN
+        Errors.raise("constructor already defined for '" + SELF.name +"'");
+    END;
+    IF ~Cast.areProceduresMatch(SELF.customConstructor, type) THEN
+        Errors.raise("constructor '" + SELF.name + "' signature mismatch: declared as '"
+                   + SELF.customConstructor.description() + "' but defined as '" 
+                   + type.description() + "'");
+    END;
+    SELF.customConstructorDefined := TRUE;
 END;
 
 PROCEDURE collectAbstractMethods(r: Record);
@@ -362,6 +379,11 @@ END;
 PROCEDURE Record.finalize();
 BEGIN
     SELF.finalized := TRUE;
+
+    IF (SELF.customConstructor # NIL) & ~SELF.customConstructorDefined THEN
+        Errors.raise("constructor was declared for '" + SELF.name + "' but was not defined");
+    END;
+
     collectAbstractMethods(SELF);
     IF SELF.instantiated THEN
         ensureNonAbstract(SELF(POINTER));

+ 27 - 42
src/eberon/eberon_context.js

@@ -32,10 +32,9 @@ function superMethodCallGenerator(context, type){
     return Procedure.makeProcCallGeneratorWithCustomArgs(context, type, args);
 }
 
-function MethodOrProcMsg(id, type, isConstructor){
+function MethodOrProcMsg(id, type){
     this.id = id;
     this.type = type;
-    this.isConstructor = isConstructor;
 }
 
 var ProcOrMethodId = Context.Chained.extend({
@@ -63,23 +62,7 @@ var ProcOrMethodId = Context.Chained.extend({
         if (this.__type && id.exported())
             throw new Errors.Error("method implementation cannot be exported: " + id.id());
         checkOrdinaryExport(id, "procedure");
-
-        var isConstructor = false;
-        if (!this.__type){
-            var s = this.currentScope().findSymbol(id.id());
-            if (s){
-                var info = s.symbol().info();
-                if (info instanceof Type.TypeId){
-                    var boundType = info.type();
-                    if (boundType instanceof Type.Record){
-                        this.__type = boundType;
-                        isConstructor = true;
-                    }
-                }
-            }
-        }
-
-        this.handleMessage(new MethodOrProcMsg(id, this.__type, isConstructor));
+        this.handleMessage(new MethodOrProcMsg(id, this.__type));
     }
 });
 
@@ -423,10 +406,18 @@ var RecordDecl = Context.RecordDecl.extend({
         Context.RecordDecl.prototype.init.call(this, context, EberonRecord.makeRecord);
     },
     handleMessage: function(msg){
-        if (msg instanceof MethodOrProcMsg)
-            return this.type().addMethod(
-                msg.id,
-                EberonTypes.makeMethodType(msg.id.id(), msg.type, Procedure.makeProcCallGenerator));
+        if (msg instanceof MethodOrProcMsg){
+            var methodType = msg.type;
+            var boundType = this.type();
+            var id = msg.id.id();
+            if (Type.typeName(boundType) == id)
+                boundType.declareConstructor(methodType);
+            else
+                boundType.addMethod(msg.id,
+                                    EberonTypes.makeMethodType(id, methodType, Procedure.makeProcCallGenerator));
+            return;
+        }
+
         if (msg == Context.endParametersMsg) // not used
             return undefined;
         if (msg instanceof Context.AddArgumentMsg) // not used
@@ -437,18 +428,14 @@ var RecordDecl = Context.RecordDecl.extend({
         return EberonRecord.makeRecordField(field, type, this.__type);
     },
     endParse: function(){
-        var gen = this.codeGenerator();
-        var pos = gen.makeInsertion();
         var type = this.type();
-        var inheritanceCode = this._generateInheritance();
-        type.setRecordInitializationCode(
-            this._generateBaseConstructorCallCode(),
-            this._generateFieldsInitializationCode(), 
-            inheritanceCode);
-        this.currentScope().addFinalizer(function(){
-            if (!this.__type.customConstructor)
-                gen.insert(pos, this._generateConstructor() + inheritanceCode);
-        }.bind(this));
+        if (!type.customConstructor)
+            return Context.RecordDecl.prototype.endParse.call(this);
+        else
+            type.setRecordInitializationCode(
+                this._generateBaseConstructorCallCode(),
+                this._generateFieldsInitializationCode(), 
+                this._generateInheritance());
     }
 });
 
@@ -564,7 +551,8 @@ var ProcOrMethodDecl = Context.ProcDecl.extend({
             if (type){
                 this.__methodId = id;
                 this.__boundType = type;
-                this.__isConstructor = msg.isConstructor;
+                var name = Type.typeName(type);
+                this.__isConstructor = name == id.id();
             }
 
             Context.ProcDecl.prototype.handleIdentdef.call(this, id);
@@ -619,11 +607,7 @@ var ProcOrMethodDecl = Context.ProcDecl.extend({
 
         if (this.__boundType){
             if (this.__endingId){
-                var expected 
-                    = (this.__isConstructor 
-                             ? ""
-                             : (Type.typeName(this.__boundType) + "."))
-                    + this.__id.id();
+                var expected = Type.typeName(this.__boundType) + "." + this.__id.id();
                 if (this.__endingId != expected)
                     throw new Errors.Error(
                           "mismatched method names: expected '" 
@@ -633,6 +617,8 @@ var ProcOrMethodDecl = Context.ProcDecl.extend({
             }
 
             if (this.__isConstructor){
+                this.__boundType.defineConstructor(this.__methodType.procType());
+
                 var base = Type.recordBase(this.__boundType);
                 if (!this.__baseConstructorWasCalled && base && base.customConstructor && base.customConstructor.args().length)
                     throw new Errors.Error("base record constructor has parameters but was not called (use '| SUPER' to pass parameters to base constructor)");
@@ -648,8 +634,7 @@ var ProcOrMethodDecl = Context.ProcDecl.extend({
                 if (fieldsWereNotInited.length)
                     throw new Errors.Error("constructor '" + Type.typeName(this.__boundType) + "' must initialize fields: " + fieldsWereNotInited);
 
-                this.codeGenerator().write(
-                    this.__boundType.defineConstructor(this.__methodType.procType()));
+                this.codeGenerator().write(this.__boundType.inheritanceCode);
             }
             else
                 this.__boundType.defineMethod(this.__methodId, this.__methodType);

+ 3 - 3
src/eberon/eberon_grammar.js

@@ -3,7 +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 CodeGenerator = require("js/CodeGenerator.js");
 var EbContext = require("eberon/eberon_context.js");
 var Grammar = require("grammar.js");
 var Parser = require("parser.js");
@@ -148,7 +148,7 @@ exports.language = {
         makeOpenArray: EbArray.makeOpenArray
     },
     codeGenerator: {
-        make: EbCodeGenerator.makeGenerator,
-        nil: EbCodeGenerator.nullGenerator()
+        make: CodeGenerator.makeGenerator,
+        nil: CodeGenerator.nullGenerator()
     }
 };

+ 13 - 6
test/input/eberon/constructor.ob

@@ -1,43 +1,50 @@
 MODULE m;
 TYPE
     T = RECORD
+        PROCEDURE T();
     END;
 
     Derived = RECORD(T)
+        PROCEDURE Derived();
     END;
 
     RecordWithField = RECORD
+        PROCEDURE RecordWithField();
+
         i: INTEGER;
     END;
 
     RecordWithFieldDerived = RECORD(T)
+        PROCEDURE RecordWithFieldDerived();
     END;
 
     RecordWithParamConstructor = RECORD
+        PROCEDURE RecordWithParamConstructor(a: INTEGER);
     END;
 
     DerivedRecordWithParamConstructor = RECORD(RecordWithParamConstructor)
+        PROCEDURE DerivedRecordWithParamConstructor();
     END;
 
-PROCEDURE T();
+PROCEDURE T.T();
 END;
 
-PROCEDURE Derived();
+PROCEDURE Derived.Derived();
 END;
 
-PROCEDURE RecordWithField();
+PROCEDURE RecordWithField.RecordWithField();
 END;
 
-PROCEDURE RecordWithFieldDerived();
+PROCEDURE RecordWithFieldDerived.RecordWithFieldDerived();
 END;
 
 PROCEDURE passAsArgument(o: T);
 END;
 
-PROCEDURE RecordWithParamConstructor(a: INTEGER);
+PROCEDURE RecordWithParamConstructor.RecordWithParamConstructor(a: INTEGER);
 END;
 
-PROCEDURE DerivedRecordWithParamConstructor()
+PROCEDURE DerivedRecordWithParamConstructor.DerivedRecordWithParamConstructor()
     | SUPER(123);
 END;
 

+ 3 - 1
test/input/eberon/run/constructor.ob

@@ -1,10 +1,12 @@
 MODULE m;
 TYPE
     T = RECORD
+        PROCEDURE T();
+
         i: INTEGER;
     END;
 
-PROCEDURE T();
+PROCEDURE T.T();
 BEGIN
     SELF.i := 3;
 END;

+ 64 - 52
test/test_unit_eberon.js

@@ -1,7 +1,7 @@
 "use strict";
 
 var Class = require("rtl.js").Class;
-var EberonCodeGenerator = require("js/EberonCodeGenerator.js");
+//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 +75,7 @@ var TestVar = Class.extend({
     type: function(){return this.__type;},
     setType: function(type){this.__type = type;}
 });
-
+/*
 function makeCodeSuite(){
     return {
         "insertion": pass(
@@ -107,9 +107,9 @@ function makeCodeSuite(){
         )
     };
 }
-
+*/
 exports.suite = {
-"code": makeCodeSuite(),
+//"code": makeCodeSuite(),
 "arithmetic operators": testWithContext(
     context(grammar.statement, "VAR b1: BOOLEAN;"),
     pass(),
@@ -1077,26 +1077,28 @@ exports.suite = {
 "constructor": {
     "declaration": testWithGrammar(
         grammar.declarationSequence, 
-        pass("TYPE T = RECORD END; PROCEDURE T(); END;",
-             "TYPE T = RECORD i: INTEGER; END; PROCEDURE T(); BEGIN SELF.i := 0; END;",
-             "TYPE T = RECORD END; PROCEDURE T(); END T;",
-             "TYPE T = RECORD END; PROCEDURE p(); PROCEDURE T(); END; BEGIN T(); END;", /* local procedure name may match type name from outer scope*/
-             "TYPE T = RECORD END; PROCEDURE T(a: INTEGER); END T;"
+        pass("TYPE T = RECORD PROCEDURE T(); END; PROCEDURE T.T(); END;",
+             "TYPE T = RECORD PROCEDURE T(); i: INTEGER; END; PROCEDURE T.T(); BEGIN SELF.i := 0; END;",
+             "TYPE T = RECORD PROCEDURE T(); END; PROCEDURE T.T(); END T.T;",
+             "TYPE T = RECORD PROCEDURE T(a: INTEGER); END; PROCEDURE T.T(a: INTEGER); END;"
         ),
-        fail(["TYPE T = RECORD END; PROCEDURE T(); END; PROCEDURE T(); END;", "constructor 'T' already defined"],
-             ["TYPE T = RECORD END; PROCEDURE T(): INTEGER; RETURN 0; END;", "constructor 'T' cannot have result type specified"],
-             ["TYPE T = ARRAY 3 OF INTEGER; PROCEDURE T(); END;", "'T' already declared"],
-             ["TYPE T = RECORD END; PROCEDURE T(); END T.T;", "mismatched method names: expected 'T' at the end (or nothing), got 'T.T'"],
-             ["TYPE T = RECORD END; PROCEDURE T.T(); END;", "'T' has no declaration for method 'T'"],
-             ["TYPE T = RECORD END; PROCEDURE T(); END T2;", "mismatched method names: expected 'T' at the end (or nothing), got 'T2'"],
-             ["TYPE T = RECORD END; PROCEDURE T(); END T.T;", "mismatched method names: expected 'T' at the end (or nothing), got 'T.T'"]
+        fail(["TYPE T = RECORD END; PROCEDURE T(); END;", "'T' already declared"],
+             ["TYPE T = RECORD END; PROCEDURE T.T(); END;", "constructor was not declared for 'T'"],
+             ["TYPE T = RECORD PROCEDURE T(); END; PROCEDURE T.T(a: INTEGER); END;", "constructor 'T' signature mismatch: declared as 'PROCEDURE' but defined as 'PROCEDURE(INTEGER)'"],
+             ["TYPE T = RECORD PROCEDURE T(); PROCEDURE T(); END;", "constructor 'T' already declared"],
+             ["TYPE T = RECORD PROCEDURE T(); END; PROCEDURE T.T(); END T;", "mismatched method names: expected 'T.T' at the end (or nothing), got 'T'"],
+             ["TYPE T = RECORD PROCEDURE T(); END; PROCEDURE p(); PROCEDURE T.T(); END; END;", "method should be defined in the same scope as its bound type 'T'"],
+             ["PROCEDURE p(); TYPE T = RECORD PROCEDURE T(); END; END;", "constructor was declared for 'T' but was not defined"],
+             ["TYPE T = RECORD PROCEDURE T(); END; PROCEDURE T.T(); END; PROCEDURE T.T(); END;", "constructor already defined for 'T'"],   
+             ["TYPE T = RECORD PROCEDURE T(): INTEGER; END;", "constructor 'T' cannot have result type specified"],
+             ["TYPE T = ARRAY 3 OF INTEGER; PROCEDURE T(); END;", "'T' already declared"]
              )
         ),
     "as expression": testWithContext(
         context(grammar.expression,
                 "TYPE T = RECORD i: INTEGER; END; PT = POINTER TO T;"
-                + "ConsWithArguments = RECORD END;"
-                + "PROCEDURE ConsWithArguments(a: INTEGER); END;"
+                + "ConsWithArguments = RECORD PROCEDURE ConsWithArguments(a: INTEGER); END;"
+                + "PROCEDURE ConsWithArguments.ConsWithArguments(a: INTEGER); END;"
                 + "PROCEDURE byVar(VAR a: T): INTEGER; RETURN 0; END;"
                 + "PROCEDURE byNonVar(a: T): INTEGER; RETURN 0; END;"
                 ),
@@ -1118,55 +1120,65 @@ exports.suite = {
         pass("r <- T()"),
         fail()
         ),
-    "call base": testWithContext(
+    "call base - correct": testWithContext(
         context(grammar.declarationSequence,
-                "TYPE T = RECORD END; RecordWthoutConstructor = RECORD END;"
-                + "Derived = RECORD(T) END;"
-                + "DerivedWthoutConstructor = RECORD(RecordWthoutConstructor) END;"
-                + "RecordWthConstructorNoParameters = RECORD END;"
-                + "DerivedWthConstructorNoParameters = RECORD(RecordWthConstructorNoParameters) END;"
-                + "PROCEDURE T(a: INTEGER); END;"
-                + "PROCEDURE RecordWthConstructorNoParameters(); END;"
+                "TYPE T = RECORD PROCEDURE T(a: INTEGER); END;"
+                + "Derived = RECORD(T) PROCEDURE Derived(); END;"
+                + "PROCEDURE T.T(a: INTEGER); END;"
                ),
-        pass("PROCEDURE Derived() | SUPER(0); END;"),
-        fail(["PROCEDURE Derived(); END;", "base record constructor has parameters but was not called (use '| SUPER' to pass parameters to base constructor)"],
-             ["PROCEDURE Derived() | SUPER(1, 2); END;", "1 argument(s) expected, got 2"],
-             ["PROCEDURE Derived() | SUPER(FALSE); END;", "type mismatch for argument 1: 'BOOLEAN' cannot be converted to 'INTEGER'"],
-             ["PROCEDURE Derived() | SUPER(); END;", "1 argument(s) expected, got 0"],
-             ["PROCEDURE Derived(); BEGIN SUPER(0); END;", "cannot call base constructor from procedure body (use '| SUPER' to pass parameters to base constructor)"],
-             ["PROCEDURE RecordWthoutConstructor() | SUPER(0); END;", "'RecordWthoutConstructor' has no base type - SUPER cannot be used"],
-             ["PROCEDURE DerivedWthoutConstructor() | SUPER(); END;", "base record constructor has no parameters and will be called automatically (do not use '| SUPER' to call base constructor)"],
-             ["PROCEDURE DerivedWthConstructorNoParameters() | SUPER(); END;", "base record constructor has no parameters and will be called automatically (do not use '| SUPER' to call base constructor)"]
+        pass("PROCEDURE Derived.Derived() | SUPER(0); END;")
+        ),
+    "call base - incorrect": testWithContext(
+        context(grammar.declarationSequence,
+                "TYPE T = RECORD PROCEDURE T(a: INTEGER); END;"
+                + "RecordWthoutBase = RECORD END;"
+                + "Derived = RECORD(T) PROCEDURE Derived(); END;"
+                + "DerivedWthoutConstructor = RECORD(RecordWthoutBase) PROCEDURE DerivedWthoutConstructor(); END;"
+                + "RecordWthConstructorNoParameters = RECORD PROCEDURE RecordWthConstructorNoParameters(); END;"
+                + "DerivedWthConstructorNoParameters = RECORD(RecordWthConstructorNoParameters) PROCEDURE DerivedWthConstructorNoParameters(); END;"
+                + "PROCEDURE T.T(a: INTEGER); END;"
+                + "PROCEDURE RecordWthConstructorNoParameters.RecordWthConstructorNoParameters(); END;"
+               ),
+        pass(),
+        fail(["PROCEDURE Derived.Derived(); END;", "base record constructor has parameters but was not called (use '| SUPER' to pass parameters to base constructor)"],
+             ["PROCEDURE Derived.Derived() | SUPER(1, 2); END;", "1 argument(s) expected, got 2"],
+             ["PROCEDURE Derived.Derived() | SUPER(FALSE); END;", "type mismatch for argument 1: 'BOOLEAN' cannot be converted to 'INTEGER'"],
+             ["PROCEDURE Derived.Derived() | SUPER(); END;", "1 argument(s) expected, got 0"],
+             ["PROCEDURE Derived.Derived(); BEGIN SUPER(0); END;", "cannot call base constructor from procedure body (use '| SUPER' to pass parameters to base constructor)"],
+             ["PROCEDURE RecordWthoutBase.RecordWthoutBase() | SUPER(0); END;", "'RecordWthoutBase' has no base type - SUPER cannot be used"],
+             ["PROCEDURE DerivedWthoutConstructor.DerivedWthoutConstructor() | SUPER(); END;", "base record constructor has no parameters and will be called automatically (do not use '| SUPER' to call base constructor)"],
+             ["PROCEDURE DerivedWthConstructorNoParameters.DerivedWthConstructorNoParameters() | SUPER(); END;", "base record constructor has no parameters and will be called automatically (do not use '| SUPER' to call base constructor)"]
             )
         ),
-    "initialize fields": testWithModule(
-            "MODULE m;"
-          + "TYPE Field* = RECORD END;"
-          + "PROCEDURE Field(a: INTEGER); END;"
-          + "END m.",
-        pass("MODULE m2; IMPORT m; TYPE T = RECORD f: m.Field; END; PROCEDURE T() | f(123); END; END m2."),
-        fail(["MODULE m2; IMPORT m; TYPE T = RECORD f: m.Field; END; PROCEDURE T(); END; END m2.", 
+    "initialize fields": testWithContext(
+        context(grammar.declarationSequence,
+                "TYPE Field = RECORD PROCEDURE Field(a: INTEGER); END;"
+              + "PROCEDURE Field.Field(a: INTEGER); END;"),
+        pass("TYPE T = RECORD PROCEDURE T(); f: Field; END; PROCEDURE T.T() | f(123); END;"),
+        fail(["TYPE T = RECORD PROCEDURE T(); f: Field; END; PROCEDURE T.T(); END;", 
               "constructor 'T' must initialize fields: f"],
-             ["MODULE m2; TYPE T = RECORD END; PROCEDURE T() | unknownField(123); END; END m2.", 
+             ["TYPE T = RECORD PROCEDURE T(); END; PROCEDURE T.T() | unknownField(123); END;", 
               "'unknownField' is not record 'T' own field"],
-             ["MODULE m2; IMPORT m; TYPE T = RECORD f: m.Field; END; Derived = RECORD(T) END; PROCEDURE Derived() | f(123); END; END m2.", 
+             ["TYPE T = RECORD f: Field; END; Derived = RECORD(T) PROCEDURE Derived(); END; PROCEDURE Derived.Derived() | f(123); END;", 
               "'f' is not record 'Derived' own field"],
-             ["MODULE m2; IMPORT m; TYPE T = RECORD f: m.Field; END; PROCEDURE T() | f(123), f(123); END; END m2.", 
+             ["TYPE T = RECORD PROCEDURE T(); f: Field; END; PROCEDURE T.T() | f(123), f(123); END;", 
               "field 'f' is already initialized"],
-             ["MODULE m2; TYPE T = RECORD i: INTEGER; END; PROCEDURE T() | i(); END; END m2.", 
+             ["TYPE T = RECORD i: INTEGER; END; PROCEDURE T.T() | i(); END;", 
               "cannot initialize field 'i', only fields of record types are supported"],
-             ["MODULE m2; TYPE T = RECORD i: INTEGER; END; PROCEDURE T() | i(123); END; END m2.", 
+             ["TYPE T = RECORD i: INTEGER; END; PROCEDURE T.T() | i(123); END;", 
               "cannot initialize field 'i', only fields of record types are supported"]
              )
         ),
     "call base and initialize fields": testWithContext(
         context(grammar.declarationSequence,
-                "TYPE Field = RECORD END; T = RECORD END; Derived = RECORD(T) f: Field; END;"
-              + "PROCEDURE Field(a: INTEGER); END;"
-              + "PROCEDURE T(a: INTEGER); END;"
+                "TYPE Field = RECORD PROCEDURE Field(a: INTEGER); END;"
+              + "T = RECORD PROCEDURE T(a: INTEGER); END;"
+              + "Derived = RECORD(T) PROCEDURE Derived(); f: Field; END;"
+              + "PROCEDURE Field.Field(a: INTEGER); END;"
+              + "PROCEDURE T.T(a: INTEGER); END;"
               ),
-        pass("PROCEDURE Derived() | SUPER(123), f(456); END;"),
-        fail(["PROCEDURE Derived() | f(456), SUPER(123); END;", "not parsed"])
+        pass("PROCEDURE Derived.Derived() | SUPER(123), f(456); END;"),
+        fail(["PROCEDURE Derived.Derived() | f(456), SUPER(123); END;", "not parsed"])
         )
     }
 };