فهرست منبع

Automatically call base constructor and initialize fields in custom constructor.

Vladislav Folts 10 سال پیش
والد
کامیت
426523ab19
5فایلهای تغییر یافته به همراه54 افزوده شده و 23 حذف شده
  1. BIN
      bin/compiled.zip
  2. 21 12
      src/context.js
  3. 12 11
      src/eberon/eberon_context.js
  4. 8 0
      test/expected/eberon/constructor.js
  5. 13 0
      test/input/eberon/constructor.ob

BIN
bin/compiled.zip


+ 21 - 12
src/context.js

@@ -590,7 +590,12 @@ exports.ProcDecl = ChainedContext.extend({
             throw new Errors.Error("mismatched procedure names: '" + this.__id.id()
                                  + "' at the begining and '" + id + "' at the end");
     },
-    _prolog: function(){return "\nfunction " + this.__id.id() + "(";},
+    _prolog: function(){
+        return "\nfunction " + this.__id.id() + "(";
+    },
+    _beginBody: function(){
+        this.codeGenerator().openScope();
+    },
     typeName: function(){return undefined;},
     setType: function(type){
         var procSymbol = Symbol.makeSymbol(
@@ -621,10 +626,9 @@ exports.ProcDecl = ChainedContext.extend({
     },
     handleMessage: function(msg){
         if (msg == endParametersMsg){
-            var code = this.codeGenerator();
-            code.write(")");
-            code.openScope();
-            return undefined;
+            this.codeGenerator().write(")");
+            this._beginBody();
+            return;
         }
         if (msg instanceof AddArgumentMsg)
             return this.__addArgument(msg.name, msg.arg);
@@ -1768,21 +1772,26 @@ exports.RecordDecl = ChainedContext.extend({
             );
     },
     _generateConstructor: function(){
-        var type = this.__type;
-        var baseType = Type.recordBase(type);
         var gen = CodeGenerator.makeGenerator();
-        var qualifiedBase = baseType ? this.qualifyScope(Type.recordScope(baseType)) + Type.typeName(baseType) : undefined; 
         gen.write("function " + this.__cons + "()");
         gen.openScope();
+        gen.write(this._generateFieldsInitializationCode());
+        gen.closeScope("");
+        return gen.result();
+    },
+    _generateFieldsInitializationCode: function(){
+        var type = this.__type;
+        var baseType = Type.recordBase(type);
+        var qualifiedBase = baseType ? this.qualifyScope(Type.recordScope(baseType)) + Type.typeName(baseType) : undefined; 
+        var result = "";
         if (baseType)
-            gen.write(qualifiedBase + ".call(this);\n");
+            result += qualifiedBase + ".call(this);\n";
         var ownFields = Type.recordOwnFields(type);
         for(var f in ownFields){
             var fieldType = ownFields[f].type();
-            gen.write("this." + mangleField(f, fieldType) + " = " + fieldType.initializer(this) + ";\n");
+            result += "this." + mangleField(f, fieldType) + " = " + fieldType.initializer(this) + ";\n";
         }
-        gen.closeScope("");
-        return gen.result();
+        return result;
     },
     _generateInheritance: function(){
         var base = Type.recordBase(this.__type);

+ 12 - 11
src/eberon/eberon_context.js

@@ -448,9 +448,11 @@ var RecordType = Class.extend.call(Type.Record, {
         if (!methodId.exported())
             this.__nonExportedMethods.push(id);
     },
-    setInheritanceCode: function(code){
-        this.__inheritanceCode = code;
+    setRecordInitializationCode: function(fieldsInitializationCode, inheritanceCode){
+        this.__fieldsInitializationCode = fieldsInitializationCode;
+        this.__inheritanceCode = inheritanceCode;
     },
+    fieldsInitializationCode: function(){return this.__fieldsInitializationCode;},
     defineConstructor: function(type){
         if (this.__customConstructor)
             throw new Errors.Error("constructor '" + Type.typeName(this) + "' already defined");
@@ -649,7 +651,9 @@ var RecordDecl = Context.RecordDecl.extend({
         var pos = gen.makeInsertion();
         var type = this.type();
         var inheritanceCode = this._generateInheritance();
-        type.setInheritanceCode(inheritanceCode);
+        type.setRecordInitializationCode(
+            this._generateFieldsInitializationCode(), 
+            inheritanceCode);
         this.currentScope().addFinalizer(function(){
             if (!this.__type.customConstructor())
                 gen.insert(pos, this._generateConstructor() + inheritanceCode);
@@ -723,6 +727,11 @@ var ProcOrMethodDecl = Context.ProcDecl.extend({
                                    : Type.typeName(this.__boundType) + ".prototype." + this.__methodId.id() + " = function("
             : Context.ProcDecl.prototype._prolog.call(this);
     },
+    _beginBody: function(){
+        Context.ProcDecl.prototype._beginBody.call(this);
+        if (this.__isConstructor)
+            this.codeGenerator().write(this.__boundType.fieldsInitializationCode());
+    },
     _makeArgumentVariable: function(arg){
         if (!arg.isVar)
             return new TypeNarrowVariable(arg.type, false, true);
@@ -743,14 +752,6 @@ var ProcOrMethodDecl = Context.ProcDecl.extend({
     handleIdent: function(id){
         if (!this.__boundType)
             Context.ProcDecl.prototype.handleIdent.call(this, id);
-        /*else if (!this.__endingId){
-            if (!this.__isConstructor || id != Type.typeName(this.__boundType))
-                this.__endingId = id;
-        }
-        else if (this.__endingId == Type.typeName(this.__boundType)
-                && id == this.__id.id())
-            this.__endingId = undefined;
-        */
         else if (this.__endingId)
             this.__endingId = this.__endingId + "." + id;
         else

+ 8 - 0
test/expected/eberon/constructor.js

@@ -10,6 +10,14 @@ var m = function (){
 function T(){
 }
 function Derived(){
+	T.call(this);
 }
 RTL$.extend(Derived, T);
+function RecordWithField(){
+	this.i = 0;
+}
+function RecordWithFieldDerived(){
+	T.call(this);
+}
+RTL$.extend(RecordWithFieldDerived, T);
 }();

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

@@ -6,10 +6,23 @@ TYPE
     Derived = RECORD(T)
     END;
 
+    RecordWithField = RECORD
+        i: INTEGER;
+    END;
+
+    RecordWithFieldDerived = RECORD(T)
+    END;
+
 PROCEDURE T();
 END;
 
 PROCEDURE Derived();
 END;
 
+PROCEDURE RecordWithField();
+END;
+
+PROCEDURE RecordWithFieldDerived();
+END;
+
 END m.