Explorar el Código

Optimize code generation when record constructors are used in ternary
operator.
Cleanup.

Vladislav Folts hace 9 años
padre
commit
b1a4287e0a

BIN
bin/compiled.zip


+ 42 - 9
src/eberon/EberonContextExpression.ob

@@ -74,6 +74,9 @@ TYPE
     END;
 
     TernaryOperatorResult = RECORD(Variable.TypedVariable)
+        PROCEDURE TernaryOperatorResult(type: Types.PStorageType; condition, l, r: Expression.PType);
+
+        condition, left, right: Expression.PType;
     END;
 VAR
     setTermTypePromotion: PROCEDURE(VAR term: TermList): EberonTypePromotion.PMaybe;
@@ -102,8 +105,6 @@ BEGIN
 END;
 
 PROCEDURE findCommonBaseRecord(t1, t2: Record.PType): Record.PType;
-VAR
-    result: Record.PType;
 BEGIN
     depth1 <- hierarchyDepth(t1^);
     depth2 <- hierarchyDepth(t2^);
@@ -129,6 +130,14 @@ PROCEDURE findCommonBase(t1, t2: Types.PType): Types.PType;
            : t1;
 END;
 
+PROCEDURE ternaryCodeImpl(condition: Expression.PType; left, right: STRING): STRING;
+    RETURN condition.code() + " ? " + left + " : " + right;
+END;
+
+PROCEDURE ternaryCode(t: TernaryOperatorResult): STRING;
+    RETURN ternaryCodeImpl(t.condition, Expression.deref(t.left).code(), Expression.deref(t.right).code());
+END;
+
 PROCEDURE parentTerm(VAR maybeFactor: ContextHierarchy.Node): PTermList;
     RETURN maybeFactor IS ContextExpression.Factor 
         ? maybeFactor.factor^(ETFactor).termList
@@ -216,13 +225,8 @@ BEGIN
         IF ~(checkResultType IS Types.PStorageType) THEN
             Errors.raise("cannot use '" + checkResultType.description() + "' as a result of ternary operator");
         ELSE
-            result := NEW Expression.Type(
-                SELF.condition.code() + " ? " + Expression.deref(SELF.first).code() 
-                                      + " : " + Expression.deref(SELF.second).code(),
-                resultType,
-                NEW TernaryOperatorResult(resultType(Types.PStorageType)),
-                NIL,
-                CodePrecedence.conditional);
+            v <- NEW TernaryOperatorResult(checkResultType, SELF.condition, SELF.first, SELF.second);
+            result := NEW Expression.Type(ternaryCode(v^), resultType, v, NIL, CodePrecedence.conditional);
         END;
     END;
     SELF.parent()(ContextExpression.PExpressionHandler).handleExpression(result);
@@ -429,6 +433,13 @@ BEGIN
     END;
 END;
 
+PROCEDURE TernaryOperatorResult.TernaryOperatorResult(type: Types.PStorageType; condition, l, r: Expression.PType)
+    | SUPER(type),
+      condition(condition),
+      left(l),
+      right(r);
+END;
+
 PROCEDURE TernaryOperatorResult.isReference(): BOOLEAN;
     RETURN FALSE;
 END;
@@ -441,6 +452,28 @@ PROCEDURE TernaryOperatorResult.idType(): STRING;
     RETURN "ternary operator result";
 END;
 
+PROCEDURE optimizeRecordRValue*(VAR info: Types.Id; l: LanguageContext.Language): STRING;
+VAR
+    result: STRING;
+BEGIN
+    IF info IS TernaryOperatorResult THEN
+        lTemp <- Expression.isTemporary(info.left^);
+        rTemp <- Expression.isTemporary(info.right^);
+        IF lTemp & rTemp THEN
+            result := ternaryCode(info);
+        ELSIF lTemp THEN
+            result := ternaryCodeImpl(info.condition, 
+                                      info.left.code(), 
+                                      l.rtl.clone(info.right.code(), l.types.typeInfo(info.type()), "undefined"));
+        ELSIF rTemp THEN
+            result := ternaryCodeImpl(info.condition, 
+                                      l.rtl.clone(info.left.code(), l.types.typeInfo(info.type()), "undefined"),
+                                      info.right.code()); 
+        END;
+    END;
+    RETURN result;
+END;
+
 BEGIN
     (*resolve recursive calls*)
     setTermTypePromotion := setTermTypePromotionProc;

+ 7 - 2
src/eberon/EberonContextInPlace.ob

@@ -2,7 +2,7 @@ MODULE EberonContextInPlace;
 IMPORT
     CodeGenerator, 
     ContextExpression, ContextHierarchy, 
-    EberonContextDesignator, EberonContextLoop,
+    EberonContextDesignator, EberonContextExpression, EberonContextLoop,
     EberonRecord, Errors, Expression, LanguageContext, Symbols, Types;
 TYPE
     VariableInit* = RECORD(ContextExpression.ExpressionHandler)
@@ -48,8 +48,13 @@ BEGIN
             IF Expression.isTemporary(e^) THEN
                 SELF.code := SELF.code + e.code();
             ELSE
+                info <- e.info();
                 l <- SELF.root().language();
-                SELF.code := SELF.code + l.rtl.clone(e.code(), l.types.typeInfo(type), "undefined");
+                code <- EberonContextExpression.optimizeRecordRValue(info^, l^);
+                IF LEN(code) = 0 THEN
+                    code := l.rtl.clone(e.code(), l.types.typeInfo(type), "undefined");
+                END;
+                SELF.code := SELF.code + code;
             END;
         ELSE
             IF Expression.isTemporary(e^) & (type IS Types.PArray) THEN

+ 1 - 1
src/ob/ContextDesignator.ob

@@ -259,7 +259,7 @@ END;
 PROCEDURE Type.endParse(): BOOLEAN;
 BEGIN
     SELF.parent().attributes.designator :=
-        NEW Designator.Type(SELF.code, SELF.currentType, SELF.info, NIL);
+        NEW Designator.Type(SELF.code, SELF.currentType, SELF.info);
     RETURN TRUE;
 END;
 

+ 4 - 11
src/ob/Designator.ob

@@ -1,19 +1,17 @@
 MODULE Designator;
 IMPORT
-    ScopeBase, Types;
+    Types;
 TYPE
     Type* = RECORD
-        PROCEDURE Type*(code: STRING; type: Types.PType; info: Types.PId; scope: ScopeBase.PType);
+        PROCEDURE Type*(code: STRING; type: Types.PType; info: Types.PId);
 
         PROCEDURE code*(): STRING;
         PROCEDURE type*(): Types.PType;
         PROCEDURE info*(): Types.PId;
-        PROCEDURE scope*(): ScopeBase.PType;
 
         mCode: STRING;
         mType: Types.PType;
         mInfo: Types.PId;
-        mScope: ScopeBase.PType
     END;
 
     PType* = POINTER TO Type;
@@ -30,15 +28,10 @@ PROCEDURE Type.info(): Types.PId;
     RETURN SELF.mInfo
 END;
 
-PROCEDURE Type.scope(): ScopeBase.PType;
-    RETURN SELF.mScope
-END;
-
-PROCEDURE Type.Type(code: STRING; type: Types.PType; info: Types.PId; scope: ScopeBase.PType)
+PROCEDURE Type.Type(code: STRING; type: Types.PType; info: Types.PId)
   | mCode(code),
     mType(type),
-    mInfo(info),
-    mScope(scope);
+    mInfo(info);
 END;
 
 END Designator.

+ 1 - 9
src/ob/Procedure.ob

@@ -204,15 +204,7 @@ PROCEDURE Id.canBeReferenced(): BOOLEAN;
 END;
 
 PROCEDURE Id.idType(): STRING;
-VAR
-    prefix: STRING;
-BEGIN
-    IF SELF.local THEN
-        prefix := "local procedure";
-    ELSE
-        prefix := SUPER();
-    END;
-    RETURN prefix + " '" + SELF.name + "'";
+    RETURN (SELF.local ? "local procedure" : SUPER()) + " '" + SELF.name + "'";
 END;
 
 PROCEDURE StdId.StdId(type: PStd; name: STRING)

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

@@ -40,6 +40,22 @@ function initRecord(b/*BOOLEAN*/){
 	var r = RTL$.clone(b ? r1 : r2, {record: {}}, undefined);
 }
 
+function initRecordFromConstructor(b/*BOOLEAN*/){
+	var $scope1 = $scope + ".initRecordFromConstructor";
+	function T(i/*INTEGER*/){
+	}
+	var r = b ? new T(1) : new T(2);
+}
+
+function initRecordFromConstructorOrVariable(b/*BOOLEAN*/){
+	var $scope1 = $scope + ".initRecordFromConstructorOrVariable";
+	function T(){
+	}
+	var r = new T();
+	var r1 = b ? RTL$.clone(r, {record: {}}, undefined) : new T();
+	var r2 = b ? new T() : RTL$.clone(r, {record: {}}, undefined);
+}
+
 function operatorsPriority(b/*BOOLEAN*/){
 	return (b ? 1 : 2) + 3 | 0;
 }

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

@@ -40,6 +40,27 @@ BEGIN
 	r <- b ? r1 : r2;
 END;
 
+PROCEDURE initRecordFromConstructor(b: BOOLEAN);
+TYPE
+	T = RECORD 
+		PROCEDURE T(i: INTEGER); 
+	END;
+	PROCEDURE T.T(i: INTEGER); 
+	END;
+BEGIN
+	r <- b ? T(1) : T(2);
+END;
+
+PROCEDURE initRecordFromConstructorOrVariable(b: BOOLEAN);
+TYPE
+	T = RECORD END;
+VAR
+	r: T;
+BEGIN
+	r1 <- b ? r : T();
+	r2 <- b ? T() : r;
+END;
+
 PROCEDURE operatorsPriority(b: BOOLEAN): INTEGER;
 	RETURN (b ? 1 : 2) + 3;
 END;