From 2ac2fe70fbdf50e69c942a0ff36f6ee5224deaf9 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Mon, 4 Jan 2021 06:33:39 -0800 Subject: [PATCH] Fixed string interpolation scoping, {{ }} escaping --- IDEHelper/Compiler/BfAst.cpp | 5 +++ IDEHelper/Compiler/BfAst.h | 8 ++++ IDEHelper/Compiler/BfExprEvaluator.cpp | 4 +- IDEHelper/Compiler/BfModule.h | 4 +- IDEHelper/Compiler/BfParser.cpp | 53 ++++++++++++++++---------- IDEHelper/Compiler/BfStmtEvaluator.cpp | 19 +++++++-- IDEHelper/Compiler/BfSystem.cpp | 5 --- 7 files changed, 67 insertions(+), 31 deletions(-) diff --git a/IDEHelper/Compiler/BfAst.cpp b/IDEHelper/Compiler/BfAst.cpp index b1b3819f..2511fc3d 100644 --- a/IDEHelper/Compiler/BfAst.cpp +++ b/IDEHelper/Compiler/BfAst.cpp @@ -651,6 +651,11 @@ void BfStructuralVisitor::Visit(BfBlock* block) Visit(block->ToBase()); } +void BfStructuralVisitor::Visit(BfUnscopedBlock* block) +{ + Visit(block->ToBase()); +} + void BfStructuralVisitor::Visit(BfBlockExtension* block) { BF_ASSERT("Shouldn't see this block, BfBlock::Iterator not being used?"); diff --git a/IDEHelper/Compiler/BfAst.h b/IDEHelper/Compiler/BfAst.h index fb2d4c11..7ef1426a 100644 --- a/IDEHelper/Compiler/BfAst.h +++ b/IDEHelper/Compiler/BfAst.h @@ -266,6 +266,7 @@ class BfAttributedStatement; class BfLiteralExpression; class BfStringInterpolationExpression; class BfBlock; +class BfUnscopedBlock; class BfBlockExtension; class BfRootNode; class BfErrorNode; @@ -545,6 +546,7 @@ public: virtual void Visit(BfUsingModDirective* usingDirective); virtual void Visit(BfNamespaceDeclaration* namespaceDeclaration); virtual void Visit(BfBlock* block); + virtual void Visit(BfUnscopedBlock* block); virtual void Visit(BfBlockExtension* block); virtual void Visit(BfRootNode* rootNode); virtual void Visit(BfInlineAsmStatement* asmStmt); @@ -1721,6 +1723,12 @@ public: } }; BF_AST_DECL(BfBlock, BfExpression); +class BfUnscopedBlock : public BfBlock +{ +public: + BF_AST_TYPE(BfUnscopedBlock, BfBlock); +}; BF_AST_DECL(BfUnscopedBlock, BfBlock); + class BfTypedValueExpression : public BfExpression { public: diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 99bfd563..20e10f3b 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -2856,7 +2856,7 @@ void BfExprEvaluator::Visit(BfBlock* blockExpr) if (!lastExpr->IsMissingSemicolon()) mModule->Fail("Expression blocks must end in an expression which is missing its terminating semicolon", lastExpr->mTrailingSemicolon); } - else if (auto lastExpr = BfNodeDynCast(blockExpr->mChildArr.GetLast())) + else if (blockExpr->mChildArr.GetLast()->IsExpression()) { // Expression } @@ -2865,7 +2865,7 @@ void BfExprEvaluator::Visit(BfBlock* blockExpr) mModule->Fail("Expression blocks must end with an expression", blockExpr); } - mModule->VisitEmbeddedStatement(blockExpr, this); + mModule->VisitEmbeddedStatement(blockExpr, this, BfNodeIsA(blockExpr) ? BfEmbeddedStatementFlags_Unscoped : BfEmbeddedStatementFlags_None); } bool BfExprEvaluator::CheckVariableDeclaration(BfAstNode* checkNode, bool requireSimpleIfExpr, bool exprMustBeTrue, bool silentFail) diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index 0a35157e..2e32d8d6 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -121,7 +121,8 @@ enum BfEmbeddedStatementFlags { BfEmbeddedStatementFlags_None = 0, BfEmbeddedStatementFlags_IsConditional = 1, - BfEmbeddedStatementFlags_IsDeferredBlock = 2 + BfEmbeddedStatementFlags_IsDeferredBlock = 2, + BfEmbeddedStatementFlags_Unscoped = 4 }; enum BfLocalVarAssignKind @@ -1653,6 +1654,7 @@ public: virtual void Visit(BfForEachStatement* forEachStmt) override; virtual void Visit(BfDeferStatement* deferStmt) override; virtual void Visit(BfBlock* block) override; + virtual void Visit(BfUnscopedBlock* block) override; virtual void Visit(BfLabeledBlock* labeledBlock) override; virtual void Visit(BfRootNode* rootNode) override; virtual void Visit(BfInlineAsmStatement* asmStmt) override; diff --git a/IDEHelper/Compiler/BfParser.cpp b/IDEHelper/Compiler/BfParser.cpp index e85f5b1f..50a496bc 100644 --- a/IDEHelper/Compiler/BfParser.cpp +++ b/IDEHelper/Compiler/BfParser.cpp @@ -1707,7 +1707,7 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate) case '"': case '\'': { - SizedArray interpolateExpressions; + SizedArray interpolateExpressions; String lineHeader; String strLiteral; @@ -2013,31 +2013,44 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate) { if (c == '{') { - BfBlock* newBlock = mAlloc->Alloc(); - mTokenStart = mSrcIdx - 1; - mTriviaStart = mTokenStart; - mTokenEnd = mTokenStart + 1; - mToken = BfToken_LBrace; - newBlock->mOpenBrace = (BfTokenNode*)CreateNode(); - newBlock->Init(this); - ParseBlock(newBlock, 1, true); - if (mToken == BfToken_RBrace) + if (mSrc[mSrcIdx] == '{') { - newBlock->mCloseBrace = (BfTokenNode*)CreateNode(); - newBlock->SetSrcEnd(mSrcIdx); - strLiteral += "}"; + strLiteral += '{'; + mSrcIdx++; } - else if ((mSyntaxToken == BfSyntaxToken_EOF) || (mSyntaxToken == BfSyntaxToken_StringQuote)) + else { - mSrcIdx--; - mPassInstance->FailAfterAt("Expected '}'", mSourceData, newBlock->GetSrcEnd() - 1); - } - mInAsmBlock = false; - interpolateExpressions.Add(newBlock); + BfUnscopedBlock* newBlock = mAlloc->Alloc(); + mTokenStart = mSrcIdx - 1; + mTriviaStart = mTokenStart; + mTokenEnd = mTokenStart + 1; + mToken = BfToken_LBrace; + newBlock->mOpenBrace = (BfTokenNode*)CreateNode(); + newBlock->Init(this); + ParseBlock(newBlock, 1, true); + if (mToken == BfToken_RBrace) + { + newBlock->mCloseBrace = (BfTokenNode*)CreateNode(); + newBlock->SetSrcEnd(mSrcIdx); + strLiteral += "}"; + } + else if ((mSyntaxToken == BfSyntaxToken_EOF) || (mSyntaxToken == BfSyntaxToken_StringQuote)) + { + mSrcIdx--; + mPassInstance->FailAfterAt("Expected '}'", mSourceData, newBlock->GetSrcEnd() - 1); + } + mInAsmBlock = false; + interpolateExpressions.Add(newBlock); + } } else if (c == '}') { - if (!interpolateExpressions.IsEmpty()) + if (mSrc[mSrcIdx] == '}') + { + strLiteral += '}'; + mSrcIdx++; + } + else if (!interpolateExpressions.IsEmpty()) { auto block = interpolateExpressions.back(); if (block->mCloseBrace == NULL) diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index 753d473c..643d1898 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -3090,15 +3090,23 @@ void BfModule::VisitEmbeddedStatement(BfAstNode* stmt, BfExprEvaluator* exprEval if ((block != NULL) && (openBrace != NULL)) UpdateSrcPos(openBrace); - if (mCurMethodState != NULL) + + if ((flags & BfEmbeddedStatementFlags_Unscoped) != 0) { - bool isIgnore = mBfIRBuilder->mIgnoreWrites; + SetAndRestoreValue prevExprEvaluator(mCurMethodState->mCurScope->mExprEvaluator, exprEvaluator); + + VisitCodeBlock(block); + } + else if (mCurMethodState != NULL) + { + bool isIgnore = mBfIRBuilder->mIgnoreWrites; mCurMethodState->mInHeadScope = false; BfScopeData scopeData; if (IsTargetingBeefBackend()) scopeData.mValueScopeStart = mBfIRBuilder->CreateValueScopeStart(); + mCurMethodState->AddScope(&scopeData); if (block != NULL) { @@ -3391,7 +3399,7 @@ void BfModule::VisitCodeBlock(BfBlock* block) } else { - FailAfter("Expression block cannot be used here. Consider adding semicolon if a statement was intended.", expr); + FailAfter("Expression block cannot be used here. Consider adding semicolon if a statement was intended.", expr); } } } @@ -6843,6 +6851,11 @@ void BfModule::Visit(BfBlock* block) VisitEmbeddedStatement(block); } +void BfModule::Visit(BfUnscopedBlock* block) +{ + VisitEmbeddedStatement(block, NULL, BfEmbeddedStatementFlags_Unscoped); +} + void BfModule::Visit(BfLabeledBlock* labeledBlock) { VisitEmbeddedStatement(labeledBlock); diff --git a/IDEHelper/Compiler/BfSystem.cpp b/IDEHelper/Compiler/BfSystem.cpp index 06bc95b6..2c0000af 100644 --- a/IDEHelper/Compiler/BfSystem.cpp +++ b/IDEHelper/Compiler/BfSystem.cpp @@ -3012,11 +3012,6 @@ void BfSystem::FinishCompositePartial(BfTypeDef* compositeTypeDef) // methodDef->mIsMutating = true; // } - if (compositeTypeDef->mName->ToString() == "Core") - { - NOP; - } - // Static ctor if ((allHasMethods[0][1].mCtor == 0) && (allHasMethods[1][1].mCtor > 1)) {