summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Foley <tfoley@nvidia.com>2017-06-16 09:09:09 -0700
committerTim Foley <tfoley@nvidia.com>2017-06-16 09:09:09 -0700
commit9ba8ce30f8314a79169e6d9cfa12e5db7239693f (patch)
tree587db9fd5b9920f39104ea6467de59d265188370
parent0bf3d6d4db7409fcd288ff69e75e8e8b4f082969 (diff)
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).
-rw-r--r--source/slang/check.cpp22
-rw-r--r--source/slang/emit.cpp126
-rw-r--r--source/slang/parser.cpp18
-rw-r--r--source/slang/syntax.h7
4 files changed, 111 insertions, 62 deletions
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<VarExpressionSyntaxNode>())
- funcName = baseVar->Variable;
+ funcName = baseVar->name;
else if(auto baseMemberRef = funcExpr.As<MemberExpressionSyntaxNode>())
- 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<InvokeExpressionSyntaxNode> callExpr,
+ int outerPrec)
+{
+ bool needClose = MaybeEmitParens(context, outerPrec, kPrecedence_Postfix);
+
+ auto funcExpr = callExpr->FunctionExpr;
+ if (auto funcDeclRefExpr = funcExpr.As<DeclRefExpr>())
+ {
+ auto declRef = funcDeclRefExpr->declRef;
+ if (auto ctorDeclRef = declRef.As<ConstructorDecl>())
+ {
+ // 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<InvokeExpressionSyntaxNode> callExpr,
@@ -458,7 +503,47 @@ static void emitCallExpr(
{
auto funcDeclRef = funcDeclRefExpr->declRef;
auto funcDecl = funcDeclRef.getDecl();
- if (auto intrinsicOpModifier = funcDecl->FindModifier<IntrinsicOpModifier>())
+ 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<InfixExpr>() )
+ {
+ EmitBinExpr(
+ context,
+ outerPrec,
+ kPrecedence_Comma,
+ funcDeclRefExpr->name.Buffer(),
+ callExpr);
+ }
+ else if( auto prefixExpr = callExpr.As<PrefixExpr>() )
+ {
+ EmitUnaryExpr(
+ context,
+ outerPrec,
+ kPrecedence_Prefix,
+ funcDeclRefExpr->name.Buffer(),
+ "",
+ callExpr);
+ }
+ else if(auto postfixExpr = callExpr.As<PostfixExpr>())
+ {
+ EmitUnaryExpr(
+ context,
+ outerPrec,
+ kPrecedence_Postfix,
+ "",
+ funcDeclRefExpr->name.Buffer(),
+ callExpr);
+ }
+ else
+ {
+ emitSimpleCallExpr(context, callExpr, outerPrec);
+ }
+ return;
+ }
+ else if (auto intrinsicOpModifier = funcDecl->FindModifier<IntrinsicOpModifier>())
{
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<DeclRefExpr>())
- {
- auto declRef = funcDeclRefExpr->declRef;
- if (auto ctorDeclRef = declRef.As<ConstructorDecl>())
- {
- // 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<ExpressionSyntaxNode> expr, int outerPrec)
@@ -761,7 +811,7 @@ static void EmitExprWithPrecedence(EmitContext* context, RefPtr<ExpressionSyntax
}
else
{
- emitName(context, varExpr->Variable);
+ emitName(context, varExpr->name);
}
}
else if (auto derefExpr = expr.As<DerefExpr>())
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<ExpressionSyntaxNode> 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<Decl> 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<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
};
@@ -1984,7 +1984,6 @@ namespace Slang
{
public:
RefPtr<ExpressionSyntaxNode> BaseExpression;
- String MemberName;
virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
};