summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Foley <tfoley@nvidia.com>2017-07-07 14:30:26 -0700
committerTim Foley <tfoley@nvidia.com>2017-07-08 18:18:36 -0700
commitf69bc6cdb10aab2d1b202668cb7ecbcc0ddf33f2 (patch)
tree21d5e647382c60a164c0b1c8c570dbcf5b1ac3f4
parentf3fe9dddb8c528b4f9955d9105908600b4a8d0c8 (diff)
Fully parse function bodies, even in "rewriter" mode
This is in anticipation of needing to have more complete knowledge to be able to handle user code that `import`s library functionality. The big picture of this change is just to remove the `UnparsedStmt` class that was used to hold the bodies of user functions as opaque token streams, and thus to let the full parser and compiler loose on that code. That is the easy part, of course, and the hard part is all the fixes that this requires in the rest of the compielr to make this even remotely work. Subsequent commit address a lot of other issues, so this particular commit mostly represents work-in-progress. One detail is that this change puts a conditional around nearly every diagnostic message in `check.cpp` to suppress thing when in rewriter mode. I have yet to check how that works out if there are errors in anything we actually need to understand for the purposes of generating reflection data.
-rw-r--r--source/slang/check.cpp419
-rw-r--r--source/slang/emit.cpp166
-rw-r--r--source/slang/expr-defs.h10
-rw-r--r--source/slang/intrinsic-defs.h1
-rw-r--r--source/slang/lexer.cpp6
-rw-r--r--source/slang/lower.cpp11
-rw-r--r--source/slang/parser.cpp185
-rw-r--r--source/slang/slang-stdlib.cpp356
-rw-r--r--source/slang/slang-stdlib.h13
-rw-r--r--source/slang/slang.cpp17
-rw-r--r--source/slang/stmt-defs.h5
-rw-r--r--source/slang/syntax.h17
12 files changed, 647 insertions, 559 deletions
diff --git a/source/slang/check.cpp b/source/slang/check.cpp
index 7c67473be..f21f9480c 100644
--- a/source/slang/check.cpp
+++ b/source/slang/check.cpp
@@ -243,14 +243,16 @@ namespace Slang
if (lookupResult.isOverloaded())
{
// We had an ambiguity anyway, so report it.
- getSink()->diagnose(overloadedExpr, Diagnostics::ambiguousReference, lookupResult.items[0].declRef.GetName());
-
- for(auto item : lookupResult.items)
+ if (!isRewriteMode())
{
- String declString = getDeclSignatureString(item);
- getSink()->diagnose(item.declRef, Diagnostics::overloadCandidate, declString);
- }
+ getSink()->diagnose(overloadedExpr, Diagnostics::ambiguousReference, lookupResult.items[0].declRef.GetName());
+ for(auto item : lookupResult.items)
+ {
+ String declString = getDeclSignatureString(item);
+ getSink()->diagnose(item.declRef, Diagnostics::overloadCandidate, declString);
+ }
+ }
// TODO(tfoley): should we construct a new ErrorExpr here?
overloadedExpr->Type = QualType(ExpressionType::Error);
return overloadedExpr;
@@ -276,9 +278,11 @@ namespace Slang
return expr;
}
- getSink()->diagnose(expr, Diagnostics::unimplemented, "expected a type");
- // TODO: construct some kind of `ErrorExpr`?
- return expr;
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(expr, Diagnostics::unimplemented, "expected a type");
+ }
+ return CreateErrorExpr(expr);
}
RefPtr<ExpressionType> ExpectAType(RefPtr<ExpressionSyntaxNode> expr)
@@ -424,7 +428,10 @@ namespace Slang
{
if (outProperType)
{
- getSink()->diagnose(typeExp.exp.Ptr(), Diagnostics::unimplemented, "can't fill in default for generic type parameter");
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(typeExp.exp.Ptr(), Diagnostics::unimplemented, "can't fill in default for generic type parameter");
+ }
*outProperType = ExpressionType::Error;
}
return false;
@@ -440,7 +447,10 @@ namespace Slang
{
if (outProperType)
{
- getSink()->diagnose(typeExp.exp.Ptr(), Diagnostics::unimplemented, "can't fill in default for generic type parameter");
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(typeExp.exp.Ptr(), Diagnostics::unimplemented, "can't fill in default for generic type parameter");
+ }
*outProperType = ExpressionType::Error;
}
return false;
@@ -511,7 +521,10 @@ namespace Slang
if (basicType->BaseType == BaseType::Void)
{
// TODO(tfoley): pick the right diagnostic message
- getSink()->diagnose(result.exp.Ptr(), Diagnostics::invalidTypeVoid);
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(result.exp.Ptr(), Diagnostics::invalidTypeVoid);
+ }
result.type = ExpressionType::Error;
return result;
}
@@ -634,7 +647,9 @@ namespace Slang
CASE(Int, Signed, Int32);
CASE(UInt, Unsigned, Int32);
CASE(UInt64, Unsigned, Int64);
+ CASE(Half, Float, Int16);
CASE(Float, Float, Int32);
+ CASE(Double, Float, Int64);
CASE(Void, Error, Error);
#undef CASE
@@ -972,7 +987,7 @@ namespace Slang
RefPtr<ExpressionType> toType,
RefPtr<ExpressionSyntaxNode> fromExpr)
{
- auto castExpr = new TypeCastExpressionSyntaxNode();
+ auto castExpr = new ImplicitCastExpr();
castExpr->Position = fromExpr->Position;
castExpr->TargetType.type = toType;
castExpr->Type = QualType(toType);
@@ -980,6 +995,10 @@ namespace Slang
return castExpr;
}
+ bool isRewriteMode()
+ {
+ return (getTranslationUnit()->compileFlags & SLANG_COMPILE_FLAG_NO_CHECKING) != 0;
+ }
// Perform type coercion, and emit errors if it isn't possible
RefPtr<ExpressionSyntaxNode> Coerce(
@@ -990,7 +1009,7 @@ namespace Slang
// expressions without a type, and we need to ignore them.
if( !fromExpr->Type.type )
{
- if(getTranslationUnit()->compileFlags & SLANG_COMPILE_FLAG_NO_CHECKING )
+ if(isRewriteMode())
return fromExpr;
}
@@ -1002,7 +1021,7 @@ namespace Slang
fromExpr.Ptr(),
nullptr))
{
- if(!(getTranslationUnit()->compileFlags & SLANG_COMPILE_FLAG_NO_CHECKING))
+ if(!isRewriteMode())
{
getSink()->diagnose(fromExpr->Position, Diagnostics::typeMismatch, toType, fromExpr->Type);
}
@@ -1041,13 +1060,20 @@ namespace Slang
else
{
// TODO: infer a type from the initializers
+
if (!initExpr)
{
- getSink()->diagnose(varDecl, Diagnostics::unimplemented, "variable declaration with no type must have initializer");
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(varDecl, Diagnostics::unimplemented, "variable declaration with no type must have initializer");
+ }
}
else
{
- getSink()->diagnose(varDecl, Diagnostics::unimplemented, "type inference for variable declaration");
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(varDecl, Diagnostics::unimplemented, "type inference for variable declaration");
+ }
}
}
@@ -1122,7 +1148,10 @@ namespace Slang
// If type expression didn't name an interface, we'll emit an error here
// TODO: deal with the case of an error in the type expression (don't cascade)
- getSink()->diagnose( base.exp, Diagnostics::expectedAnInterfaceGot, base.type);
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose( base.exp, Diagnostics::expectedAnInterfaceGot, base.type);
+ }
}
RefPtr<ConstantIntVal> checkConstantIntVal(
@@ -1138,7 +1167,10 @@ namespace Slang
auto constIntVal = intVal.As<ConstantIntVal>();
if(!constIntVal)
{
- getSink()->diagnose(expr->Position, Diagnostics::expectedIntegerConstantNotLiteral);
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(expr->Position, Diagnostics::expectedIntegerConstantNotLiteral);
+ }
return nullptr;
}
return constIntVal;
@@ -1503,7 +1535,10 @@ namespace Slang
if (!funcDecl->ReturnType.Equals(prevFuncDecl->ReturnType))
{
// Bad dedeclaration
- getSink()->diagnose(funcDecl, Diagnostics::unimplemented, "redeclaration has a different return type");
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(funcDecl, Diagnostics::unimplemented, "redeclaration has a different return type");
+ }
// Don't bother emitting other errors at this point
break;
@@ -1517,7 +1552,10 @@ namespace Slang
if (funcDecl->Body && prevFuncDecl->Body)
{
// Redefinition
- getSink()->diagnose(funcDecl, Diagnostics::unimplemented, "function redefinition");
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(funcDecl, Diagnostics::unimplemented, "function redefinition");
+ }
// Don't bother emitting other errors
break;
@@ -1539,7 +1577,12 @@ namespace Slang
para->Type = CheckUsableType(para->Type);
if (para->Type.Equals(ExpressionType::GetVoid()))
- getSink()->diagnose(para, Diagnostics::parameterCannotBeVoid);
+ {
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(para, Diagnostics::parameterCannotBeVoid);
+ }
+ }
}
void VisitFunctionDeclaration(FunctionSyntaxNode *functionNode)
@@ -1556,7 +1599,12 @@ namespace Slang
checkDecl(para);
if (paraNames.Contains(para->Name.Content))
- getSink()->diagnose(para, Diagnostics::parameterAlreadyDefined, para->Name);
+ {
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(para, Diagnostics::parameterAlreadyDefined, para->Name);
+ }
+ }
else
paraNames.Add(para->Name.Content);
}
@@ -1613,7 +1661,10 @@ namespace Slang
auto outer = FindOuterStmt<BreakableStmt>();
if (!outer)
{
- getSink()->diagnose(stmt, Diagnostics::breakOutsideLoop);
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(stmt, Diagnostics::breakOutsideLoop);
+ }
}
stmt->parentStmt = outer;
}
@@ -1622,7 +1673,10 @@ namespace Slang
auto outer = FindOuterStmt<LoopStmt>();
if (!outer)
{
- getSink()->diagnose(stmt, Diagnostics::continueOutsideLoop);
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(stmt, Diagnostics::continueOutsideLoop);
+ }
}
stmt->parentStmt = outer;
}
@@ -1691,7 +1745,10 @@ namespace Slang
if (!switchStmt)
{
- getSink()->diagnose(stmt, Diagnostics::caseOutsideSwitch);
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(stmt, Diagnostics::caseOutsideSwitch);
+ }
}
else
{
@@ -1707,7 +1764,10 @@ namespace Slang
auto switchStmt = FindOuterStmt<SwitchStmt>();
if (!switchStmt)
{
- getSink()->diagnose(stmt, Diagnostics::defaultOutsideSwitch);
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(stmt, Diagnostics::defaultOutsideSwitch);
+ }
}
stmt->parentStmt = switchStmt;
}
@@ -1718,12 +1778,6 @@ namespace Slang
checkStmt(stmt->NegativeStatement);
}
- void visitUnparsedStmt(UnparsedStmt*)
- {
- // Nothing to do
- }
-
-
void visitEmptyStatementSyntaxNode(EmptyStatementSyntaxNode*)
{
// Nothing to do
@@ -1739,7 +1793,12 @@ namespace Slang
if (!stmt->Expression)
{
if (function && !function->ReturnType.Equals(ExpressionType::GetVoid()))
- getSink()->diagnose(stmt, Diagnostics::returnNeedsExpression);
+ {
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(stmt, Diagnostics::returnNeedsExpression);
+ }
+ }
}
else
{
@@ -1832,7 +1891,10 @@ namespace Slang
// TODO(tfoley): How to handle the case where bound isn't known?
if (GetMinBound(elementCount) <= 0)
{
- getSink()->diagnose(varDecl, Diagnostics::invalidArraySize);
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(varDecl, Diagnostics::invalidArraySize);
+ }
return;
}
}
@@ -1853,7 +1915,12 @@ namespace Slang
#endif
varDecl->Type = typeExp;
if (varDecl->Type.Equals(ExpressionType::GetVoid()))
- getSink()->diagnose(varDecl, Diagnostics::invalidTypeVoid);
+ {
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(varDecl, Diagnostics::invalidTypeVoid);
+ }
+ }
if(auto initExpr = varDecl->Expr)
{
@@ -2160,7 +2227,10 @@ namespace Slang
auto result = TryCheckIntegerConstantExpression(expr.Ptr());
if (!result)
{
- getSink()->diagnose(expr, Diagnostics::expectedIntegerConstantNotConstant);
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(expr, Diagnostics::expectedIntegerConstantNotConstant);
+ }
}
return result;
}
@@ -2177,7 +2247,10 @@ namespace Slang
if (!indexExpr->Type->Equals(ExpressionType::GetInt()) &&
!indexExpr->Type->Equals(ExpressionType::GetUInt()))
{
- getSink()->diagnose(indexExpr, Diagnostics::subscriptIndexNonInteger);
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(indexExpr, Diagnostics::subscriptIndexNonInteger);
+ }
return CreateErrorExpr(subscriptExpr.Ptr());
}
@@ -2320,7 +2393,10 @@ namespace Slang
fail:
{
- getSink()->diagnose(subscriptExpr, Diagnostics::subscriptNonArray, baseType);
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(subscriptExpr, Diagnostics::subscriptNonArray, baseType);
+ }
return CreateErrorExpr(subscriptExpr);
}
}
@@ -2419,6 +2495,16 @@ namespace Slang
return appExpr;
}
+ RefPtr<ExpressionSyntaxNode> visitParenExpr(ParenExpr* expr)
+ {
+ auto base = expr->base;
+ base = CheckTerm(base);
+
+ expr->base = base;
+ expr->Type = base->Type;
+ return expr;
+ }
+
//
RefPtr<ExpressionSyntaxNode> visitAssignExpr(AssignExpr* expr)
@@ -2431,7 +2517,10 @@ namespace Slang
if (!type.IsLeftValue)
{
- getSink()->diagnose(expr, Diagnostics::assignNonLValue);
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(expr, Diagnostics::assignNonLValue);
+ }
}
expr->Type = type;
return expr;
@@ -2460,7 +2549,10 @@ namespace Slang
}
else
{
- getSink()->diagnose(decl->targetType.exp, Diagnostics::unimplemented, "expected a nominal type here");
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(decl->targetType.exp, Diagnostics::unimplemented, "expected a nominal type here");
+ }
}
}
else if (decl->targetType->Equals(ExpressionType::Error))
@@ -2469,7 +2561,10 @@ namespace Slang
}
else
{
- getSink()->diagnose(decl->targetType.exp, Diagnostics::unimplemented, "expected a nominal type here");
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(decl->targetType.exp, Diagnostics::unimplemented, "expected a nominal type here");
+ }
}
decl->SetCheckState(DeclCheckState::CheckedHeader);
@@ -3073,12 +3168,18 @@ namespace Slang
{
if (argCount < paramCounts.required)
{
- getSink()->diagnose(context.appExpr, Diagnostics::notEnoughArguments, argCount, paramCounts.required);
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(context.appExpr, Diagnostics::notEnoughArguments, argCount, paramCounts.required);
+ }
}
else
{
assert(argCount > paramCounts.allowed);
- getSink()->diagnose(context.appExpr, Diagnostics::tooManyArguments, argCount, paramCounts.allowed);
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(context.appExpr, Diagnostics::tooManyArguments, argCount, paramCounts.allowed);
+ }
}
}
@@ -3100,8 +3201,11 @@ namespace Slang
if (context.mode != OverloadResolveContext::Mode::JustTrying)
{
- getSink()->diagnose(context.appExpr, Diagnostics::expectedPrefixOperator);
- getSink()->diagnose(decl, Diagnostics::seeDefinitionOf, decl->getName());
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(context.appExpr, Diagnostics::expectedPrefixOperator);
+ getSink()->diagnose(decl, Diagnostics::seeDefinitionOf, decl->getName());
+ }
}
return false;
@@ -3113,8 +3217,11 @@ namespace Slang
if (context.mode != OverloadResolveContext::Mode::JustTrying)
{
- getSink()->diagnose(context.appExpr, Diagnostics::expectedPostfixOperator);
- getSink()->diagnose(decl, Diagnostics::seeDefinitionOf, decl->getName());
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(context.appExpr, Diagnostics::expectedPostfixOperator);
+ getSink()->diagnose(decl, Diagnostics::seeDefinitionOf, decl->getName());
+ }
}
return false;
@@ -3311,13 +3418,16 @@ namespace Slang
if (candidate.status == OverloadCandidate::Status::GenericArgumentInferenceFailed)
{
String callString = GetCallSignatureString(context.appExpr);
- getSink()->diagnose(
- context.appExpr,
- Diagnostics::genericArgumentInferenceFailed,
- callString);
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(
+ context.appExpr,
+ Diagnostics::genericArgumentInferenceFailed,
+ callString);
- String declString = getDeclSignatureString(candidate.item);
- getSink()->diagnose(candidate.item.declRef, Diagnostics::genericSignatureTried, declString);
+ String declString = getDeclSignatureString(candidate.item);
+ getSink()->diagnose(candidate.item.declRef, Diagnostics::genericSignatureTried, declString);
+ }
goto error;
}
@@ -4223,6 +4333,14 @@ namespace Slang
{
return CreateErrorExpr(expr);
}
+ // If any of the arguments is an error, then we should bail out, to avoid
+ // cascading errors where we successfully pick an overload, but not the one
+ // the user meant.
+ for (auto arg : expr->Arguments)
+ {
+ if (IsErrorExpr(arg))
+ return CreateErrorExpr(expr);
+ }
OverloadResolveContext context;
context.appExpr = expr;
@@ -4268,11 +4386,17 @@ namespace Slang
// We will construct a diagnostic message to help out.
if (funcName.Length() != 0)
{
- getSink()->diagnose(expr, Diagnostics::noApplicableOverloadForNameWithArgs, funcName, argsList);
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(expr, Diagnostics::noApplicableOverloadForNameWithArgs, funcName, argsList);
+ }
}
else
{
- getSink()->diagnose(expr, Diagnostics::noApplicableWithArgs, argsList);
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(expr, Diagnostics::noApplicableWithArgs, argsList);
+ }
}
}
else
@@ -4281,32 +4405,41 @@ namespace Slang
if (funcName.Length() != 0)
{
- getSink()->diagnose(expr, Diagnostics::ambiguousOverloadForNameWithArgs, funcName, argsList);
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(expr, Diagnostics::ambiguousOverloadForNameWithArgs, funcName, argsList);
+ }
}
else
{
- getSink()->diagnose(expr, Diagnostics::ambiguousOverloadWithArgs, argsList);
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(expr, Diagnostics::ambiguousOverloadWithArgs, argsList);
+ }
}
}
- UInt candidateCount = context.bestCandidates.Count();
- UInt maxCandidatesToPrint = 10; // don't show too many candidates at once...
- UInt candidateIndex = 0;
- for (auto candidate : context.bestCandidates)
+ if (!isRewriteMode())
{
- String declString = getDeclSignatureString(candidate.item);
+ UInt candidateCount = context.bestCandidates.Count();
+ UInt maxCandidatesToPrint = 10; // don't show too many candidates at once...
+ UInt candidateIndex = 0;
+ for (auto candidate : context.bestCandidates)
+ {
+ String declString = getDeclSignatureString(candidate.item);
- declString = declString + "[" + String(candidate.conversionCostSum) + "]";
+ declString = declString + "[" + String(candidate.conversionCostSum) + "]";
- getSink()->diagnose(candidate.item.declRef, Diagnostics::overloadCandidate, declString);
+ getSink()->diagnose(candidate.item.declRef, Diagnostics::overloadCandidate, declString);
- candidateIndex++;
- if (candidateIndex == maxCandidatesToPrint)
- break;
- }
- if (candidateIndex != candidateCount)
- {
- getSink()->diagnose(expr, Diagnostics::moreOverloadCandidates, candidateCount - candidateIndex);
+ candidateIndex++;
+ if (candidateIndex == maxCandidatesToPrint)
+ break;
+ }
+ if (candidateIndex != candidateCount)
+ {
+ getSink()->diagnose(expr, Diagnostics::moreOverloadCandidates, candidateCount - candidateIndex);
+ }
}
return CreateErrorExpr(expr);
@@ -4322,7 +4455,10 @@ namespace Slang
else
{
// Nothing at all was found that we could even consider invoking
- getSink()->diagnose(expr->FunctionExpr, Diagnostics::expectedFunction);
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(expr->FunctionExpr, Diagnostics::expectedFunction);
+ }
expr->Type = QualType(ExpressionType::Error);
return expr;
}
@@ -4417,7 +4553,10 @@ namespace Slang
// TODO(tfoley): print a reasonable message here...
- getSink()->diagnose(genericAppExpr, Diagnostics::unimplemented, "no applicable generic");
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(genericAppExpr, Diagnostics::unimplemented, "no applicable generic");
+ }
return CreateErrorExpr(genericAppExpr);
}
@@ -4448,76 +4587,12 @@ namespace Slang
else
{
// Nothing at all was found that we could even consider invoking
- getSink()->diagnose(genericAppExpr, Diagnostics::unimplemented, "expected a generic");
- return CreateErrorExpr(genericAppExpr);
- }
-
-
-#if TIMREMOVED
-
- if (IsErrorExpr(base))
- {
- return CreateErrorExpr(typeNode);
- }
- else if(auto baseDeclRefExpr = base.As<DeclRefExpr>())
- {
- auto declRef = baseDeclRefExpr->declRef;
-
- if (auto genericDeclRef = declRef.As<GenericDecl>())
+ if (!isRewriteMode())
{
- int argCount = typeNode->Args.Count();
- int argIndex = 0;
- for (RefPtr<Decl> member : genericDeclRef.getDecl()->Members)
- {
- if (auto typeParam = member.As<GenericTypeParamDecl>())
- {
- if (argIndex == argCount)
- {
- // Too few arguments!
-
- }
-
- // TODO: checking!
- }
- else if (auto valParam = member.As<GenericValueParamDecl>())
- {
- // TODO: checking
- }
- else
- {
-
- }
- }
- if (argIndex != argCount)
- {
- // Too many arguments!
- }
-
- // Now instantiate the declaration given those arguments
- auto type = InstantiateGenericType(genericDeclRef, args);
- typeResult = type;
- typeNode->Type = new TypeExpressionType(type);
- return typeNode;
- }
- }
- else if (auto overloadedExpr = base.As<OverloadedExpr>())
- {
- // We are referring to a bunch of declarations, each of which might be generic
- LookupResult result;
- for (auto item : overloadedExpr->lookupResult2.items)
- {
- auto applied = TryApplyGeneric(item, typeNode);
- if (!applied)
- continue;
-
- AddToLookupResult(result, appliedItem);
+ getSink()->diagnose(genericAppExpr, Diagnostics::unimplemented, "expected a generic");
}
+ return CreateErrorExpr(genericAppExpr);
}
-
- // TODO: correct diagnostic here!
- getSink()->diagnose(typeNode, Diagnostics::expectedAGeneric, base->Type);
- return CreateErrorExpr(typeNode);
-#endif
}
RefPtr<ExpressionSyntaxNode> visitSharedTypeExpr(SharedTypeExpr* expr)
@@ -4568,7 +4643,10 @@ namespace Slang
if (i < expr->Arguments.Count() && expr->Arguments[i]->Type->AsBasicType() &&
!expr->Arguments[i]->Type.IsLeftValue)
{
- getSink()->diagnose(expr->Arguments[i], Diagnostics::argumentExpectedLValue, (*params)[i]->Name);
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(expr->Arguments[i], Diagnostics::argumentExpectedLValue, (*params)[i]->Name);
+ }
}
}
}
@@ -4610,7 +4688,10 @@ namespace Slang
expr);
}
- getSink()->diagnose(expr, Diagnostics::undefinedIdentifier2, expr->name);
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(expr, Diagnostics::undefinedIdentifier2, expr->name);
+ }
return expr;
}
@@ -4651,32 +4732,13 @@ namespace Slang
fail:
// Default: in no other case succeds, then the cast failed and we emit a diagnostic.
- getSink()->diagnose(expr, Diagnostics::invalidTypeCast, expr->Expression->Type, targetType->ToString());
- expr->Type = QualType(ExpressionType::Error);
- return expr;
- }
-#if TIMREMOVED
- virtual RefPtr<ExpressionSyntaxNode> VisitSelectExpression(SelectExpressionSyntaxNode * expr) override
- {
- auto selectorExpr = expr->SelectorExpr;
- selectorExpr = CheckExpr(selectorExpr);
- selectorExpr = Coerce(ExpressionType::GetBool(), selectorExpr);
- expr->SelectorExpr = selectorExpr;
-
- // TODO(tfoley): We need a general purpose "join" on types for inferring
- // generic argument types for builtins/intrinsics, so this should really
- // be using the exact same logic...
- //
- expr->Expr0 = expr->Expr0->Accept(this).As<ExpressionSyntaxNode>();
- expr->Expr1 = expr->Expr1->Accept(this).As<ExpressionSyntaxNode>();
- if (!expr->Expr0->Type->Equals(expr->Expr1->Type.Ptr()))
+ if (!isRewriteMode())
{
- getSink()->diagnose(expr, Diagnostics::selectValuesTypeMismatch);
+ getSink()->diagnose(expr, Diagnostics::invalidTypeCast, expr->Expression->Type, targetType->ToString());
}
- expr->Type = expr->Expr0->Type;
+ expr->Type = QualType(ExpressionType::Error);
return expr;
}
-#endif
// Get the type to use when referencing a declaration
QualType GetTypeForDeclRef(DeclRef<Decl> declRef)
@@ -4771,7 +4833,10 @@ namespace Slang
case 'w': case 'a': elementIndex = 3; break;
default:
// An invalid character in the swizzle is an error
- getSink()->diagnose(swizExpr, Diagnostics::unimplemented, "invalid component name for swizzle");
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(swizExpr, Diagnostics::unimplemented, "invalid component name for swizzle");
+ }
anyError = true;
continue;
}
@@ -4782,7 +4847,10 @@ namespace Slang
// Make sure the index is in range for the source type
if (elementIndex >= limitElement)
{
- getSink()->diagnose(swizExpr, Diagnostics::unimplemented, "swizzle component out of range for type");
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(swizExpr, Diagnostics::unimplemented, "swizzle component out of range for type");
+ }
anyError = true;
continue;
}
@@ -4806,7 +4874,7 @@ namespace Slang
if (anyError)
{
- swizExpr->Type = QualType(ExpressionType::Error);
+ return CreateErrorExpr(memberRefExpr);
}
else if (elementCount == 1)
{
@@ -4844,7 +4912,10 @@ namespace Slang
}
else
{
- getSink()->diagnose(memberRefExpr, Diagnostics::unimplemented, "swizzle on vector of unknown size");
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(memberRefExpr, Diagnostics::unimplemented, "swizzle on vector of unknown size");
+ }
return CreateErrorExpr(memberRefExpr);
}
}
@@ -4928,7 +4999,10 @@ namespace Slang
// catch-all
fail:
- getSink()->diagnose(expr, Diagnostics::noMemberOfNameInType, expr->name, baseType);
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(expr, Diagnostics::noMemberOfNameInType, expr->name, baseType);
+ }
expr->Type = QualType(ExpressionType::Error);
return expr;
}
@@ -4940,7 +5014,10 @@ namespace Slang
if (!baseType->Equals(ExpressionType::Error.Ptr()) &&
expr->Type->Equals(ExpressionType::Error.Ptr()))
{
- getSink()->diagnose(expr, Diagnostics::typeHasNoPublicMemberOfName, baseType, expr->name);
+ if (!isRewriteMode())
+ {
+ getSink()->diagnose(expr, Diagnostics::typeHasNoPublicMemberOfName, baseType, expr->name);
+ }
}
return expr;
}
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index df74d19e4..830ff6d97 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -238,7 +238,9 @@ struct EmitVisitor
if (isReservedWord(name))
{
- name = name + "_";
+ // TODO(tfoley): Need to put this back in, as part of lowering.
+
+// name = name + "_";
}
advanceToSourceLocation(loc);
@@ -970,6 +972,14 @@ struct EmitVisitor
{
e = derefExpr->base;
}
+
+ if (auto declRefExpr = e.As<DeclRefExpr>())
+ {
+ auto decl = declRefExpr->declRef.getDecl();
+ if (decl && decl->HasModifier<TransparentModifier>())
+ return true;
+ }
+
// Is the expression referencing a constant buffer?
if (auto cbufferType = e->Type->As<ConstantBufferType>())
{
@@ -1308,6 +1318,13 @@ struct EmitVisitor
if(needClose) Emit(")");
}
+ void visitParenExpr(ParenExpr* expr, ExprEmitArg const& arg)
+ {
+ Emit("(");
+ EmitExpr(expr->base);
+ Emit(")");
+ }
+
void visitAssignExpr(AssignExpr* assignExpr, ExprEmitArg const& arg)
{
auto outerPrec = arg.outerPrec;
@@ -1318,6 +1335,64 @@ struct EmitVisitor
if(needClose) Emit(")");
}
+ void emitUncheckedCallExpr(
+ RefPtr<InvokeExpressionSyntaxNode> callExpr,
+ String const& funcName,
+ ExprEmitArg const& arg)
+ {
+ auto outerPrec = arg.outerPrec;
+ auto funcExpr = callExpr->FunctionExpr;
+
+ // 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(
+ outerPrec,
+ kPrecedence_Comma,
+ funcName.Buffer(),
+ callExpr);
+ }
+ else if( auto prefixExpr = callExpr.As<PrefixExpr>() )
+ {
+ EmitUnaryExpr(
+ outerPrec,
+ kPrecedence_Prefix,
+ funcName.Buffer(),
+ "",
+ callExpr);
+ }
+ else if(auto postfixExpr = callExpr.As<PostfixExpr>())
+ {
+ EmitUnaryExpr(
+ outerPrec,
+ kPrecedence_Postfix,
+ "",
+ funcName.Buffer(),
+ callExpr);
+ }
+ else
+ {
+ bool needClose = MaybeEmitParens(outerPrec, kPrecedence_Postfix);
+
+ auto funcExpr = callExpr->FunctionExpr;
+ EmitExpr(funcExpr);
+
+ Emit("(");
+ UInt argCount = callExpr->Arguments.Count();
+ for (UInt aa = 0; aa < argCount; ++aa)
+ {
+ if (aa != 0) Emit(", ");
+ EmitExpr(callExpr->Arguments[aa]);
+ }
+ Emit(")");
+
+ if (needClose) Emit(")");
+ }
+ }
+
+
void visitInvokeExpressionSyntaxNode(
RefPtr<InvokeExpressionSyntaxNode> callExpr,
ExprEmitArg const& arg)
@@ -1331,39 +1406,7 @@ struct EmitVisitor
auto funcDecl = funcDeclRef.getDecl();
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(
- outerPrec,
- kPrecedence_Comma,
- funcDeclRefExpr->name.Buffer(),
- callExpr);
- }
- else if( auto prefixExpr = callExpr.As<PrefixExpr>() )
- {
- EmitUnaryExpr(
- outerPrec,
- kPrecedence_Prefix,
- funcDeclRefExpr->name.Buffer(),
- "",
- callExpr);
- }
- else if(auto postfixExpr = callExpr.As<PostfixExpr>())
- {
- EmitUnaryExpr(
- outerPrec,
- kPrecedence_Postfix,
- "",
- funcDeclRefExpr->name.Buffer(),
- callExpr);
- }
- else
- {
- emitSimpleCallExpr(callExpr, outerPrec);
- }
+ emitUncheckedCallExpr(callExpr, funcDeclRef.GetName(), arg);
return;
}
else if (auto intrinsicOpModifier = funcDecl->FindModifier<IntrinsicOpModifier>())
@@ -1408,6 +1451,7 @@ struct EmitVisitor
case IntrinsicOp::Sequence: EmitBinExpr(outerPrec, kPrecedence_Comma, ",", callExpr); return;
#define CASE(NAME, OP) case IntrinsicOp::NAME: EmitUnaryExpr(outerPrec, kPrecedence_Prefix, #OP, "", callExpr); return
+ CASE(Pos, +);
CASE(Neg, -);
CASE(Not, !);
CASE(BitNot, ~);
@@ -1603,6 +1647,11 @@ struct EmitVisitor
}
}
}
+ else if (auto overloadedExpr = funcExpr.As<OverloadedExpr>())
+ {
+ emitUncheckedCallExpr(callExpr, overloadedExpr->lookupResult2.getName(), arg);
+ return;
+ }
// Fall through to default handling...
emitSimpleCallExpr(callExpr, outerPrec);
@@ -1633,7 +1682,16 @@ struct EmitVisitor
Emit(".");
}
- emitName(memberExpr->declRef.GetName());
+ if (!memberExpr->declRef)
+ {
+ // This case arises when checking didn't find anything, but we were
+ // in "rewrite" mode so we blazed ahead anyway.
+ emitName(memberExpr->name);
+ }
+ else
+ {
+ emit(memberExpr->declRef.GetName());
+ }
if(needClose) Emit(")");
}
@@ -1655,14 +1713,17 @@ struct EmitVisitor
if(needClose) Emit(")");
}
- void visitIndexExpressionSyntaxNode(IndexExpressionSyntaxNode* indexExpr, ExprEmitArg const& arg)
+ void visitIndexExpressionSyntaxNode(IndexExpressionSyntaxNode* subscriptExpr, ExprEmitArg const& arg)
{
auto outerPrec = arg.outerPrec;
bool needClose = MaybeEmitParens(outerPrec, kPrecedence_Postfix);
- EmitExprWithPrecedence(indexExpr->BaseExpression, kPrecedence_Postfix);
+ EmitExprWithPrecedence(subscriptExpr->BaseExpression, kPrecedence_Postfix);
Emit("[");
- EmitExpr(indexExpr->IndexExpression);
+ if (auto indexExpr = subscriptExpr->IndexExpression)
+ {
+ EmitExpr(indexExpr);
+ }
Emit("]");
if(needClose) Emit(")");
@@ -1696,7 +1757,7 @@ struct EmitVisitor
}
else
{
- emitName(varExpr->name);
+ emit(varExpr->name);
}
if(needClose) Emit(")");
@@ -1777,6 +1838,16 @@ struct EmitVisitor
void visitTypeCastExpressionSyntaxNode(TypeCastExpressionSyntaxNode* castExpr, ExprEmitArg const& arg)
{
+ if (context->isRewrite)
+ {
+ if (dynamic_cast<ImplicitCastExpr*>(castExpr))
+ {
+ // This was an implicit cast, so don't try to output it
+ EmitExprWithPrecedence(castExpr->Expression, arg.outerPrec);
+ return;
+ }
+ }
+
bool needClose = false;
switch(context->shared->target)
{
@@ -1858,18 +1929,6 @@ struct EmitVisitor
}
}
-
- void EmitUnparsedStmt(RefPtr<UnparsedStmt> stmt)
- {
- // TODO: actually emit the tokens that made up the statement...
- Emit("{\n");
- for( auto& token : stmt->tokens )
- {
- emitTokenWithLocation(token);
- }
- Emit("}\n");
- }
-
void EmitStmt(RefPtr<StatementSyntaxNode> stmt)
{
// Try to ensure that debugging can find the right location
@@ -1888,11 +1947,6 @@ struct EmitVisitor
}
return;
}
- else if( auto unparsedStmt = stmt.As<UnparsedStmt>() )
- {
- EmitUnparsedStmt(unparsedStmt);
- return;
- }
else if (auto exprStmt = stmt.As<ExpressionStatementSyntaxNode>())
{
EmitExpr(exprStmt->Expression);
diff --git a/source/slang/expr-defs.h b/source/slang/expr-defs.h
index ca5bfacb8..5ca6629b9 100644
--- a/source/slang/expr-defs.h
+++ b/source/slang/expr-defs.h
@@ -96,6 +96,9 @@ SYNTAX_CLASS(TypeCastExpressionSyntaxNode, ExpressionSyntaxNode)
SYNTAX_FIELD(RefPtr<ExpressionSyntaxNode>, Expression)
END_SYNTAX_CLASS()
+SYNTAX_CLASS(ImplicitCastExpr, TypeCastExpressionSyntaxNode)
+END_SYNTAX_CLASS()
+
SIMPLE_SYNTAX_CLASS(SelectExpressionSyntaxNode, OperatorExpressionSyntaxNode)
SIMPLE_SYNTAX_CLASS(GenericAppExpr, AppExprBase)
@@ -112,3 +115,10 @@ SYNTAX_CLASS(AssignExpr, ExpressionSyntaxNode)
SYNTAX_FIELD(RefPtr<ExpressionSyntaxNode>, right);
END_SYNTAX_CLASS()
+// Just an expression inside parentheses `(exp)`
+//
+// We keep this around explicitly to be sure we don't lose any structure
+// when we do rewriter stuff.
+SYNTAX_CLASS(ParenExpr, ExpressionSyntaxNode)
+ SYNTAX_FIELD(RefPtr<ExpressionSyntaxNode>, base);
+END_SYNTAX_CLASS()
diff --git a/source/slang/intrinsic-defs.h b/source/slang/intrinsic-defs.h
index 19a3899a3..a272bd51c 100644
--- a/source/slang/intrinsic-defs.h
+++ b/source/slang/intrinsic-defs.h
@@ -46,6 +46,7 @@ INTRINSIC(RshAssign)
INTRINSIC(OrAssign)
INTRINSIC(AndAssign)
INTRINSIC(XorAssign)
+INTRINSIC(Pos)
INTRINSIC(Neg)
INTRINSIC(Not)
INTRINSIC(BitNot)
diff --git a/source/slang/lexer.cpp b/source/slang/lexer.cpp
index 2d75e1900..d8211fb20 100644
--- a/source/slang/lexer.cpp
+++ b/source/slang/lexer.cpp
@@ -517,7 +517,7 @@ namespace Slang
if(base > 10)
{
cursor++;
- return c - 'a';
+ return 10 + c - 'a';
}
return -1;
@@ -525,7 +525,7 @@ namespace Slang
if(base > 10)
{
cursor++;
- return c - 'A';
+ return 10 + c - 'A';
}
return -1;
}
@@ -957,7 +957,7 @@ namespace Slang
switch(peek(lexer))
{
default:
- return TokenType::IntegerLiteral;
+ return maybeLexNumberSuffix(lexer, TokenType::IntegerLiteral);
case '.':
advance(lexer);
diff --git a/source/slang/lower.cpp b/source/slang/lower.cpp
index b90573495..c154c96c8 100644
--- a/source/slang/lower.cpp
+++ b/source/slang/lower.cpp
@@ -451,6 +451,7 @@ struct LoweringVisitor
lowerExprCommon(loweredExpr, expr);
loweredExpr->BaseExpression = loweredBase;
loweredExpr->declRef = loweredDeclRef;
+ loweredExpr->name = expr->name;
return loweredExpr;
}
@@ -687,16 +688,6 @@ struct LoweringVisitor
addStmt(loweredStmt);
}
- void visitUnparsedStmt(UnparsedStmt* stmt)
- {
- RefPtr<UnparsedStmt> loweredStmt = new UnparsedStmt();
- lowerStmtFields(loweredStmt, stmt);
-
- loweredStmt->tokens = stmt->tokens;
-
- addStmt(loweredStmt);
- }
-
void visitCaseStmt(CaseStmt* stmt)
{
RefPtr<CaseStmt> loweredStmt = new CaseStmt();
diff --git a/source/slang/parser.cpp b/source/slang/parser.cpp
index b134f9645..2056bf809 100644
--- a/source/slang/parser.cpp
+++ b/source/slang/parser.cpp
@@ -1392,6 +1392,28 @@ namespace Slang
return genericApp;
}
+ // Parse option `[]` braces after a type expression, that indicate an array type
+ static RefPtr<ExpressionSyntaxNode> parsePostfixTypeSuffix(
+ Parser* parser,
+ RefPtr<ExpressionSyntaxNode> inTypeExpr)
+ {
+ auto typeExpr = inTypeExpr;
+ while (parser->LookAheadToken(TokenType::LBracket))
+ {
+ RefPtr<IndexExpressionSyntaxNode> arrType = new IndexExpressionSyntaxNode();
+ arrType->Position = typeExpr->Position;
+ arrType->BaseExpression = typeExpr;
+ parser->ReadToken(TokenType::LBracket);
+ if (!parser->LookAheadToken(TokenType::RBracket))
+ {
+ arrType->IndexExpression = parser->ParseExpression();
+ }
+ parser->ReadToken(TokenType::RBracket);
+ typeExpr = arrType;
+ }
+ return typeExpr;
+ }
+
static TypeSpec
parseTypeSpec(Parser* parser)
{
@@ -1431,11 +1453,16 @@ namespace Slang
typeExpr = parseGenericApp(parser, typeExpr);
}
+ // GLSL allows `[]` directly in a type specifier
+ if (parser->translationUnit->sourceLanguage == SourceLanguage::GLSL)
+ {
+ typeExpr = parsePostfixTypeSuffix(parser, typeExpr);
+ }
+
typeSpec.expr = typeExpr;
return typeSpec;
}
-
static RefPtr<DeclBase> ParseDeclaratorDecl(
Parser* parser,
ContainerDecl* containerDecl)
@@ -2572,50 +2599,6 @@ namespace Slang
RefPtr<StatementSyntaxNode> Parser::ParseBlockStatement()
{
- if( translationUnit->compileFlags & SLANG_COMPILE_FLAG_NO_CHECKING )
- {
- // We have been asked to parse the input, but not attempt to understand it.
-
- // TODO: record start/end locations...
-
- List<Token> tokens;
-
- ReadToken(TokenType::LBrace);
-
- int depth = 1;
- for( ;;)
- {
- switch( tokenReader.PeekTokenType() )
- {
- case TokenType::EndOfFile:
- goto done;
-
- case TokenType::RBrace:
- depth--;
- if(depth == 0)
- goto done;
- break;
-
- case TokenType::LBrace:
- depth++;
- break;
-
- default:
- break;
- }
-
- auto token = tokenReader.AdvanceToken();
- tokens.Add(token);
- }
- done:
- ReadToken(TokenType::RBrace);
-
- RefPtr<UnparsedStmt> unparsedStmt = new UnparsedStmt();
- unparsedStmt->tokens = tokens;
- return unparsedStmt;
- }
-
-
RefPtr<ScopeDecl> scopeDecl = new ScopeDecl();
RefPtr<BlockStmt> blockStatement = new BlockStmt();
blockStatement->scopeDecl = scopeDecl;
@@ -2816,19 +2799,7 @@ namespace Slang
}
auto typeExpr = typeSpec.expr;
- while (LookAheadToken(TokenType::LBracket))
- {
- RefPtr<IndexExpressionSyntaxNode> arrType = new IndexExpressionSyntaxNode();
- arrType->Position = typeExpr->Position;
- arrType->BaseExpression = typeExpr;
- ReadToken(TokenType::LBracket);
- if (!LookAheadToken(TokenType::RBracket))
- {
- arrType->IndexExpression = ParseExpression();
- }
- ReadToken(TokenType::RBracket);
- typeExpr = arrType;
- }
+ typeExpr = parsePostfixTypeSuffix(this, typeExpr);
return typeExpr;
}
@@ -2915,83 +2886,6 @@ namespace Slang
}
}
- Operator GetOpFromToken(Token & token)
- {
- switch(token.Type)
- {
- case TokenType::Comma:
- return Operator::Sequence;
- case TokenType::OpAssign:
- return Operator::Assign;
- case TokenType::OpAddAssign:
- return Operator::AddAssign;
- case TokenType::OpSubAssign:
- return Operator::SubAssign;
- case TokenType::OpMulAssign:
- return Operator::MulAssign;
- case TokenType::OpDivAssign:
- return Operator::DivAssign;
- case TokenType::OpModAssign:
- return Operator::ModAssign;
- case TokenType::OpShlAssign:
- return Operator::LshAssign;
- case TokenType::OpShrAssign:
- return Operator::RshAssign;
- case TokenType::OpOrAssign:
- return Operator::OrAssign;
- case TokenType::OpAndAssign:
- return Operator::AddAssign;
- case TokenType::OpXorAssign:
- return Operator::XorAssign;
- case TokenType::OpOr:
- return Operator::Or;
- case TokenType::OpAnd:
- return Operator::And;
- case TokenType::OpBitOr:
- return Operator::BitOr;
- case TokenType::OpBitXor:
- return Operator::BitXor;
- case TokenType::OpBitAnd:
- return Operator::BitAnd;
- case TokenType::OpEql:
- return Operator::Eql;
- case TokenType::OpNeq:
- return Operator::Neq;
- case TokenType::OpGeq:
- return Operator::Geq;
- case TokenType::OpLeq:
- return Operator::Leq;
- case TokenType::OpGreater:
- return Operator::Greater;
- case TokenType::OpLess:
- return Operator::Less;
- case TokenType::OpLsh:
- return Operator::Lsh;
- case TokenType::OpRsh:
- return Operator::Rsh;
- case TokenType::OpAdd:
- return Operator::Add;
- case TokenType::OpSub:
- return Operator::Sub;
- case TokenType::OpMul:
- return Operator::Mul;
- case TokenType::OpDiv:
- return Operator::Div;
- case TokenType::OpMod:
- return Operator::Mod;
- case TokenType::OpInc:
- return Operator::PostInc;
- case TokenType::OpDec:
- return Operator::PostDec;
- case TokenType::OpNot:
- return Operator::Not;
- case TokenType::OpBitNot:
- return Operator::BitNot;
- default:
- throw "Illegal TokenType.";
- }
- }
-
static RefPtr<ExpressionSyntaxNode> parseOperator(Parser* parser)
{
Token opToken;
@@ -3194,9 +3088,8 @@ namespace Slang
// but for now we will follow some hueristics.
case TokenType::LParent:
{
- parser->ReadToken(TokenType::LParent);
+ Token openParen = parser->ReadToken(TokenType::LParent);
- RefPtr<ExpressionSyntaxNode> expr;
if (peekTypeName(parser) && parser->LookAheadToken(TokenType::RParent, 1))
{
RefPtr<TypeCastExpressionSyntaxNode> tcexpr = new TypeCastExpressionSyntaxNode();
@@ -3204,15 +3097,18 @@ namespace Slang
tcexpr->TargetType = parser->ParseTypeExp();
parser->ReadToken(TokenType::RParent);
tcexpr->Expression = parser->ParseExpression(Precedence::Multiplicative); // Note(tfoley): need to double-check this
- expr = tcexpr;
+ return tcexpr;
}
else
{
- expr = parser->ParseExpression();
+ RefPtr<ExpressionSyntaxNode> base = parser->ParseExpression();
parser->ReadToken(TokenType::RParent);
- }
- return expr;
+ RefPtr<ParenExpr> parenExpr = new ParenExpr();
+ parenExpr->Position = openParen.Position;
+ parenExpr->base = base;
+ return parenExpr;
+ }
}
// An initializer list `{ expr, ... }`
@@ -3476,7 +3372,11 @@ namespace Slang
indexExpr->BaseExpression = expr;
parser->FillPosition(indexExpr.Ptr());
parser->ReadToken(TokenType::LBracket);
- indexExpr->IndexExpression = parser->ParseExpression();
+ // TODO: eventually we may want to support multiple arguments inside the `[]`
+ if (!parser->LookAheadToken(TokenType::RBracket))
+ {
+ indexExpr->IndexExpression = parser->ParseExpression();
+ }
parser->ReadToken(TokenType::RBracket);
expr = indexExpr;
@@ -3539,6 +3439,7 @@ namespace Slang
case TokenType::OpDec:
case TokenType::OpNot:
case TokenType::OpBitNot:
+ case TokenType::OpAdd:
case TokenType::OpSub:
{
RefPtr<PrefixExpr> prefixExpr = new PrefixExpr();
diff --git a/source/slang/slang-stdlib.cpp b/source/slang/slang-stdlib.cpp
index e1bba8885..e2d5829b4 100644
--- a/source/slang/slang-stdlib.cpp
+++ b/source/slang/slang-stdlib.cpp
@@ -7,18 +7,40 @@
#define STRINGIZE2(x) #x
#define LINE_STRING STRINGIZE(__LINE__)
-enum { kLibIncludeStringLine = __LINE__+1 };
-const char * LibIncludeStringChunks[] = { R"=(
+enum { kCoreLibIncludeStringLine = __LINE__ + 1 };
+const char* kCoreLibIncludeStringChunks[] = { R"=(
-typedef uint UINT;
+// A type that can be used as an operand for builtins
+interface __BuiltinType {}
+
+// A type that can be used for arithmetic operations
+interface __BuiltinArithmeticType : __BuiltinType {}
+
+// A type that logically has a sign (positive/negative/zero)
+interface __BuiltinSignedArithmeticType : __BuiltinArithmeticType {}
-__generic<T> __intrinsic_op(Assign) T operator=(out T left, T right);
+// A type that can represent integers
+interface __BuiltinIntegerType : __BuiltinArithmeticType {}
+
+// A type that can represent non-integers
+interface __BuiltinRealType : __BuiltinArithmeticType {}
+
+// A type that uses a floating-point representation
+interface __BuiltinFloatingPointType : __BuiltinRealType, __BuiltinSignedArithmeticType {}
__generic<T,U> __intrinsic_op(Sequence) U operator,(T left, U right);
__generic<T> __intrinsic_op(Select) T operator?:(bool condition, T ifTrue, T ifFalse);
__generic<T, let N : int> __intrinsic_op(Select) vector<T,N> operator?:(vector<bool,N> condition, vector<T,N> ifTrue, vector<T,N> ifFalse);
+)=" };
+
+
+enum { kHLSLLibIncludeStringLine = __LINE__+1 };
+const char * kHLSLLibIncludeStringChunks[] = { R"=(
+
+typedef uint UINT;
+
__generic<T> __magic_type(HLSLAppendStructuredBufferType) struct AppendStructuredBuffer
{
__intrinsic void Append(T value);
@@ -252,24 +274,6 @@ __generic<T> __magic_type(HLSLLineStreamType) struct TriangleStream
// Note(tfoley): Trying to systematically add all the HLSL builtins
-// A type that can be used as an operand for builtins
-interface __BuiltinType {}
-
-// A type that can be used for arithmetic operations
-interface __BuiltinArithmeticType : __BuiltinType {}
-
-// A type that logically has a sign (positive/negative/zero)
-interface __BuiltinSignedArithmeticType : __BuiltinArithmeticType {}
-
-// A type that can represent integers
-interface __BuiltinIntegerType : __BuiltinArithmeticType {}
-
-// A type that can represent non-integers
-interface __BuiltinRealType : __BuiltinArithmeticType {}
-
-// A type that uses a floating-point representation
-interface __BuiltinFloatingPointType : __BuiltinRealType, __BuiltinSignedArithmeticType {}
-
// Try to terminate the current draw or dispatch call (HLSL SM 4.0)
__intrinsic void abort();
@@ -1011,7 +1015,11 @@ namespace Slang
return stdlibPath;
}
- String SlangStdLib::code;
+ // Cached code for the various libraries
+ String coreLibraryCode;
+ String slangLibraryCode;
+ String hlslLibraryCode;
+ String glslLibraryCode;
enum
{
@@ -1029,93 +1037,88 @@ namespace Slang
ANY_MASK = INT_MASK | FLOAT_MASK | BOOL_MASK,
};
- String SlangStdLib::GetCode()
- {
- if (code.Length() > 0)
- return code;
- StringBuilder sb;
-
- // generate operator overloads
-
-
-
- struct OpInfo { IntrinsicOp opCode; char const* opName; unsigned flags; };
-
- OpInfo unaryOps[] = {
- { IntrinsicOp::Neg, "-", ARITHMETIC_MASK },
- { IntrinsicOp::Not, "!", ANY_MASK },
- { IntrinsicOp::BitNot, "~", INT_MASK },
- { IntrinsicOp::PreInc, "++", ARITHMETIC_MASK | ASSIGNMENT },
- { IntrinsicOp::PreDec, "--", ARITHMETIC_MASK | ASSIGNMENT },
- { IntrinsicOp::PostInc, "++", ARITHMETIC_MASK | ASSIGNMENT | POSTFIX },
- { IntrinsicOp::PostDec, "--", ARITHMETIC_MASK | ASSIGNMENT | POSTFIX },
- };
-
- OpInfo binaryOps[] = {
- { IntrinsicOp::Add, "+", ARITHMETIC_MASK },
- { IntrinsicOp::Sub, "-", ARITHMETIC_MASK },
- { IntrinsicOp::Mul, "*", ARITHMETIC_MASK },
- { IntrinsicOp::Div, "/", ARITHMETIC_MASK },
- { IntrinsicOp::Mod, "%", INT_MASK },
-
- { IntrinsicOp::And, "&&", LOGICAL_MASK },
- { IntrinsicOp::Or, "||", LOGICAL_MASK },
-
- { IntrinsicOp::BitAnd, "&", LOGICAL_MASK },
- { IntrinsicOp::BitOr, "|", LOGICAL_MASK },
- { IntrinsicOp::BitXor, "^", LOGICAL_MASK },
+ static const struct {
+ char const* name;
+ BaseType tag;
+ unsigned flags;
+ } kBaseTypes[] = {
+ { "void", BaseType::Void, 0 },
+ { "int", BaseType::Int, SINT_MASK },
+ { "half", BaseType::Half, FLOAT_MASK },
+ { "float", BaseType::Float, FLOAT_MASK },
+ { "double", BaseType::Double, FLOAT_MASK },
+ { "uint", BaseType::UInt, UINT_MASK },
+ { "bool", BaseType::Bool, BOOL_MASK },
+ { "uint64_t", BaseType::UInt64, UINT_MASK },
+ };
- { IntrinsicOp::Lsh, "<<", INT_MASK },
- { IntrinsicOp::Rsh, ">>", INT_MASK },
+ struct OpInfo { IntrinsicOp opCode; char const* opName; unsigned flags; };
+
+ static const OpInfo unaryOps[] = {
+ { IntrinsicOp::Pos, "+", ARITHMETIC_MASK },
+ { IntrinsicOp::Neg, "-", ARITHMETIC_MASK },
+ { IntrinsicOp::Not, "!", ANY_MASK },
+ { IntrinsicOp::BitNot, "~", INT_MASK },
+ { IntrinsicOp::PreInc, "++", ARITHMETIC_MASK | ASSIGNMENT },
+ { IntrinsicOp::PreDec, "--", ARITHMETIC_MASK | ASSIGNMENT },
+ { IntrinsicOp::PostInc, "++", ARITHMETIC_MASK | ASSIGNMENT | POSTFIX },
+ { IntrinsicOp::PostDec, "--", ARITHMETIC_MASK | ASSIGNMENT | POSTFIX },
+ };
- { IntrinsicOp::Eql, "==", ANY_MASK | COMPARISON },
- { IntrinsicOp::Neq, "!=", ANY_MASK | COMPARISON },
+ static const OpInfo binaryOps[] = {
+ { IntrinsicOp::Add, "+", ARITHMETIC_MASK },
+ { IntrinsicOp::Sub, "-", ARITHMETIC_MASK },
+ { IntrinsicOp::Mul, "*", ARITHMETIC_MASK },
+ { IntrinsicOp::Div, "/", ARITHMETIC_MASK },
+ { IntrinsicOp::Mod, "%", INT_MASK },
+
+ { IntrinsicOp::And, "&&", LOGICAL_MASK },
+ { IntrinsicOp::Or, "||", LOGICAL_MASK },
+
+ { IntrinsicOp::BitAnd, "&", LOGICAL_MASK },
+ { IntrinsicOp::BitOr, "|", LOGICAL_MASK },
+ { IntrinsicOp::BitXor, "^", LOGICAL_MASK },
+
+ { IntrinsicOp::Lsh, "<<", INT_MASK },
+ { IntrinsicOp::Rsh, ">>", INT_MASK },
+
+ { IntrinsicOp::Eql, "==", ANY_MASK | COMPARISON },
+ { IntrinsicOp::Neq, "!=", ANY_MASK | COMPARISON },
+
+ { IntrinsicOp::Greater, ">", ARITHMETIC_MASK | COMPARISON },
+ { IntrinsicOp::Less, "<", ARITHMETIC_MASK | COMPARISON },
+ { IntrinsicOp::Geq, ">=", ARITHMETIC_MASK | COMPARISON },
+ { IntrinsicOp::Leq, "<=", ARITHMETIC_MASK | COMPARISON },
+
+ { IntrinsicOp::AddAssign, "+=", ASSIGNMENT | ARITHMETIC_MASK },
+ { IntrinsicOp::SubAssign, "-=", ASSIGNMENT | ARITHMETIC_MASK },
+ { IntrinsicOp::MulAssign, "*=", ASSIGNMENT | ARITHMETIC_MASK },
+ { IntrinsicOp::DivAssign, "/=", ASSIGNMENT | ARITHMETIC_MASK },
+ { IntrinsicOp::ModAssign, "%=", ASSIGNMENT | ARITHMETIC_MASK },
+ { IntrinsicOp::AndAssign, "&=", ASSIGNMENT | LOGICAL_MASK },
+ { IntrinsicOp::OrAssign, "|=", ASSIGNMENT | LOGICAL_MASK },
+ { IntrinsicOp::XorAssign, "^=", ASSIGNMENT | LOGICAL_MASK },
+ { IntrinsicOp::LshAssign, "<<=", ASSIGNMENT | INT_MASK },
+ { IntrinsicOp::RshAssign, ">>=", ASSIGNMENT | INT_MASK },
+ };
- { IntrinsicOp::Greater, ">", ARITHMETIC_MASK | COMPARISON },
- { IntrinsicOp::Less, "<", ARITHMETIC_MASK | COMPARISON },
- { IntrinsicOp::Geq, ">=", ARITHMETIC_MASK | COMPARISON },
- { IntrinsicOp::Leq, "<=", ARITHMETIC_MASK | COMPARISON },
- { IntrinsicOp::AddAssign, "+=", ASSIGNMENT | ARITHMETIC_MASK },
- { IntrinsicOp::SubAssign, "-=", ASSIGNMENT | ARITHMETIC_MASK },
- { IntrinsicOp::MulAssign, "*=", ASSIGNMENT | ARITHMETIC_MASK },
- { IntrinsicOp::DivAssign, "/=", ASSIGNMENT | ARITHMETIC_MASK },
- { IntrinsicOp::ModAssign, "%=", ASSIGNMENT | ARITHMETIC_MASK },
- { IntrinsicOp::AndAssign, "&=", ASSIGNMENT | LOGICAL_MASK },
- { IntrinsicOp::OrAssign, "|=", ASSIGNMENT | LOGICAL_MASK },
- { IntrinsicOp::XorAssign, "^=", ASSIGNMENT | LOGICAL_MASK },
- { IntrinsicOp::LshAssign, "<<=", ASSIGNMENT | INT_MASK },
- { IntrinsicOp::RshAssign, ">>=", ASSIGNMENT | INT_MASK },
+ String getCoreLibraryCode()
+ {
+ if (coreLibraryCode.Length() > 0)
+ return coreLibraryCode;
+ StringBuilder sb;
- };
+ // generate operator overloads
- /*
- String floatTypes[] = { "float", "float2", "float3", "float4" };
- String intTypes[] = { "int", "int2", "int3", "int4" };
- String uintTypes[] = { "uint", "uint2", "uint3", "uint4" };
- */
String path = getStdlibPath();
-
-
#define EMIT_LINE_DIRECTIVE() sb << "#line " << (__LINE__+1) << " \"" << path << "\"\n"
// Generate declarations for all the base types
- static const struct {
- char const* name;
- BaseType tag;
- unsigned flags;
- } kBaseTypes[] = {
- { "void", BaseType::Void, 0 },
- { "int", BaseType::Int, SINT_MASK },
- { "float", BaseType::Float, FLOAT_MASK },
- { "uint", BaseType::UInt, UINT_MASK },
- { "bool", BaseType::Bool, BOOL_MASK },
- { "uint64_t", BaseType::UInt64, UINT_MASK },
- };
static const int kBaseTypeCount = sizeof(kBaseTypes) / sizeof(kBaseTypes[0]);
for (int tt = 0; tt < kBaseTypeCount; ++tt)
{
@@ -1126,7 +1129,7 @@ namespace Slang
sb << "\n : __BuiltinType\n";
- switch( kBaseTypes[tt].tag )
+ switch (kBaseTypes[tt].tag)
{
case BaseType::Float:
sb << "\n , __BuiltinFloatingPointType\n";
@@ -1151,9 +1154,9 @@ namespace Slang
// Declare initializers to convert from various other types
- for( int ss = 0; ss < kBaseTypeCount; ++ss )
+ for (int ss = 0; ss < kBaseTypeCount; ++ss)
{
- if( kBaseTypes[ss].tag == BaseType::Void )
+ if (kBaseTypes[ss].tag == BaseType::Void)
continue;
EMIT_LINE_DIRECTIVE();
@@ -1163,12 +1166,6 @@ namespace Slang
sb << "};\n";
}
- // Declare ad hoc aliases for some types, just to get things compiling
- //
- // TODO(tfoley): At the very least, `double` should be treated as a distinct type.
- sb << "typedef float double;\n";
- sb << "typedef float half;\n";
-
// Declare vector and matrix types
sb << "__generic<T = float, let N : int = 4> __magic_type(Vector) struct vector\n{\n";
@@ -1205,6 +1202,12 @@ namespace Slang
}
}
+ // Declare additional built-in generic types
+// EMIT_LINE_DIRECTIVE();
+ sb << "__generic<T> __magic_type(ConstantBuffer) struct ConstantBuffer {};\n";
+ sb << "__generic<T> __magic_type(TextureBuffer) struct TextureBuffer {};\n";
+
+
static const char* kComponentNames[]{ "x", "y", "z", "w" };
static const char* kVectorNames[]{ "", "x", "xy", "xyz", "xyzw" };
@@ -1292,7 +1295,6 @@ namespace Slang
sb << "}\n";
}
-
// Declare built-in texture and sampler types
sb << "__magic_type(SamplerState," << int(SamplerStateType::Flavor::SamplerState) << ") struct SamplerState {};";
@@ -1372,11 +1374,11 @@ namespace Slang
for(int isFloat = 0; isFloat < 2; ++isFloat)
for(int includeMipInfo = 0; includeMipInfo < 2; ++includeMipInfo)
{
- char const* t = isFloat ? "out float " : "out UINT ";
+ char const* t = isFloat ? "out float " : "out uint ";
sb << "void GetDimensions(";
if(includeMipInfo)
- sb << "UINT mipLevel, ";
+ sb << "uint mipLevel, ";
switch(baseShape)
{
@@ -1671,27 +1673,6 @@ namespace Slang
}
}
- // Declare additional built-in generic types
- EMIT_LINE_DIRECTIVE();
- sb << "__generic<T> __magic_type(ConstantBuffer) struct ConstantBuffer {};\n";
- sb << "__generic<T> __magic_type(TextureBuffer) struct TextureBuffer {};\n";
-
- sb << "__generic<T> __magic_type(PackedBuffer) struct PackedBuffer {};\n";
- sb << "__generic<T> __magic_type(Uniform) struct Uniform {};\n";
- sb << "__generic<T> __magic_type(Patch) struct Patch {};\n";
-
-
- // Stale declarations for GLSL inner-product builtins
-#if 0
- sb << "__intrinsic vec3 operator * (vec3, mat3);\n";
- sb << "__intrinsic vec3 operator * (mat3, vec3);\n";
-
- sb << "__intrinsic vec4 operator * (vec4, mat4);\n";
- sb << "__intrinsic vec4 operator * (mat4, vec4);\n";
-
- sb << "__intrinsic mat3 operator * (mat3, mat3);\n";
- sb << "__intrinsic mat4 operator * (mat4, mat4);\n";
-#endif
for (auto op : unaryOps)
{
@@ -1745,29 +1726,93 @@ namespace Slang
sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << "vector<" << leftType << ",N> left, vector<" << rightType << ",N> right);\n";
// matrix version
+
+ // skip matrix-matrix multiply operations here, so that GLSL doesn't see them
+ switch (op.opCode)
+ {
+ case IntrinsicOp::Mul:
+ case IntrinsicOp::MulAssign:
+ break;
+
+ default:
+ sb << "__generic<let N : int, let M : int> ";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << "matrix<" << leftType << ",N,M> left, matrix<" << rightType << ",N,M> right);\n";
+ break;
+ }
+ }
+ }
+
+ // Output a suitable `#line` directive to point at our raw stdlib code above
+ sb << "\n#line " << kCoreLibIncludeStringLine << " \"" << path << "\"\n";
+
+ int chunkCount = sizeof(kCoreLibIncludeStringChunks) / sizeof(kCoreLibIncludeStringChunks[0]);
+ for (int cc = 0; cc < chunkCount; ++cc)
+ {
+ sb << kCoreLibIncludeStringChunks[cc];
+ }
+
+ coreLibraryCode = sb.ProduceString();
+ return coreLibraryCode;
+ }
+
+ String getHLSLLibraryCode()
+ {
+ if (hlslLibraryCode.Length() > 0)
+ return hlslLibraryCode;
+
+ StringBuilder sb;
+
+
+// sb << "__generic<T> __magic_type(PackedBuffer) struct PackedBuffer {};\n";
+// sb << "__generic<T> __magic_type(Uniform) struct Uniform {};\n";
+// sb << "__generic<T> __magic_type(Patch) struct Patch {};\n";
+
+ // Component-wise multiplication ops
+ for(auto op : binaryOps)
+ {
+ switch (op.opCode)
+ {
+ default:
+ continue;
+
+ case IntrinsicOp::Mul:
+ case IntrinsicOp::MulAssign:
+ break;
+ }
+
+ for (auto type : kBaseTypes)
+ {
+ if ((type.flags & op.flags) == 0)
+ continue;
+
+ char const* leftType = type.name;
+ char const* rightType = leftType;
+ char const* resultType = leftType;
+
+ char const* leftQual = "";
+ if(op.flags & ASSIGNMENT) leftQual = "in out ";
+
sb << "__generic<let N : int, let M : int> ";
sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << "matrix<" << leftType << ",N,M> left, matrix<" << rightType << ",N,M> right);\n";
}
}
// Output a suitable `#line` directive to point at our raw stdlib code above
- sb << "\n#line " << kLibIncludeStringLine << " \"" << path << "\"\n";
+ sb << "\n#line " << kHLSLLibIncludeStringLine << " \"" << getStdlibPath() << "\"\n";
- int chunkCount = sizeof(LibIncludeStringChunks) / sizeof(LibIncludeStringChunks[0]);
+ int chunkCount = sizeof(kHLSLLibIncludeStringChunks) / sizeof(kHLSLLibIncludeStringChunks[0]);
for (int cc = 0; cc < chunkCount; ++cc)
{
- sb << LibIncludeStringChunks[cc];
+ sb << kHLSLLibIncludeStringChunks[cc];
}
- code = sb.ProduceString();
- return code;
+ hlslLibraryCode = sb.ProduceString();
+ return hlslLibraryCode;
}
// GLSL-specific library code
- String glslLibraryCode;
-
String getGLSLLibraryCode()
{
if(glslLibraryCode.Length() != 0)
@@ -1794,16 +1839,42 @@ namespace Slang
// Declare GLSL aliases for HLSL types
for (int vv = 2; vv <= 4; ++vv)
{
- sb << "typedef " << kTypes[tt].name << vv << " " << kTypes[tt].glslPrefix << "vec" << vv << ";\n";
- sb << "typedef " << kTypes[tt].name << vv << "x" << vv << " " << kTypes[tt].glslPrefix << "mat" << vv << ";\n";
+ sb << "typedef vector<" << kTypes[tt].name << "," << vv << "> " << kTypes[tt].glslPrefix << "vec" << vv << ";\n";
+ sb << "typedef matrix<" << kTypes[tt].name << "," << vv << "," << vv << "> " << kTypes[tt].glslPrefix << "mat" << vv << ";\n";
}
for (int rr = 2; rr <= 4; ++rr)
for (int cc = 2; cc <= 4; ++cc)
{
- sb << "typedef " << kTypes[tt].name << rr << "x" << cc << " " << kTypes[tt].glslPrefix << "mat" << rr << "x" << cc << ";\n";
+ sb << "typedef matrix<" << kTypes[tt].name << "," << rr << "," << cc << "> " << kTypes[tt].glslPrefix << "mat" << rr << "x" << cc << ";\n";
}
}
+ // Multiplication operations for vectors + matrices
+
+ // scalar-vector and vector-scalar
+ sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op(Mul) vector<T,N> operator*(vector<T,N> x, T y);\n";
+ sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op(Mul) vector<T,N> operator*(T x, vector<T,N> y);\n";
+
+ // scalar-matrix and matrix-scalar
+ sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M :int> __intrinsic_op(Mul) matrix<T,N,M> operator*(matrix<T,N,M> x, T y);\n";
+ sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M :int> __intrinsic_op(Mul) matrix<T,N,M> operator*(T x, matrix<T,N,M> y);\n";
+
+ // vector-vector (dot product)
+ sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op(Mul) T operator*(vector<T,N> x, vector<T,N> y);\n";
+
+ // vector-matrix
+ sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op(Mul) vector<T,M> operator*(vector<T,N> x, matrix<T,N,M> y);\n";
+
+ // matrix-vector
+ sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op(Mul) vector<T,N> operator*(matrix<T,N,M> x, vector<T,M> y);\n";
+
+ // matrix-matrix
+ sb << "__generic<T : __BuiltinArithmeticType, let R : int, let N : int, let C : int> __intrinsic_op(Mul) matrix<T,R,C> operator*(matrix<T,R,N> x, matrix<T,N,C> y);\n";
+
+
+
+ //
+
// TODO(tfoley): Need to handle `RW*` variants of texture types as well...
static const struct {
char const* name;
@@ -1909,6 +1980,7 @@ namespace Slang
sb << "__modifier(GLSLPatchModifier) patch;\n";
sb << "__modifier(SimpleModifier) flat;\n";
+ sb << "__modifier(SimpleModifier) highp;\n";
glslLibraryCode = sb.ProduceString();
return glslLibraryCode;
@@ -1918,10 +1990,12 @@ namespace Slang
//
- void SlangStdLib::Finalize()
+ void finalizeShaderLibrary()
{
- code = String();
stdlibPath = String();
+
+ coreLibraryCode = String();
+ hlslLibraryCode = String();
glslLibraryCode = String();
}
diff --git a/source/slang/slang-stdlib.h b/source/slang/slang-stdlib.h
index e4ee8cee3..d21b1e7f1 100644
--- a/source/slang/slang-stdlib.h
+++ b/source/slang/slang-stdlib.h
@@ -5,16 +5,11 @@
namespace Slang
{
- class SlangStdLib
- {
- private:
- static String code;
- public:
- static String GetCode();
- static void Finalize();
- };
-
+ String getCoreLibraryCode();
+ String getHLSLLibraryCode();
String getGLSLLibraryCode();
+
+ void finalizeShaderLibrary();
}
#endif \ No newline at end of file
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index c4944c5a4..e5bfcb923 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -25,8 +25,9 @@ public:
bool useCache = false;
String cacheDir;
- RefPtr<Scope> slangLanguageScope;
+ RefPtr<Scope> coreLanguageScope;
RefPtr<Scope> hlslLanguageScope;
+ RefPtr<Scope> slangLanguageScope;
RefPtr<Scope> glslLanguageScope;
List<RefPtr<ProgramSyntaxNode>> loadedModuleCode;
@@ -43,15 +44,19 @@ public:
// TODO: load these on-demand to avoid parsing
// stdlib code for languages the user won't use.
- slangLanguageScope = new Scope();
+ coreLanguageScope = new Scope();
hlslLanguageScope = new Scope();
- hlslLanguageScope->parent = slangLanguageScope;
+ hlslLanguageScope->nextSibling = coreLanguageScope;
+
+ slangLanguageScope = new Scope();
+ slangLanguageScope->nextSibling = hlslLanguageScope;
glslLanguageScope = new Scope();
- glslLanguageScope->parent = slangLanguageScope;
+ glslLanguageScope->nextSibling = coreLanguageScope;
- addBuiltinSource(slangLanguageScope, "stdlib", SlangStdLib::GetCode());
+ addBuiltinSource(coreLanguageScope, "core", getCoreLibraryCode());
+ addBuiltinSource(hlslLanguageScope, "hlsl", getHLSLLibraryCode());
addBuiltinSource(glslLanguageScope, "glsl", getGLSLLibraryCode());
}
@@ -61,7 +66,7 @@ public:
// code that we might have allocated and loaded into static
// variables (TODO: don't use `static` variables for this stuff)
- SlangStdLib::Finalize();
+ finalizeShaderLibrary();
// Ditto for our type represnetation stuff
diff --git a/source/slang/stmt-defs.h b/source/slang/stmt-defs.h
index c5bcda63b..165ffea83 100644
--- a/source/slang/stmt-defs.h
+++ b/source/slang/stmt-defs.h
@@ -16,11 +16,6 @@ SYNTAX_CLASS(BlockStmt, ScopeStmt)
SYNTAX_FIELD(RefPtr<StatementSyntaxNode>, body);
END_SYNTAX_CLASS()
-SYNTAX_CLASS(UnparsedStmt, StatementSyntaxNode)
- // The tokens that were contained between `{` and `}`
- FIELD(List<Token>, tokens)
-END_SYNTAX_CLASS()
-
SIMPLE_SYNTAX_CLASS(EmptyStatementSyntaxNode, StatementSyntaxNode)
SIMPLE_SYNTAX_CLASS(DiscardStatementSyntaxNode, StatementSyntaxNode)
diff --git a/source/slang/syntax.h b/source/slang/syntax.h
index 1704c1224..de5467c71 100644
--- a/source/slang/syntax.h
+++ b/source/slang/syntax.h
@@ -176,6 +176,7 @@ namespace Slang
Int,
UInt,
UInt64,
+ Half,
Float,
Double,
};
@@ -690,22 +691,6 @@ namespace Slang
LookupMask mask = LookupMask::All;
};
- enum class Operator
- {
- Neg, Not, BitNot, PreInc, PreDec, PostInc, PostDec,
- Mul, Div, Mod,
- Add, Sub,
- Lsh, Rsh,
- Eql, Neq, Greater, Less, Geq, Leq,
- BitAnd, BitXor, BitOr,
- And,
- Or,
- Sequence,
- Select,
- Assign = 200, AddAssign, SubAssign, MulAssign, DivAssign, ModAssign,
- LshAssign, RshAssign, OrAssign, AndAssign, XorAssign,
- };
-
// Generate class definition for all syntax classes
#define SYNTAX_FIELD(TYPE, NAME) TYPE NAME;
#define FIELD(TYPE, NAME) TYPE NAME;