Browse Source

proper inlining support (not yet finished -- disabled for the time being)

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@8498 8c9fc860-2736-0410-a75d-ab315db34111
felixf 6 years ago
parent
commit
955439151b

+ 2 - 2
source/FoxCSharpParser.Mod

@@ -637,7 +637,7 @@ KernelLog.Ln();
         PROCEDURE EnterInit;
             VAR block: SyntaxTree.StatementBlock;
         BEGIN
-            block := SyntaxTree.NewStatementBlock(invalidPosition, NIL);
+            block := SyntaxTree.NewStatementBlock(invalidPosition, NIL, NIL);
             initOuter := block;
             initStatements := SyntaxTree.NewStatementSequence();
             block.SetStatementSequence(initStatements);
@@ -1355,7 +1355,7 @@ KernelLog.Ln();
             END;
             Check(Scanner.LeftBrace);
             position := symbol.position; position.start := position.end; 
-            block := SyntaxTree.NewStatementBlock(position, outer);
+            block := SyntaxTree.NewStatementBlock(position, outer, NIL);
             (* CommentStatement(block); *)
             IF ~Optional(Scanner.RightBrace) THEN
                 localIdentTable.OpenScope;

+ 10 - 2
source/FoxIntermediateBackend.Mod

@@ -6157,7 +6157,12 @@ TYPE
 			currentIsInline := wasInline;
 			RETURN ~tooComplex
 		END InlineProcedureCall;
-
+		
+		PROCEDURE VisitInlineCallDesignator*(x: SyntaxTree.InlineCallDesignator);
+		BEGIN
+			VisitStatementBlock(x.block);
+		END VisitInlineCallDesignator;
+			
 		PROCEDURE VisitProcedureCallDesignator*(x: SyntaxTree.ProcedureCallDesignator);
 		VAR
 			parameters: SyntaxTree.ExpressionList;
@@ -12065,6 +12070,7 @@ TYPE
 
 		PROCEDURE VisitStatementBlock*(x: SyntaxTree.StatementBlock);
 		VAR previouslyUnchecked, previouslyCooperativeSwitches: BOOLEAN; end: Label;
+			prevScope: SyntaxTree.Scope;
 		BEGIN
 			IF Trace THEN TraceEnter("VisitStatementBlock") END;
 			IF emitLabels THEN Emit(LabelInstruction(x.position)) END;
@@ -12073,6 +12079,8 @@ TYPE
 			isUnchecked := isUnchecked OR x.isUnchecked;
 			previouslyCooperativeSwitches := cooperativeSwitches;
 			cooperativeSwitches := cooperativeSwitches & ~x.isUncooperative;
+			prevScope := currentScope;
+			IF x.scope # NIL THEN currentScope := x.scope END;
 
 			IF x.isExclusive THEN Lock(TRUE); ASSERT(~locked);  locked := TRUE; END;
 			IF x.statements # NIL THEN
@@ -12096,7 +12104,7 @@ TYPE
 			IF x.isExclusive THEN Lock(FALSE); ASSERT(locked); locked := FALSE; END;
 			isUnchecked := previouslyUnchecked;
 			cooperativeSwitches := previouslyCooperativeSwitches;
-
+			currentScope := prevScope;
 			IF Trace THEN TraceExit("VisitStatementBlock") END;
 		END VisitStatementBlock;
 

+ 1 - 1
source/FoxParser.Mod

@@ -1381,7 +1381,7 @@ TYPE
 			IF Trace THEN S( "StatementBlock" ) END;
 			position := symbol.position;
 			position.start := position.end;
-			block := SyntaxTree.NewStatementBlock( position, outer );
+			block := SyntaxTree.NewStatementBlock( position, outer, NIL );
 			CommentStatement(block);
 			IF Optional( Scanner.LeftBrace ) THEN
 				block.SetModifier(Flags());

+ 6 - 0
source/FoxPrintout.Mod

@@ -733,6 +733,12 @@ TYPE
 			w.String("("); ExpressionList(x.parameters); w.String(")");
 		END VisitProcedureCallDesignator;
 
+		PROCEDURE VisitInlineCallDesignator*(x: SyntaxTree.InlineCallDesignator);
+		BEGIN
+			VisitStatementBlock(x.block);
+		END VisitInlineCallDesignator;
+		
+
 		PROCEDURE VisitStatementDesignator*(x: SyntaxTree.StatementDesignator);
 		BEGIN
 			Indent; Keyword("STATEMENT-DESIGNATOR ");

+ 228 - 2
source/FoxSemanticChecker.Mod

@@ -11,6 +11,8 @@ CONST
 	Infinity = MAX(LONGINT); (* for type distance *)
 	UndefinedPhase = 0; DeclarationPhase=1; InlinePhase=2; ImplementationPhase=3;
 
+	InliningSupport = FALSE;
+
 TYPE
 	Position=SyntaxTree.Position;
 	FileName=ARRAY 256 OF CHAR;
@@ -3666,6 +3668,148 @@ TYPE
 			END;
 		END CanPassInRegister;
 
+		PROCEDURE ReplaceExpressions(x: SyntaxTree.ExpressionList; rScope: SyntaxTree.Scope);
+		VAR i: LONGINT;
+		BEGIN
+				IF x # NIL THEN
+					FOR i := 0 TO x.Length()-1 DO
+						ReplaceExpression(x.GetExpression(i),rScope);
+					END;
+				END;				
+		END ReplaceExpressions;
+		
+		PROCEDURE ReplaceExpression(x: SyntaxTree.Expression; rScope: SyntaxTree.Scope);
+		VAR find: SyntaxTree.Symbol; name: ARRAY 32 OF CHAR;
+		BEGIN
+			IF x = NIL THEN RETURN END;
+			WITH
+				x: SyntaxTree.ResultDesignator DO ReplaceExpression(x.left,rScope);
+			| SyntaxTree.SelfDesignator DO ReplaceExpression(x.left,rScope);
+			| SyntaxTree.SupercallDesignator DO ReplaceExpression(x.left,rScope);
+			| SyntaxTree.DereferenceDesignator DO ReplaceExpression(x.left,rScope);
+			| SyntaxTree.TypeGuardDesignator DO ReplaceExpression(x.left,rScope);
+			| SyntaxTree.BuiltinCallDesignator DO 
+				ReplaceExpression(x.left,rScope);
+				ReplaceExpressions(x.parameters,rScope);
+			| SyntaxTree.StatementDesignator DO
+				ReplaceStatement(x.statement, rScope);
+				ReplaceExpression(x.result, rScope);
+			| SyntaxTree.ProcedureCallDesignator DO
+				ReplaceExpression(x.left,rScope);
+				ReplaceExpressions(x.parameters,rScope);
+			| SyntaxTree.InlineCallDesignator DO
+				HALT(200);
+			| SyntaxTree.IndexDesignator DO
+				ReplaceExpression(x.left,rScope);
+				ReplaceExpressions(x.parameters,rScope);
+			| SyntaxTree.SymbolDesignator DO
+				IF x.symbol IS SyntaxTree.Parameter THEN
+					find := rScope.FindSymbol(x.symbol.name);
+					IF find # NIL THEN
+						x.symbol.GetName(name);
+						TRACE(name);
+						x.SetSymbol(find);
+					END;
+				END;
+			| SyntaxTree.BracketDesignator DO HALT(100)
+			| SyntaxTree.ArrowDesignator DO HALT(100)
+			| SyntaxTree.ParameterDesignator DO HALT(100)
+			| SyntaxTree.SelectorDesignator DO HALT(100)
+			| SyntaxTree.IdentifierDesignator DO HALT(100)
+			| SyntaxTree.Conversion DO
+				ReplaceExpression(x.expression,rScope);
+			| SyntaxTree.TensorRangeExpression DO
+			| SyntaxTree.RangeExpression DO
+				ReplaceExpression(x.first, rScope);
+				ReplaceExpression(x.last, rScope);
+				ReplaceExpression(x.step, rScope);
+			| SyntaxTree.BinaryExpression DO
+				ReplaceExpression(x.left, rScope);
+				ReplaceExpression(x.right, rScope);			
+			| SyntaxTree.UnaryExpression DO
+				ReplaceExpression(x.left, rScope);
+			| SyntaxTree.MathArrayExpression DO
+				ReplaceExpressions(x.elements, rScope);
+			| SyntaxTree.Set DO
+				ReplaceExpressions(x.elements, rScope);
+			ELSE			
+			END;
+		END ReplaceExpression;
+
+		PROCEDURE ReplaceIfPart(x: SyntaxTree.IfPart; rScope: SyntaxTree.Scope);
+		BEGIN
+				ReplaceExpression(x.condition,rScope);
+				ReplaceStatements(x.statements,rScope);
+		END ReplaceIfPart;		
+
+		PROCEDURE ReplaceStatement(x: SyntaxTree.Statement; rScope: SyntaxTree.Scope);
+		VAR i: LONGINT;
+		BEGIN
+			WITH x: 
+			SyntaxTree.ProcedureCallStatement DO
+				ReplaceExpression(x.call,rScope);
+			| SyntaxTree.Assignment DO 
+				ReplaceExpression(x.left,rScope);
+				ReplaceExpression(x.right,rScope);
+			| SyntaxTree.CommunicationStatement DO
+					ReplaceExpression(x.left,rScope);
+					ReplaceExpression(x.right,rScope);
+			| SyntaxTree.IfStatement DO 
+					ReplaceIfPart(x.ifPart, rScope);
+					FOR i := 0 TO x.ElsifParts()-1 DO
+						ReplaceIfPart(x.GetElsifPart(i), rScope);
+					END;
+					IF x.elsePart # NIL THEN
+						ReplaceStatements(x.elsePart,rScope);
+					END;
+			| SyntaxTree.WithStatement DO
+					ReplaceExpression(x.variable,rScope);
+					FOR i := 0 TO x.WithParts()-1 DO
+						ReplaceStatements(x.GetWithPart(i).statements,rScope);
+					END;
+					IF x.elsePart # NIL THEN
+						ReplaceStatements(x.elsePart,rScope);
+					END;					
+			| SyntaxTree.CaseStatement DO
+					ReplaceExpression(x.variable,rScope);
+					FOR i := 0 TO x.CaseParts()-1 DO
+						ReplaceStatements(x.GetCasePart(i).statements,rScope);
+					END;
+					IF x.elsePart # NIL THEN
+						ReplaceStatements(x.elsePart,rScope);
+					END;										
+			| SyntaxTree.WhileStatement DO
+				ReplaceExpression(x.condition,rScope);
+				ReplaceStatements(x.statements,rScope);
+			| SyntaxTree.RepeatStatement DO
+				ReplaceExpression(x.condition,rScope);
+				ReplaceStatements(x.statements,rScope);
+			| SyntaxTree.ForStatement DO
+				ReplaceExpression(x.variable,rScope);
+				ReplaceExpression(x.from,rScope);
+				ReplaceExpression(x.to,rScope);
+				ReplaceExpression(x.by,rScope);
+				ReplaceStatements(x.statements,rScope);				
+			| SyntaxTree.LoopStatement DO
+				ReplaceStatements(x.statements,rScope);				
+			| SyntaxTree.ExitStatement DO 
+			| SyntaxTree.ReturnStatement DO
+				ReplaceExpression(x.returnValue,rScope);
+			| SyntaxTree.AwaitStatement DO
+				ReplaceExpression(x.condition,rScope);				
+			| SyntaxTree.StatementBlock DO
+				ReplaceStatements(x.statements,rScope);
+			ELSE
+			END;
+		END ReplaceStatement;
+
+		PROCEDURE ReplaceStatements(statements: SyntaxTree.StatementSequence; rScope: SyntaxTree.Scope);
+		VAR i: LONGINT;
+		BEGIN
+			FOR i := 0 TO statements.Length()-1 DO
+				ReplaceStatement(statements.GetStatement(i), rScope);
+			END;
+		END ReplaceStatements;
 
 		(** return procedure call designator left(actualParameters)
 			- check realtime procedure call in realtime procedure
@@ -3681,10 +3825,18 @@ TYPE
 			actualParameter: SyntaxTree.Expression;
 			i: LONGINT;
 			self: SyntaxTree.Expression;
+			inlineScope: SyntaxTree.Scope; procedureType: SyntaxTree.ProcedureType;
+			tooComplex : BOOLEAN;
+			duplicate: BOOLEAN;
+			procedure: SyntaxTree.Procedure;
+			block: SyntaxTree.StatementBlock;
+			returnType: SyntaxTree.Type;
+			const: SyntaxTree.Constant;
+			var: SyntaxTree.Variable;
 		BEGIN
 			IF Trace THEN D.Str("ProcedureCallDesignator"); D.Ln; END;
 			result := SyntaxTree.invalidDesignator;
-			formalType := left.type.resolved(SyntaxTree.ProcedureType); (* type checked in ResolveParameterDesignator *)
+			formalType := left.type.resolved(SyntaxTree.ProcedureType); (* type checked in VisitParameterDesignator *)
 			numberFormalParameters := formalType.numberParameters;
 			numberActualParameters := actualParameters.Length();
 
@@ -3737,10 +3889,71 @@ TYPE
 
 			END;
 
+
+
+			IF result = SyntaxTree.invalidDesignator THEN
+			ELSIF (left IS SyntaxTree.SymbolDesignator) & (left(SyntaxTree.SymbolDesignator).symbol IS SyntaxTree.Procedure) THEN
+				procedure := left(SyntaxTree.SymbolDesignator).symbol(SyntaxTree.Procedure);
+			END;
+
+			IF InliningSupport & (procedure # NIL) & IsOberonInline(procedure) THEN
+				NEW(inlineScope, currentScope); 
+				procedureType := procedure.type(SyntaxTree.ProcedureType);
+
+				formalParameter := procedureType.firstParameter;
+				actualParameters := result(SyntaxTree.ProcedureCallDesignator).parameters;
+
+				tooComplex := FALSE;
+
+				i := 0;
+				WHILE (i < actualParameters.Length()) & ~tooComplex DO
+					actualParameter := actualParameters.GetExpression(i);
+					IF actualParameter.resolved # NIL THEN
+						actualParameter := actualParameter.resolved
+					END;
+					IF (actualParameter.resolved # NIL) & (actualParameter.resolved IS SyntaxTree.Value) THEN
+						const := SyntaxTree.NewConstant(actualParameter.position,formalParameter.name);
+						const.SetValue(actualParameter);
+						const.SetType(actualParameter.type);
+						inlineScope.AddConstant(const);
+						inlineScope.EnterSymbol(const, duplicate);
+					ELSE
+						var := SyntaxTree.NewVariable(actualParameter.position, formalParameter.name); 
+						(* copy expression to var *)
+						var.SetType(actualParameter.type);
+						inlineScope.AddVariable(var); 
+						inlineScope.EnterSymbol(var, duplicate);
+					END;
+					formalParameter := formalParameter.nextParameter;
+					INC(i);
+ 				END;
+			(*IF ~tooComplex & (procedureType.returnType # NIL) THEN
+				IF resultDesignator # NIL THEN
+					returnDesignator := resultDesignator
+				ELSE
+					returnDesignator := GetTemp(procedureType.returnType, TRUE);
+				END;
+				currentMapper.Add(NIL, returnDesignator, NIL, resultDesignator # NIL);
+			END;
+			*)
+					
+				Warning(result.position,"call to inline proc");
+				
+				block := SyntaxTree.NewStatementBlock(result.position, NIL, inlineScope);
+				block.SetStatementSequence(SyntaxTree.CloneStatementSequence(procedure.procedureScope.body.statements));
+				(*Parameters(block, procedure.type(SyntaxTree.ProcedureType).firstParameter, call(SyntaxTree.ProcedureCallDesignator).parameters);*)					
+				ReplaceStatements(block.statements, block.scope); 
+				ResolveStatementBlock(block);
+				returnType := result.type; 
+				result := SyntaxTree.NewInlineCallDesignator(result.position, result(SyntaxTree.ProcedureCallDesignator), block); 
+				result.SetType(returnType); 
+			END;
+
 			RETURN result
 		END NewProcedureCallDesignator;
 
 
+
 		(**
 			builtin call designator generated in ResolveParameterDesignator
 			-> nothing to be resolved
@@ -7884,7 +8097,18 @@ TYPE
 			((procedure.procedureScope.body = NIL) OR (procedure.procedureScope.body # NIL) & (procedure.procedureScope.body.code = NIL))
 	END IsOberonInline;
 
-
+	PROCEDURE SimpleExpression(e: SyntaxTree.Expression): BOOLEAN;
+	BEGIN
+		IF e = NIL THEN RETURN TRUE
+		ELSIF (e IS SyntaxTree.SymbolDesignator) THEN RETURN SimpleExpression(e(SyntaxTree.SymbolDesignator).left)
+		ELSIF (e IS SyntaxTree.Value) THEN RETURN TRUE
+		ELSIF (e IS SyntaxTree.SelfDesignator) THEN RETURN TRUE
+		ELSIF (e IS SyntaxTree.ResultDesignator) THEN RETURN TRUE
+		ELSIF (e IS SyntaxTree.DereferenceDesignator) THEN RETURN SimpleExpression(e(SyntaxTree.DereferenceDesignator).left)
+		ELSE RETURN FALSE
+		END;
+	END SimpleExpression;
+	
 	PROCEDURE Resolved(x: SyntaxTree.Type): SyntaxTree.Type;
 	BEGIN
 		IF x = NIL THEN RETURN NIL ELSE RETURN x.resolved END;
@@ -8832,6 +9056,8 @@ TYPE
 			RETURN TRUE
 		ELSIF expression IS SyntaxTree.BuiltinCallDesignator THEN
 			RETURN TRUE
+		ELSIF expression IS SyntaxTree.InlineCallDesignator THEN
+			RETURN TRUE
 		ELSIF (expression.type # NIL) & (expression.type.resolved IS SyntaxTree.ProcedureType) THEN
 			RETURN TRUE
 		ELSE

+ 32 - 5
source/FoxSyntaxTree.Mod

@@ -234,6 +234,10 @@ TYPE
 		PROCEDURE VisitProcedureCallDesignator*(x: ProcedureCallDesignator);
 		BEGIN HALT(100) (* abstract *) END VisitProcedureCallDesignator;
 
+		PROCEDURE VisitInlineCallDesignator*(x: InlineCallDesignator);
+		BEGIN HALT(100) (* abstract *) END VisitInlineCallDesignator;
+
+
 		PROCEDURE VisitStatementDesignator*(x: StatementDesignator);
 		BEGIN HALT(100) (* abstract *) END VisitStatementDesignator;
 
@@ -300,6 +304,7 @@ TYPE
 			| BuiltinCallDesignator DO VisitBuiltinCallDesignator(x)
 			| StatementDesignator DO VisitStatementDesignator(x)
 			| ProcedureCallDesignator DO VisitProcedureCallDesignator(x)
+			| InlineCallDesignator DO VisitInlineCallDesignator(x)
 			| IndexDesignator DO VisitIndexDesignator(x)
 			| SymbolDesignator DO VisitSymbolDesignator(x)
 			| BracketDesignator DO VisitBracketDesignator(x)
@@ -2435,6 +2440,20 @@ TYPE
 		END Clone;
 
 	END ProcedureCallDesignator;
+	
+	InlineCallDesignator*= OBJECT(Designator)
+	VAR
+		procedureCall-: ProcedureCallDesignator;
+		block-: StatementBlock; (* contains scope *)
+		
+		PROCEDURE & InitInlineCall*(position: Position; o: ProcedureCallDesignator; b: StatementBlock);
+		BEGIN
+			InitDesignator(position); 
+			procedureCall := o;
+			block := b;
+		END InitInlineCall;
+		
+	END InlineCallDesignator;
 
 	(** <<procedure(parameters)>>
 		builtin procedure call **)
@@ -4108,14 +4127,16 @@ TYPE
 			isRealtime-: BOOLEAN;
 			isUnchecked-: BOOLEAN;
 			isUncooperative-: BOOLEAN;
+			scope-: Scope;
 
-		PROCEDURE & InitStatementBlock( position: Position ; outer: Statement);
+		PROCEDURE & InitStatementBlock( position: Position ; outer: Statement; s: Scope);
 		BEGIN
 			InitStatement( position ,outer);  statements := NIL;  blockModifiers := NIL;
 			isExclusive := FALSE;
 			isRealtime := FALSE;
 			isUnchecked := FALSE;
 			isUncooperative := FALSE;
+			scope := s; 
 		END InitStatementBlock;
 
 		PROCEDURE SetRealtime*(b: BOOLEAN);
@@ -4198,7 +4219,7 @@ TYPE
 
 		PROCEDURE & InitBody(position: Position; scope: ProcedureScope);
 		BEGIN
-			InitStatementBlock(position,NIL); finally := NIL; priority := NIL; inScope := scope; code := NIL;
+			InitStatementBlock(position,NIL,scope); finally := NIL; priority := NIL; inScope := scope; code := NIL;
 			isActive := FALSE; isSafe := FALSE; isRealtime := FALSE;
 		END InitBody;
 
@@ -4272,7 +4293,7 @@ TYPE
 		ownerModule-: Module;
 
 
-		PROCEDURE & InitScope(outer: Scope);
+		PROCEDURE & InitScope*(outer: Scope);
 		BEGIN
 			firstSymbol := NIL; numberSymbols := 0;
 			firstConstant := NIL; lastConstant := NIL; numberConstants := 0;
@@ -5404,6 +5425,12 @@ VAR
 	BEGIN
 		NEW(procedureCallDesignator, position, left, parameters); RETURN procedureCallDesignator
 	END NewProcedureCallDesignator;
+	
+	PROCEDURE NewInlineCallDesignator*(position: Position; o: ProcedureCallDesignator; block: StatementBlock): InlineCallDesignator;
+	VAR inlineCall: InlineCallDesignator;
+	BEGIN
+		NEW(inlineCall, position, o, block); RETURN inlineCall;
+	END NewInlineCallDesignator;
 
 	PROCEDURE NewBuiltinCallDesignator*(position: Position; id: LONGINT; left: Designator; parameters: ExpressionList): BuiltinCallDesignator;
 	VAR builtinCallDesignator: BuiltinCallDesignator;
@@ -5609,10 +5636,10 @@ VAR
 		NEW(blockModifier,position,identifier,expression); RETURN blockModifier
 	END NewModifier;
 
-	PROCEDURE NewStatementBlock*( position: Position ; outer: Statement): StatementBlock;
+	PROCEDURE NewStatementBlock*( position: Position ; outer: Statement; scope: Scope): StatementBlock;
 	VAR statementBlock: StatementBlock;
 	BEGIN
-		NEW( statementBlock, position, outer );  RETURN statementBlock
+		NEW( statementBlock, position, outer, scope );  RETURN statementBlock
 	END NewStatementBlock;
 
 	PROCEDURE NewStatementDesignator*(position: Position; s: Statement): StatementDesignator;