From 098a5442caeb2e9505864e985900d4793014dffc Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Thu, 6 Jul 2017 12:30:19 -0700 Subject: More exhaustive lowering - Handle all statement cases explicitly (rather than falling back to the "structural recursion" mess) - Handle back-references from child statements to their parents --- source/slang/emit.cpp | 7 +- source/slang/lower.cpp | 203 +++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 195 insertions(+), 15 deletions(-) diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index 0b79cb52f..79a8277bf 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -1491,12 +1491,15 @@ static void EmitType(EmitContext* context, RefPtr type) static void EmitType(EmitContext* context, TypeExp const& typeExp, Token const& nameToken) { EmitType(context, typeExp.type, - typeExp.exp ? typeExp.exp->Position : CodePosition(), nameToken.Content, nameToken.Position); + typeExp.exp ? typeExp.exp->Position : CodePosition(), + nameToken.Content, nameToken.Position); } static void EmitType(EmitContext* context, TypeExp const& typeExp, String const& name) { - EmitType(context, typeExp.type, typeExp.exp->Position, name, CodePosition()); + EmitType(context, typeExp.type, + typeExp.exp ? typeExp.exp->Position : CodePosition(), + name, CodePosition()); } // Statements diff --git a/source/slang/lower.cpp b/source/slang/lower.cpp index 8a732467c..f9bf97107 100644 --- a/source/slang/lower.cpp +++ b/source/slang/lower.cpp @@ -60,6 +60,7 @@ struct StructuralTransformVisitorBase RefPtr transformSyntaxField(ScopeDecl* decl) { + if(!decl) return nullptr; return visitor->transformSyntaxField(decl).As(); } @@ -263,6 +264,7 @@ struct LoweringVisitor RefPtr lowerType( ExpressionType* type) { + if(!type) return nullptr; return TypeVisitor::dispatch(type); } @@ -456,12 +458,11 @@ struct LoweringVisitor // Statements // - StatementSyntaxNode* translateStmtRef( - StatementSyntaxNode*) - { - throw "unimplemented"; - } - + // Lowering one statement to another. + // The source statement might desugar into multiple statements, + // (or event to none), and in such a case this function wraps + // the result up as a `SeqStmt` or `EmptyStmt` as appropriate. + // RefPtr lowerStmt( StatementSyntaxNode* stmt) { @@ -483,6 +484,37 @@ struct LoweringVisitor } } + + // Structure to track "outer" statements during lowering + struct StmtLoweringState + { + // The next "outer" statement entry + StmtLoweringState* parent = nullptr; + + // The outer statement (both lowered and original) + StatementSyntaxNode* loweredStmt = nullptr; + StatementSyntaxNode* originalStmt = nullptr; + }; + StmtLoweringState stmtLoweringState; + + // Translate a reference from one statement to an outer statement + StatementSyntaxNode* translateStmtRef( + StatementSyntaxNode* originalStmt) + { + if(!originalStmt) return nullptr; + + for( auto state = &stmtLoweringState; state; state = state->parent ) + { + if(state->originalStmt == originalStmt) + return state->loweredStmt; + } + + assert(!"unexepcted"); + + return nullptr; + } + + // Expand a statement to be lowered into one or more statements void lowerStmtImpl( StatementSyntaxNode* stmt) { @@ -498,14 +530,17 @@ struct LoweringVisitor LoweringVisitor pushScope( RefPtr loweredStmt, - RefPtr stmt) + RefPtr originalStmt) { - loweredStmt->scopeDecl = translateDeclRef(stmt->scopeDecl).As(); + loweredStmt->scopeDecl = translateDeclRef(originalStmt->scopeDecl).As(); LoweringVisitor subVisitor = *this; subVisitor.isBuildingStmt = true; subVisitor.stmtBeingBuilt = nullptr; subVisitor.parentDecl = loweredStmt->scopeDecl; + subVisitor.stmtLoweringState.parent = &stmtLoweringState; + subVisitor.stmtLoweringState.originalStmt = originalStmt; + subVisitor.stmtLoweringState.loweredStmt = loweredStmt; return subVisitor; } @@ -562,11 +597,11 @@ struct LoweringVisitor void visit(BlockStmt* stmt) { RefPtr loweredStmt = new BlockStmt(); + lowerScopeStmtFields(loweredStmt, stmt); LoweringVisitor subVisitor = pushScope(loweredStmt, stmt); - subVisitor.stmtBeingBuilt = loweredStmt; - subVisitor.lowerStmtImpl(stmt->body); + loweredStmt->body = subVisitor.lowerStmt(stmt->body); addStmt(loweredStmt); } @@ -589,10 +624,152 @@ struct LoweringVisitor DeclVisitor::dispatch(stmt->decl); } - // catch-all - void visit(StatementSyntaxNode* stmt) + void lowerStmtFields( + StatementSyntaxNode* loweredStmt, + StatementSyntaxNode* originalStmt) + { + loweredStmt->Position = originalStmt->Position; + loweredStmt->modifiers = originalStmt->modifiers; + } + + void lowerScopeStmtFields( + ScopeStmt* loweredStmt, + ScopeStmt* originalStmt) + { + lowerStmtFields(loweredStmt, originalStmt); + loweredStmt->scopeDecl = translateDeclRef(originalStmt->scopeDecl).As(); + } + + // Child statements reference their parent statement, + // so we need to translate that cross-reference + void lowerChildStmtFields( + ChildStmt* loweredStmt, + ChildStmt* originalStmt) + { + lowerStmtFields(loweredStmt, originalStmt); + + loweredStmt->parentStmt = translateStmtRef(originalStmt->parentStmt); + } + + void visit(ContinueStatementSyntaxNode* stmt) + { + RefPtr loweredStmt = new ContinueStatementSyntaxNode(); + lowerChildStmtFields(loweredStmt, stmt); + addStmt(loweredStmt); + } + + void visit(BreakStatementSyntaxNode* stmt) + { + RefPtr loweredStmt = new BreakStatementSyntaxNode(); + lowerChildStmtFields(loweredStmt, stmt); + addStmt(loweredStmt); + } + + void visit(DefaultStmt* stmt) + { + RefPtr loweredStmt = new DefaultStmt(); + lowerChildStmtFields(loweredStmt, stmt); + addStmt(loweredStmt); + } + + void visit(DiscardStatementSyntaxNode* stmt) + { + RefPtr loweredStmt = new DiscardStatementSyntaxNode(); + lowerStmtFields(loweredStmt, stmt); + addStmt(loweredStmt); + } + + void visit(EmptyStatementSyntaxNode* stmt) + { + RefPtr loweredStmt = new EmptyStatementSyntaxNode(); + lowerStmtFields(loweredStmt, stmt); + addStmt(loweredStmt); + } + + void visit(UnparsedStmt* stmt) { - auto loweredStmt = structuralTransform(stmt, this); + RefPtr loweredStmt = new UnparsedStmt(); + lowerStmtFields(loweredStmt, stmt); + + loweredStmt->tokens = stmt->tokens; + + addStmt(loweredStmt); + } + + void visit(CaseStmt* stmt) + { + RefPtr loweredStmt = new CaseStmt(); + lowerChildStmtFields(loweredStmt, stmt); + + loweredStmt->expr = lowerExpr(stmt->expr); + + addStmt(loweredStmt); + } + + void visit(IfStatementSyntaxNode* stmt) + { + RefPtr loweredStmt = new IfStatementSyntaxNode(); + lowerStmtFields(loweredStmt, stmt); + + loweredStmt->Predicate = lowerExpr(stmt->Predicate); + loweredStmt->PositiveStatement = lowerStmt(stmt->PositiveStatement); + loweredStmt->NegativeStatement = lowerStmt(stmt->NegativeStatement); + + addStmt(loweredStmt); + } + + void visit(SwitchStmt* stmt) + { + RefPtr loweredStmt = new SwitchStmt(); + lowerScopeStmtFields(loweredStmt, stmt); + + LoweringVisitor subVisitor = pushScope(loweredStmt, stmt); + + loweredStmt->condition = subVisitor.lowerExpr(stmt->condition); + loweredStmt->body = subVisitor.lowerStmt(stmt->body); + + addStmt(loweredStmt); + } + + + void visit(ForStatementSyntaxNode* stmt) + { + RefPtr loweredStmt = new ForStatementSyntaxNode(); + lowerScopeStmtFields(loweredStmt, stmt); + + LoweringVisitor subVisitor = pushScope(loweredStmt, stmt); + + loweredStmt->InitialStatement = subVisitor.lowerStmt(stmt->InitialStatement); + loweredStmt->SideEffectExpression = subVisitor.lowerExpr(stmt->SideEffectExpression); + loweredStmt->PredicateExpression = subVisitor.lowerExpr(stmt->PredicateExpression); + loweredStmt->Statement = subVisitor.lowerStmt(stmt->Statement); + + addStmt(loweredStmt); + } + + void visit(WhileStatementSyntaxNode* stmt) + { + RefPtr loweredStmt = new WhileStatementSyntaxNode(); + lowerScopeStmtFields(loweredStmt, stmt); + + LoweringVisitor subVisitor = pushScope(loweredStmt, stmt); + + loweredStmt->Predicate = subVisitor.lowerExpr(stmt->Predicate); + loweredStmt->Statement = subVisitor.lowerStmt(stmt->Statement); + + addStmt(loweredStmt); + } + + void visit(DoWhileStatementSyntaxNode* stmt) + { + RefPtr loweredStmt = new DoWhileStatementSyntaxNode(); + lowerScopeStmtFields(loweredStmt, stmt); + + LoweringVisitor subVisitor = pushScope(loweredStmt, stmt); + + loweredStmt->Statement = subVisitor.lowerStmt(stmt->Statement); + loweredStmt->Predicate = subVisitor.lowerExpr(stmt->Predicate); + addStmt(loweredStmt); } -- cgit v1.2.3