From 9ba8ce30f8314a79169e6d9cfa12e5db7239693f Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Fri, 16 Jun 2017 09:09:09 -0700 Subject: Bug fix: handle unchecked operator application in emit logic When in rewriter mode, the emit logic will never see function applications inside function bodies, but it *will* see function application expressions at global scope, and some of these expressions might be unchecked. The challenge here is that even simple math operations now show up as function calls, so we need a bit of special-case logic to detect unchecked calls and then emit them using the syntax they were written with (e.g., use infix syntax if they were written as an infix expression). --- source/slang/check.cpp | 22 ++++----- source/slang/emit.cpp | 126 +++++++++++++++++++++++++++++++++--------------- source/slang/parser.cpp | 18 +++---- source/slang/syntax.h | 7 ++- 4 files changed, 111 insertions(+), 62 deletions(-) (limited to 'source') diff --git a/source/slang/check.cpp b/source/slang/check.cpp index 7d101d070..0827641d1 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -119,7 +119,7 @@ namespace Slang auto expr = new MemberExpressionSyntaxNode(); expr->Position = originalExpr->Position; expr->BaseExpression = baseExpr; - expr->MemberName = declRef.GetName(); + expr->name = declRef.GetName(); expr->Type = GetTypeForDeclRef(declRef); expr->declRef = declRef; return expr; @@ -128,7 +128,7 @@ namespace Slang { auto expr = new VarExpressionSyntaxNode(); expr->Position = originalExpr->Position; - expr->Variable = declRef.GetName(); + expr->name = declRef.GetName(); expr->Type = GetTypeForDeclRef(declRef); expr->declRef = declRef; return expr; @@ -4207,9 +4207,9 @@ namespace Slang String funcName; if (auto baseVar = funcExpr.As()) - funcName = baseVar->Variable; + funcName = baseVar->name; else if(auto baseMemberRef = funcExpr.As()) - funcName = baseMemberRef->MemberName; + funcName = baseMemberRef->name; String argsList = GetCallSignatureString(expr); @@ -4547,7 +4547,7 @@ namespace Slang expr->Type = ExpressionType::Error; - auto lookupResult = LookUp(expr->Variable, expr->scope); + auto lookupResult = LookUp(expr->name, expr->scope); if (lookupResult.isValid()) { return createLookupResultExpr( @@ -4556,7 +4556,7 @@ namespace Slang expr); } - getSink()->diagnose(expr, Diagnostics::undefinedIdentifier2, expr->Variable); + getSink()->diagnose(expr, Diagnostics::undefinedIdentifier2, expr->name); return expr; } @@ -4674,9 +4674,9 @@ namespace Slang bool anyDuplicates = false; bool anyError = false; - for (int i = 0; i < memberRefExpr->MemberName.Length(); i++) + for (int i = 0; i < memberRefExpr->name.Length(); i++) { - auto ch = memberRefExpr->MemberName[i]; + auto ch = memberRefExpr->name[i]; int elementIndex = -1; switch (ch) { @@ -4798,7 +4798,7 @@ namespace Slang EnsureDecl(aggTypeDeclRef.getDecl(), DeclCheckState::Checked); - LookupResult lookupResult = LookUpLocal(expr->MemberName, aggTypeDeclRef); + LookupResult lookupResult = LookUpLocal(expr->name, aggTypeDeclRef); if (!lookupResult.isValid()) { goto fail; @@ -4894,7 +4894,7 @@ namespace Slang // catch-all fail: - getSink()->diagnose(expr, Diagnostics::noMemberOfNameInType, expr->MemberName, baseType); + getSink()->diagnose(expr, Diagnostics::noMemberOfNameInType, expr->name, baseType); expr->Type = ExpressionType::Error; return expr; } @@ -4906,7 +4906,7 @@ namespace Slang if (!baseType->Equals(ExpressionType::Error.Ptr()) && expr->Type->Equals(ExpressionType::Error.Ptr())) { - getSink()->diagnose(expr, Diagnostics::typeHasNoPublicMemberOfName, baseType, expr->MemberName); + getSink()->diagnose(expr, Diagnostics::typeHasNoPublicMemberOfName, baseType, expr->name); } return expr; } diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index a2a1e9e21..ef5df830f 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -448,6 +448,51 @@ static String getStringOrIdentifierTokenValue( } } +// Emit a call expression that doesn't involve any special cases, +// just an expression of the form `f(a0, a1, ...)` +static void emitSimpleCallExpr( + EmitContext* context, + RefPtr callExpr, + int outerPrec) +{ + bool needClose = MaybeEmitParens(context, outerPrec, kPrecedence_Postfix); + + auto funcExpr = callExpr->FunctionExpr; + if (auto funcDeclRefExpr = funcExpr.As()) + { + auto declRef = funcDeclRefExpr->declRef; + if (auto ctorDeclRef = declRef.As()) + { + // We really want to emit a reference to the type begin constructed + EmitType(context, callExpr->Type); + } + else + { + // default case: just emit the decl ref + EmitExpr(context, funcExpr); + } + } + else + { + // default case: just emit the expression + EmitPostfixExpr(context, funcExpr); + } + + Emit(context, "("); + int argCount = callExpr->Arguments.Count(); + for (int aa = 0; aa < argCount; ++aa) + { + if (aa != 0) Emit(context, ", "); + EmitExpr(context, callExpr->Arguments[aa]); + } + Emit(context, ")"); + + if (needClose) + { + Emit(context, ")"); + } +} + static void emitCallExpr( EmitContext* context, RefPtr callExpr, @@ -458,7 +503,47 @@ static void emitCallExpr( { auto funcDeclRef = funcDeclRefExpr->declRef; auto funcDecl = funcDeclRef.getDecl(); - if (auto intrinsicOpModifier = funcDecl->FindModifier()) + if(!funcDecl) + { + // This can occur when we are dealing with unchecked input syntax, + // because we are in "rewriter" mode. In this case we should go + // ahead and emit things in the form that they were written. + if( auto infixExpr = callExpr.As() ) + { + EmitBinExpr( + context, + outerPrec, + kPrecedence_Comma, + funcDeclRefExpr->name.Buffer(), + callExpr); + } + else if( auto prefixExpr = callExpr.As() ) + { + EmitUnaryExpr( + context, + outerPrec, + kPrecedence_Prefix, + funcDeclRefExpr->name.Buffer(), + "", + callExpr); + } + else if(auto postfixExpr = callExpr.As()) + { + EmitUnaryExpr( + context, + outerPrec, + kPrecedence_Postfix, + "", + funcDeclRefExpr->name.Buffer(), + callExpr); + } + else + { + emitSimpleCallExpr(context, callExpr, outerPrec); + } + return; + } + else if (auto intrinsicOpModifier = funcDecl->FindModifier()) { switch (intrinsicOpModifier->op) { @@ -641,42 +726,7 @@ static void emitCallExpr( } // Fall through to default handling... - - bool needClose = MaybeEmitParens(context, outerPrec, kPrecedence_Postfix); - - if (auto funcDeclRefExpr = funcExpr.As()) - { - auto declRef = funcDeclRefExpr->declRef; - if (auto ctorDeclRef = declRef.As()) - { - // We really want to emit a reference to the type begin constructed - EmitType(context, callExpr->Type); - } - else - { - // default case: just emit the decl ref - EmitExpr(context, funcExpr); - } - } - else - { - // default case: just emit the expression - EmitPostfixExpr(context, funcExpr); - } - - Emit(context, "("); - int argCount = callExpr->Arguments.Count(); - for (int aa = 0; aa < argCount; ++aa) - { - if (aa != 0) Emit(context, ", "); - EmitExpr(context, callExpr->Arguments[aa]); - } - Emit(context, ")"); - - if (needClose) - { - Emit(context, ")"); - } + emitSimpleCallExpr(context, callExpr, outerPrec); } static void EmitExprWithPrecedence(EmitContext* context, RefPtr expr, int outerPrec) @@ -761,7 +811,7 @@ static void EmitExprWithPrecedence(EmitContext* context, RefPtrVariable); + emitName(context, varExpr->name); } } else if (auto derefExpr = expr.As()) diff --git a/source/slang/parser.cpp b/source/slang/parser.cpp index 29b02f816..b8997b1d7 100644 --- a/source/slang/parser.cpp +++ b/source/slang/parser.cpp @@ -1302,7 +1302,7 @@ namespace Slang auto expr = new VarExpressionSyntaxNode(); expr->scope = parser->currentScope.Ptr(); expr->Position = decl->getNameToken().Position; - expr->Variable = decl->getName(); + expr->name = decl->getName(); return expr; } @@ -1347,7 +1347,7 @@ namespace Slang auto basicType = new VarExpressionSyntaxNode(); basicType->scope = parser->currentScope.Ptr(); basicType->Position = typeName.Position; - basicType->Variable = typeName.Content; + basicType->name = typeName.Content; RefPtr typeExpr = basicType; @@ -1659,13 +1659,13 @@ namespace Slang // Construct a type expression to reference the buffer data type auto bufferDataTypeExpr = new VarExpressionSyntaxNode(); bufferDataTypeExpr->Position = bufferDataTypeDecl->Position; - bufferDataTypeExpr->Variable = bufferDataTypeDecl->Name.Content; + bufferDataTypeExpr->name = bufferDataTypeDecl->Name.Content; bufferDataTypeExpr->scope = parser->currentScope.Ptr(); // Construct a type exrpession to reference the type constructor auto bufferWrapperTypeExpr = new VarExpressionSyntaxNode(); bufferWrapperTypeExpr->Position = bufferWrapperTypeNamePos; - bufferWrapperTypeExpr->Variable = bufferWrapperTypeName; + bufferWrapperTypeExpr->name = bufferWrapperTypeName; // Always need to look this up in the outer scope, // so that it won't collide with, e.g., a local variable called `ConstantBuffer` @@ -1812,13 +1812,13 @@ namespace Slang // Construct a type expression to reference the buffer data type auto blockDataTypeExpr = new VarExpressionSyntaxNode(); blockDataTypeExpr->Position = blockDataTypeDecl->Position; - blockDataTypeExpr->Variable = blockDataTypeDecl->Name.Content; + blockDataTypeExpr->name = blockDataTypeDecl->Name.Content; blockDataTypeExpr->scope = parser->currentScope.Ptr(); // Construct a type exrpession to reference the type constructor auto blockWrapperTypeExpr = new VarExpressionSyntaxNode(); blockWrapperTypeExpr->Position = pos; - blockWrapperTypeExpr->Variable = blockWrapperTypeName; + blockWrapperTypeExpr->name = blockWrapperTypeName; // Always need to look this up in the outer scope, // so that it won't collide with, e.g., a local variable called `ConstantBuffer` blockWrapperTypeExpr->scope = parser->outerScope; @@ -2894,7 +2894,7 @@ parser->ReadToken(TokenType::Comma); } auto opExpr = new VarExpressionSyntaxNode(); - opExpr->Variable = opToken.Content; + opExpr->name = opToken.Content; opExpr->scope = parser->currentScope; opExpr->Position = opToken.Position; @@ -3060,7 +3060,7 @@ parser->ReadToken(TokenType::Comma); varExpr->scope = currentScope.Ptr(); FillPosition(varExpr.Ptr()); auto token = ReadToken(TokenType::Identifier); - varExpr->Variable = token.Content; + varExpr->name = token.Content; rs = varExpr; } @@ -3125,7 +3125,7 @@ parser->ReadToken(TokenType::Comma); FillPosition(memberExpr.Ptr()); memberExpr->BaseExpression = rs; ReadToken(TokenType::Dot); - memberExpr->MemberName = ReadToken(TokenType::Identifier).Content; + memberExpr->name = ReadToken(TokenType::Identifier).Content; rs = memberExpr; } } diff --git a/source/slang/syntax.h b/source/slang/syntax.h index 9f93c305c..56574d124 100644 --- a/source/slang/syntax.h +++ b/source/slang/syntax.h @@ -1784,14 +1784,14 @@ namespace Slang // The declaration of the symbol being referenced DeclRef declRef; + + // The name of the symbol being referenced + String name; }; class VarExpressionSyntaxNode : public DeclRefExpr { public: - // The name of the symbol being referenced - String Variable; - virtual RefPtr Accept(SyntaxVisitor * visitor) override; }; @@ -1984,7 +1984,6 @@ namespace Slang { public: RefPtr BaseExpression; - String MemberName; virtual RefPtr Accept(SyntaxVisitor * visitor) override; }; -- cgit v1.2.3