summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Foley <tfoley@nvidia.com>2017-06-29 08:55:09 -0700
committerTim Foley <tfoley@nvidia.com>2017-06-30 12:22:33 -0700
commitcab694dcead92a554654d7fa3f08909d519425f0 (patch)
tree6c2c07c3930ff68b5518e562b0b507d5ec54d0bf
parentb2b08679a32506d629df84730f36639dab9f9593 (diff)
Add meta-definitions for AST types
- The big change here is that all the definitions for syntax-node classes have been macro-ized, to that we can do light metaprogramming over them - The use of macros for this has big down-sides, but I'm not quite ready to do anything more heavy-weight right now - The macro-ized definitions can be included multiple times, to generate different declarations/code as needed - The first example of using this meta-programming facility is a new visitor system - The actual visitor base classes and the dispatch logic are all generated from the meta-files - There was only one visitor left in the code: the semantics checker, so that was ported to the new system. - All current test cases pass, so *of course* that means all is well.
-rw-r--r--source/slang/check.cpp457
-rw-r--r--source/slang/compiler.h3
-rw-r--r--source/slang/decl-defs.h232
-rw-r--r--source/slang/expr-defs.h109
-rw-r--r--source/slang/lookup.h3
-rw-r--r--source/slang/modifier-defs.h271
-rw-r--r--source/slang/object-meta-begin.h36
-rw-r--r--source/slang/object-meta-end.h11
-rw-r--r--source/slang/slang-stdlib.cpp83
-rw-r--r--source/slang/slang.cpp12
-rw-r--r--source/slang/slang.vcxproj11
-rw-r--r--source/slang/slang.vcxproj.filters11
-rw-r--r--source/slang/stmt-defs.h101
-rw-r--r--source/slang/syntax-base-defs.h261
-rw-r--r--source/slang/syntax-defs.h10
-rw-r--r--source/slang/syntax-visitors.h5
-rw-r--r--source/slang/syntax.cpp506
-rw-r--r--source/slang/syntax.h1923
-rw-r--r--source/slang/type-defs.h393
-rw-r--r--source/slang/val-defs.h37
-rw-r--r--source/slang/visitor.h346
-rw-r--r--tests/diagnostics/while-predicate-type.slang.expected2
22 files changed, 2259 insertions, 2564 deletions
diff --git a/source/slang/check.cpp b/source/slang/check.cpp
index 4966b102f..a3e061a3b 100644
--- a/source/slang/check.cpp
+++ b/source/slang/check.cpp
@@ -2,6 +2,7 @@
#include "lookup.h"
#include "compiler.h"
+#include "visitor.h"
#include <assert.h>
@@ -42,14 +43,28 @@ namespace Slang
return name;
}
- class SemanticsVisitor : public SyntaxVisitor
+ struct SemanticsVisitor
+ : ExprVisitor<SemanticsVisitor, RefPtr<ExpressionSyntaxNode>>
+ , StmtVisitor<SemanticsVisitor>
+ , DeclVisitor<SemanticsVisitor>
{
+ DiagnosticSink* sink = nullptr;
+ DiagnosticSink* getSink()
+ {
+ return sink;
+ }
+
// ProgramSyntaxNode * program = nullptr;
FunctionSyntaxNode * function = nullptr;
CompileRequest* request = nullptr;
TranslationUnitRequest* translationUnit = nullptr;
+ SourceLanguage getSourceLanguage()
+ {
+ return translationUnit->sourceLanguage;
+ }
+
// lexical outer statements
List<StatementSyntaxNode*> outerStmts;
@@ -62,10 +77,10 @@ namespace Slang
public:
SemanticsVisitor(
- DiagnosticSink * pErr,
+ DiagnosticSink* sink,
CompileRequest* request,
TranslationUnitRequest* translationUnit)
- : SyntaxVisitor(pErr)
+ : sink(sink)
, request(request)
, translationUnit(translationUnit)
{
@@ -80,7 +95,8 @@ namespace Slang
RefPtr<ExpressionSyntaxNode> TranslateTypeNodeImpl(const RefPtr<ExpressionSyntaxNode> & node)
{
if (!node) return nullptr;
- auto expr = node->Accept(this).As<ExpressionSyntaxNode>();
+
+ auto expr = CheckTerm(node);
expr = ExpectATypeRepr(expr);
return expr;
}
@@ -348,9 +364,8 @@ namespace Slang
decl->SetCheckState(DeclCheckState::CheckingHeader);
}
- // TODO: not all of the `Visit` cases are ready to
- // handle this being called on-the-fly
- decl->Accept(this);
+ // Use visitor pattern to dispatch to correct case
+ DeclVisitor::dispatch(decl);
decl->SetCheckState(DeclCheckState::Checked);
}
@@ -513,7 +528,7 @@ namespace Slang
RefPtr<ExpressionSyntaxNode> CheckTerm(RefPtr<ExpressionSyntaxNode> term)
{
if (!term) return nullptr;
- return term->Accept(this).As<ExpressionSyntaxNode>();
+ return ExprVisitor::dispatch(term);
}
RefPtr<ExpressionSyntaxNode> CreateErrorExpr(ExpressionSyntaxNode* expr)
@@ -1052,7 +1067,12 @@ namespace Slang
decl->sup = TranslateTypeNode(decl->sup);
}
- virtual RefPtr<GenericDecl> VisitGenericDecl(GenericDecl* genericDecl) override
+ void checkDecl(Decl* decl)
+ {
+ EnsureDecl(decl, DeclCheckState::Checked);
+ }
+
+ void visit(GenericDecl* genericDecl)
{
// check the parameters
for (auto m : genericDecl->Members)
@@ -1074,16 +1094,15 @@ namespace Slang
// check the nested declaration
// TODO: this needs to be done in an appropriate environment...
- genericDecl->inner->Accept(this);
- return genericDecl;
+ checkDecl(genericDecl->inner);
}
- virtual void visitInterfaceDecl(InterfaceDecl* /*decl*/) override
+ void visit(InterfaceDecl* /*decl*/)
{
// TODO: do some actual checking of members here
}
- virtual void visitInheritanceDecl(InheritanceDecl* inheritanceDecl) override
+ void visit(InheritanceDecl* inheritanceDecl)
{
// check the type being inherited from
auto base = inheritanceDecl->base;
@@ -1125,6 +1144,31 @@ namespace Slang
return constIntVal;
}
+ void visit(ModifierDecl* decl)
+ {
+ // These are only used in the stdlib, so no checking is needed
+ }
+
+ void visit(GenericTypeParamDecl* decl)
+ {
+ // These are only used in the stdlib, so no checking is needed for now
+ }
+
+ void visit(GenericValueParamDecl* decl)
+ {
+ // These are only used in the stdlib, so no checking is needed for now
+ }
+
+ void visit(GenericTypeConstraintDecl* decl)
+ {
+ // These are only used in the stdlib, so no checking is needed for now
+ }
+
+ void visit(Modifier* modifier)
+ {
+ // Do nothing with modifiers for now
+ }
+
RefPtr<Modifier> checkModifier(
RefPtr<Modifier> m,
Decl* /*decl*/)
@@ -1226,7 +1270,7 @@ namespace Slang
decl->modifiers.first = resultModifiers;
}
- virtual RefPtr<ProgramSyntaxNode> VisitProgram(ProgramSyntaxNode * programNode) override
+ void visit(ProgramSyntaxNode* programNode)
{
// Try to register all the builtin decls
for (auto decl : programNode->Members)
@@ -1256,37 +1300,37 @@ namespace Slang
//
- for (auto & s : programNode->GetTypeDefs())
- VisitTypeDefDecl(s.Ptr());
- for (auto & s : programNode->GetStructs())
+ for (auto & s : programNode->getMembersOfType<TypeDefDecl>())
+ checkDecl(s.Ptr());
+ for (auto & s : programNode->getMembersOfType<StructSyntaxNode>())
{
- VisitStruct(s.Ptr());
+ checkDecl(s.Ptr());
}
- for (auto & s : programNode->GetClasses())
+ for (auto & s : programNode->getMembersOfType<ClassSyntaxNode>())
{
- VisitClass(s.Ptr());
+ checkDecl(s.Ptr());
}
// HACK(tfoley): Visiting all generic declarations here,
// because otherwise they won't get visited.
for (auto & g : programNode->getMembersOfType<GenericDecl>())
{
- VisitGenericDecl(g.Ptr());
+ checkDecl(g.Ptr());
}
- for (auto & func : programNode->GetFunctions())
+ for (auto & func : programNode->getMembersOfType<FunctionSyntaxNode>())
{
if (!func->IsChecked(DeclCheckState::Checked))
{
VisitFunctionDeclaration(func.Ptr());
}
}
- for (auto & func : programNode->GetFunctions())
+ for (auto & func : programNode->getMembersOfType<FunctionSyntaxNode>())
{
EnsureDecl(func);
}
if (sink->GetErrorCount() != 0)
- return programNode;
+ return;
// Force everything to be fully checked, just in case
// Note that we don't just call this on the program,
@@ -1301,14 +1345,12 @@ namespace Slang
{
checkModifiers(d.Ptr());
}
-
- return programNode;
}
- virtual RefPtr<ClassSyntaxNode> VisitClass(ClassSyntaxNode * classNode) override
+ void visit(ClassSyntaxNode * classNode)
{
if (classNode->IsChecked(DeclCheckState::Checked))
- return classNode;
+ return;
classNode->SetCheckState(DeclCheckState::Checked);
for (auto field : classNode->GetFields())
@@ -1316,51 +1358,68 @@ namespace Slang
field->Type = CheckUsableType(field->Type);
field->SetCheckState(DeclCheckState::Checked);
}
- return classNode;
}
- virtual RefPtr<StructSyntaxNode> VisitStruct(StructSyntaxNode * structNode) override
+ void visit(StructField* field)
+ {
+ // TODO: bottleneck through general-case variable checking
+
+ field->Type = CheckUsableType(field->Type);
+ field->SetCheckState(DeclCheckState::Checked);
+ }
+
+ void visit(StructSyntaxNode * structNode)
{
if (structNode->IsChecked(DeclCheckState::Checked))
- return structNode;
+ return;
structNode->SetCheckState(DeclCheckState::Checked);
for (auto field : structNode->GetFields())
{
- field->Type = CheckUsableType(field->Type);
- field->SetCheckState(DeclCheckState::Checked);
+ checkDecl(field);
}
- return structNode;
}
- virtual RefPtr<TypeDefDecl> VisitTypeDefDecl(TypeDefDecl* decl) override
+ void visit(DeclGroup* declGroup)
{
- if (decl->IsChecked(DeclCheckState::Checked)) return decl;
+ for (auto decl : declGroup->decls)
+ {
+ checkDecl(decl);
+ }
+ }
+
+ void visit(TypeDefDecl* decl)
+ {
+ if (decl->IsChecked(DeclCheckState::Checked)) return;
decl->SetCheckState(DeclCheckState::CheckingHeader);
decl->Type = CheckProperType(decl->Type);
decl->SetCheckState(DeclCheckState::Checked);
- return decl;
}
- virtual RefPtr<FunctionSyntaxNode> VisitFunction(FunctionSyntaxNode *functionNode) override
+ void checkStmt(StatementSyntaxNode* stmt)
+ {
+ if (!stmt) return;
+ StmtVisitor::dispatch(stmt);
+ }
+
+ void visit(FunctionSyntaxNode *functionNode)
{
if (functionNode->IsChecked(DeclCheckState::Checked))
- return functionNode;
+ return;
VisitFunctionDeclaration(functionNode);
+ // TODO: This should really onlye set "checked header"
functionNode->SetCheckState(DeclCheckState::Checked);
- if (!functionNode->IsExtern())
+ // TODO: should put the checking of the body onto a "work list"
+ // to avoid recursion here.
+ if (functionNode->Body)
{
this->function = functionNode;
- if (functionNode->Body)
- {
- functionNode->Body->Accept(this);
- }
+ checkStmt(functionNode->Body);
this->function = nullptr;
}
- return functionNode;
}
// Check if two functions have the same signature for the purposes
@@ -1469,6 +1528,20 @@ namespace Slang
}
}
+ void visit(ScopeDecl*)
+ {
+ // Nothing to do
+ }
+
+ void visit(ParameterSyntaxNode* para)
+ {
+ // TODO: This needs to bottleneck through the common variable checks
+
+ para->Type = CheckUsableType(para->Type);
+ if (para->Type.Equals(ExpressionType::GetVoid()))
+ getSink()->diagnose(para, Diagnostics::parameterCannotBeVoid);
+ }
+
void VisitFunctionDeclaration(FunctionSyntaxNode *functionNode)
{
if (functionNode->IsChecked(DeclCheckState::CheckedHeader)) return;
@@ -1480,13 +1553,12 @@ namespace Slang
HashSet<String> paraNames;
for (auto & para : functionNode->GetParameters())
{
+ checkDecl(para);
+
if (paraNames.Contains(para->Name.Content))
getSink()->diagnose(para, Diagnostics::parameterAlreadyDefined, para->Name);
else
paraNames.Add(para->Name.Content);
- para->Type = CheckUsableType(para->Type);
- if (para->Type.Equals(ExpressionType::GetVoid()))
- getSink()->diagnose(para, Diagnostics::parameterCannotBeVoid);
}
this->function = NULL;
functionNode->SetCheckState(DeclCheckState::CheckedHeader);
@@ -1495,13 +1567,26 @@ namespace Slang
ValidateFunctionRedeclaration(functionNode);
}
- virtual RefPtr<StatementSyntaxNode> VisitBlockStatement(BlockStatementSyntaxNode *stmt) override
+ void visit(VarDeclrStatementSyntaxNode* stmt)
+ {
+ // We directly dispatch here instead of using `EnsureDecl()` for two
+ // reasons:
+ //
+ // 1. We expect that a local declaration won't have been referenced
+ // before it is declared, so that we can just check things in-order
+ //
+ // 2. `EnsureDecl()` is specialized for `Decl*` instead of `DeclBase*`
+ // and trying to special case `DeclGroup*` here feels silly.
+ //
+ DeclVisitor::dispatch(stmt->decl);
+ }
+
+ void visit(BlockStatementSyntaxNode *stmt)
{
for (auto & node : stmt->Statements)
{
- node->Accept(this);
+ checkStmt(node);
}
- return stmt;
}
template<typename T>
@@ -1518,7 +1603,7 @@ namespace Slang
return nullptr;
}
- virtual RefPtr<StatementSyntaxNode> VisitBreakStatement(BreakStatementSyntaxNode *stmt) override
+ void visit(BreakStatementSyntaxNode *stmt)
{
auto outer = FindOuterStmt<BreakableStmt>();
if (!outer)
@@ -1526,9 +1611,8 @@ namespace Slang
getSink()->diagnose(stmt, Diagnostics::breakOutsideLoop);
}
stmt->parentStmt = outer;
- return stmt;
}
- virtual RefPtr<StatementSyntaxNode> VisitContinueStatement(ContinueStatementSyntaxNode *stmt) override
+ void visit(ContinueStatementSyntaxNode *stmt)
{
auto outer = FindOuterStmt<LoopStmt>();
if (!outer)
@@ -1536,7 +1620,6 @@ namespace Slang
getSink()->diagnose(stmt, Diagnostics::continueOutsideLoop);
}
stmt->parentStmt = outer;
- return stmt;
}
void PushOuterStmt(StatementSyntaxNode* stmt)
@@ -1549,59 +1632,55 @@ namespace Slang
outerStmts.RemoveAt(outerStmts.Count() - 1);
}
- virtual RefPtr<StatementSyntaxNode> VisitDoWhileStatement(DoWhileStatementSyntaxNode *stmt) override
+ RefPtr<ExpressionSyntaxNode> checkPredicateExpr(ExpressionSyntaxNode* expr)
+ {
+ RefPtr<ExpressionSyntaxNode> e = expr;
+ e = CheckTerm(e);
+ e = Coerce(ExpressionType::GetBool(), e);
+ return e;
+ }
+
+ void visit(DoWhileStatementSyntaxNode *stmt)
{
PushOuterStmt(stmt);
- if (stmt->Predicate != NULL)
- stmt->Predicate = stmt->Predicate->Accept(this).As<ExpressionSyntaxNode>();
- if (!stmt->Predicate->Type->Equals(ExpressionType::GetError()) &&
- !stmt->Predicate->Type->Equals(ExpressionType::GetInt()) &&
- !stmt->Predicate->Type->Equals(ExpressionType::GetBool()))
- {
- getSink()->diagnose(stmt, Diagnostics::whilePredicateTypeError);
- }
- stmt->Statement->Accept(this);
+ stmt->Predicate = checkPredicateExpr(stmt->Predicate);
+ checkStmt(stmt->Statement);
PopOuterStmt(stmt);
- return stmt;
}
- virtual RefPtr<StatementSyntaxNode> VisitForStatement(ForStatementSyntaxNode *stmt) override
+ void visit(ForStatementSyntaxNode *stmt)
{
PushOuterStmt(stmt);
- if (stmt->InitialStatement)
- {
- stmt->InitialStatement = stmt->InitialStatement->Accept(this).As<StatementSyntaxNode>();
- }
+ checkStmt(stmt->InitialStatement);
if (stmt->PredicateExpression)
{
- stmt->PredicateExpression = stmt->PredicateExpression->Accept(this).As<ExpressionSyntaxNode>();
- if (!stmt->PredicateExpression->Type->Equals(ExpressionType::GetBool()) &&
- !stmt->PredicateExpression->Type->Equals(ExpressionType::GetInt()) &&
- !stmt->PredicateExpression->Type->Equals(ExpressionType::GetUInt()))
- {
- getSink()->diagnose(stmt->PredicateExpression.Ptr(), Diagnostics::forPredicateTypeError);
- }
+ stmt->PredicateExpression = checkPredicateExpr(stmt->PredicateExpression);
}
if (stmt->SideEffectExpression)
{
- stmt->SideEffectExpression = stmt->SideEffectExpression->Accept(this).As<ExpressionSyntaxNode>();
+ stmt->SideEffectExpression = CheckExpr(stmt->SideEffectExpression);
}
- stmt->Statement->Accept(this);
+ checkStmt(stmt->Statement);
PopOuterStmt(stmt);
- return stmt;
}
- virtual RefPtr<SwitchStmt> VisitSwitchStmt(SwitchStmt* stmt) override
+ void visit(SwitchStmt* stmt)
{
PushOuterStmt(stmt);
// TODO(tfoley): need to coerce condition to an integral type...
stmt->condition = CheckExpr(stmt->condition);
- stmt->body->Accept(this);
+ checkStmt(stmt->body);
+
+ // TODO(tfoley): need to check that all case tags are unique
+
+ // TODO(tfoley): check that there is at most one `default` clause
+
PopOuterStmt(stmt);
- return stmt;
}
- virtual RefPtr<CaseStmt> VisitCaseStmt(CaseStmt* stmt) override
+ void visit(CaseStmt* stmt)
{
+ // TODO(tfoley): Need to coerce to type being switch on,
+ // and ensure that value is a compile-time constant
auto expr = CheckExpr(stmt->expr);
auto switchStmt = FindOuterStmt<SwitchStmt>();
@@ -1617,10 +1696,8 @@ namespace Slang
stmt->expr = expr;
stmt->parentStmt = switchStmt;
-
- return stmt;
}
- virtual RefPtr<DefaultStmt> VisitDefaultStmt(DefaultStmt* stmt) override
+ void visit(DefaultStmt* stmt)
{
auto switchStmt = FindOuterStmt<SwitchStmt>();
if (!switchStmt)
@@ -1628,33 +1705,31 @@ namespace Slang
getSink()->diagnose(stmt, Diagnostics::defaultOutsideSwitch);
}
stmt->parentStmt = switchStmt;
- return stmt;
}
- virtual RefPtr<StatementSyntaxNode> VisitIfStatement(IfStatementSyntaxNode *stmt) override
+ void visit(IfStatementSyntaxNode *stmt)
{
- auto condition = stmt->Predicate;
- condition = CheckTerm(condition);
- condition = Coerce(ExpressionType::GetBool(), condition);
+ stmt->Predicate = checkPredicateExpr(stmt->Predicate);
+ checkStmt(stmt->PositiveStatement);
+ checkStmt(stmt->NegativeStatement);
+ }
- stmt->Predicate = condition;
+ void visit(UnparsedStmt*)
+ {
+ // Nothing to do
+ }
-#if 0
- if (stmt->Predicate != NULL)
- stmt->Predicate = stmt->Predicate->Accept(this).As<ExpressionSyntaxNode>();
- if (!stmt->Predicate->Type->Equals(ExpressionType::GetError())
- && (!stmt->Predicate->Type->Equals(ExpressionType::GetInt()) &&
- !stmt->Predicate->Type->Equals(ExpressionType::GetBool())))
- getSink()->diagnose(stmt, Diagnostics::ifPredicateTypeError);
-#endif
- if (stmt->PositiveStatement != NULL)
- stmt->PositiveStatement->Accept(this);
+ void visit(EmptyStatementSyntaxNode*)
+ {
+ // Nothing to do
+ }
- if (stmt->NegativeStatement != NULL)
- stmt->NegativeStatement->Accept(this);
- return stmt;
+ void visit(DiscardStatementSyntaxNode*)
+ {
+ // Nothing to do
}
- virtual RefPtr<StatementSyntaxNode> VisitReturnStatement(ReturnStatementSyntaxNode *stmt) override
+
+ void visit(ReturnStatementSyntaxNode *stmt)
{
if (!stmt->Expression)
{
@@ -1663,7 +1738,7 @@ namespace Slang
}
else
{
- stmt->Expression = stmt->Expression->Accept(this).As<ExpressionSyntaxNode>();
+ stmt->Expression = CheckTerm(stmt->Expression);
if (!stmt->Expression->Type->Equals(ExpressionType::Error.Ptr()))
{
if (function)
@@ -1680,7 +1755,6 @@ namespace Slang
}
}
}
- return stmt;
}
IntegerLiteralValue GetMinBound(RefPtr<IntVal> val)
@@ -1758,7 +1832,7 @@ namespace Slang
}
}
- virtual RefPtr<Variable> VisitDeclrVariable(Variable* varDecl)
+ void visit(Variable* varDecl)
{
TypeExp typeExp = CheckUsableType(varDecl->Type);
#if 0
@@ -1806,86 +1880,21 @@ namespace Slang
}
varDecl->SetCheckState(DeclCheckState::Checked);
-
- return varDecl;
}
- virtual RefPtr<StatementSyntaxNode> VisitWhileStatement(WhileStatementSyntaxNode *stmt) override
+ void visit(WhileStatementSyntaxNode *stmt)
{
PushOuterStmt(stmt);
- stmt->Predicate = stmt->Predicate->Accept(this).As<ExpressionSyntaxNode>();
- if (!stmt->Predicate->Type->Equals(ExpressionType::GetError()) &&
- !stmt->Predicate->Type->Equals(ExpressionType::GetInt()) &&
- !stmt->Predicate->Type->Equals(ExpressionType::GetBool()))
- getSink()->diagnose(stmt, Diagnostics::whilePredicateTypeError2);
-
- stmt->Statement->Accept(this);
+ stmt->Predicate = checkPredicateExpr(stmt->Predicate);
+ checkStmt(stmt->Statement);
PopOuterStmt(stmt);
- return stmt;
}
- virtual RefPtr<StatementSyntaxNode> VisitExpressionStatement(ExpressionStatementSyntaxNode *stmt) override
+ void visit(ExpressionStatementSyntaxNode *stmt)
{
- stmt->Expression = stmt->Expression->Accept(this).As<ExpressionSyntaxNode>();
- return stmt;
+ stmt->Expression = CheckExpr(stmt->Expression);
}
- virtual RefPtr<ExpressionSyntaxNode> VisitOperatorExpression(OperatorExpressionSyntaxNode *expr) override
- {
-#if 0
-
- for (int i = 0; i < expr->Arguments.Count(); i++)
- expr->Arguments[i] = expr->Arguments[i]->Accept(this).As<ExpressionSyntaxNode>();
- auto & leftType = expr->Arguments[0]->Type;
- QualType rightType;
- if (expr->Arguments.Count() == 2)
- rightType = expr->Arguments[1]->Type;
- RefPtr<ExpressionType> matchedType;
- auto checkAssign = [&]()
- {
- if (!leftType.IsLeftValue &&
- !leftType->Equals(ExpressionType::Error.Ptr()))
- getSink()->diagnose(expr->Arguments[0].Ptr(), Diagnostics::assignNonLValue);
- if (expr->Operator == Operator::AndAssign ||
- expr->Operator == Operator::OrAssign ||
- expr->Operator == Operator::XorAssign ||
- expr->Operator == Operator::LshAssign ||
- expr->Operator == Operator::RshAssign)
- {
-#if 0
- if (!(leftType->IsIntegral() && rightType->IsIntegral()))
- {
- // TODO(tfoley): This diagnostic shouldn't be handled here
-// getSink()->diagnose(expr, Diagnostics::bitOperationNonIntegral);
- }
-#endif
- }
- // TODO(tfoley): Need to actual insert coercion here...
- if(CanCoerce(leftType, expr->Type))
- expr->Type = leftType;
- else
- expr->Type = ExpressionType::Error;
- };
-#if 0
- if (expr->Operator == Operator::Assign)
- {
- expr->Type = rightType;
- checkAssign();
- }
- else
-#endif
- {
- expr->FunctionExpr = CheckExpr(expr->FunctionExpr);
- CheckInvokeExprWithCheckedOperands(expr);
- if (expr->Operator > Operator::Assign)
- checkAssign();
- }
- return expr;
-#endif
-
- // Treat operator application just like a function call
- return VisitInvokeExpression(expr);
- }
- virtual RefPtr<ExpressionSyntaxNode> VisitConstantExpression(ConstantExpressionSyntaxNode *expr) override
+ RefPtr<ExpressionSyntaxNode> visit(ConstantExpressionSyntaxNode *expr)
{
// The expression might already have a type, determined by its suffix
if(expr->Type.type)
@@ -2053,7 +2062,7 @@ namespace Slang
{
auto varDecl = varRef.getDecl();
- switch(sourceLanguage)
+ switch(getSourceLanguage())
{
case SourceLanguage::Slang:
case SourceLanguage::HLSL:
@@ -2202,7 +2211,7 @@ namespace Slang
return DeclRefType::Create(declRef)->As<VectorExpressionType>();
}
- virtual RefPtr<ExpressionSyntaxNode> VisitIndexExpression(IndexExpressionSyntaxNode* subscriptExpr) override
+ RefPtr<ExpressionSyntaxNode> visit(IndexExpressionSyntaxNode* subscriptExpr)
{
auto baseExpr = subscriptExpr->BaseExpression;
baseExpr = CheckExpr(baseExpr);
@@ -2408,7 +2417,7 @@ namespace Slang
//
- virtual void VisitExtensionDecl(ExtensionDecl* decl) override
+ void visit(ExtensionDecl* decl)
{
if (decl->IsChecked(DeclCheckState::Checked)) return;
@@ -2451,7 +2460,7 @@ namespace Slang
decl->SetCheckState(DeclCheckState::Checked);
}
- virtual void VisitConstructorDecl(ConstructorDecl* decl) override
+ void visit(ConstructorDecl* decl)
{
if (decl->IsChecked(DeclCheckState::Checked)) return;
decl->SetCheckState(DeclCheckState::CheckingHeader);
@@ -2467,7 +2476,7 @@ namespace Slang
}
- virtual void visitSubscriptDecl(SubscriptDecl* decl) override
+ void visit(SubscriptDecl* decl)
{
if (decl->IsChecked(DeclCheckState::Checked)) return;
decl->SetCheckState(DeclCheckState::CheckingHeader);
@@ -2484,7 +2493,7 @@ namespace Slang
decl->SetCheckState(DeclCheckState::Checked);
}
- virtual void visitAccessorDecl(AccessorDecl* decl) override
+ void visit(AccessorDecl* decl)
{
// TODO: check the body!
@@ -4337,7 +4346,7 @@ namespace Slang
}
}
- RefPtr<ExpressionSyntaxNode> VisitGenericApp(GenericAppExpr * genericAppExpr) override
+ RefPtr<ExpressionSyntaxNode> visit(GenericAppExpr * genericAppExpr)
{
// We are applying a generic to arguments, but there might be multiple generic
// declarations with the same name, so this becomes a specialized case of
@@ -4488,7 +4497,7 @@ namespace Slang
#endif
}
- RefPtr<ExpressionSyntaxNode> VisitSharedTypeExpr(SharedTypeExpr* expr) override
+ RefPtr<ExpressionSyntaxNode> visit(SharedTypeExpr* expr)
{
if (!expr->Type.Ptr())
{
@@ -4503,7 +4512,12 @@ namespace Slang
RefPtr<ExpressionSyntaxNode> CheckExpr(RefPtr<ExpressionSyntaxNode> expr)
{
- return expr->Accept(this).As<ExpressionSyntaxNode>();
+ auto term = CheckTerm(expr);
+
+ // TODO(tfoley): Need a step here to ensure that the term actually
+ // resolves to a (single) expression with a real type.
+
+ return term;
}
RefPtr<ExpressionSyntaxNode> CheckInvokeExprWithCheckedOperands(InvokeExpressionSyntaxNode *expr)
@@ -4541,7 +4555,7 @@ namespace Slang
return rs;
}
- virtual RefPtr<ExpressionSyntaxNode> VisitInvokeExpression(InvokeExpressionSyntaxNode *expr) override
+ RefPtr<ExpressionSyntaxNode> visit(InvokeExpressionSyntaxNode *expr)
{
// check the base expression first
expr->FunctionExpr = CheckExpr(expr->FunctionExpr);
@@ -4556,7 +4570,7 @@ namespace Slang
}
- virtual RefPtr<ExpressionSyntaxNode> VisitVarExpression(VarExpressionSyntaxNode *expr) override
+ RefPtr<ExpressionSyntaxNode> visit(VarExpressionSyntaxNode *expr)
{
// If we've already resolved this expression, don't try again.
if (expr->declRef)
@@ -4577,9 +4591,10 @@ namespace Slang
return expr;
}
- virtual RefPtr<ExpressionSyntaxNode> VisitTypeCastExpression(TypeCastExpressionSyntaxNode * expr) override
+
+ RefPtr<ExpressionSyntaxNode> visit(TypeCastExpressionSyntaxNode * expr)
{
- expr->Expression = expr->Expression->Accept(this).As<ExpressionSyntaxNode>();
+ expr->Expression = CheckTerm(expr->Expression);
auto targetType = CheckProperType(expr->TargetType);
expr->TargetType = targetType;
@@ -4608,6 +4623,8 @@ namespace Slang
return expr;
}
}
+ // TODO: other cases? Should we allow a cast to succeeed whenever
+ // a single-argument constructor for the target type would work?
fail:
// Default: in no other case succeds, then the cast failed and we emit a diagnostic.
@@ -4648,6 +4665,34 @@ namespace Slang
&typeResult);
}
+ //
+ // Some syntax nodes should not occur in the concrete input syntax,
+ // and will only appear *after* checking is complete. We need to
+ // deal with this cases here, even if they are no-ops.
+ //
+
+ RefPtr<ExpressionSyntaxNode> visit(DerefExpr* expr)
+ {
+ assert(!"unexpected");
+ return expr;
+ }
+
+ RefPtr<ExpressionSyntaxNode> visit(SwizzleExpr* expr)
+ {
+ assert(!"unexpected");
+ return expr;
+ }
+
+ RefPtr<ExpressionSyntaxNode> visit(OverloadedExpr* expr)
+ {
+ assert(!"unexpected");
+ return expr;
+ }
+
+ //
+ //
+ //
+
RefPtr<ExpressionSyntaxNode> MaybeDereference(RefPtr<ExpressionSyntaxNode> inExpr)
{
RefPtr<ExpressionSyntaxNode> expr = inExpr;
@@ -4782,7 +4827,7 @@ namespace Slang
}
- virtual RefPtr<ExpressionSyntaxNode> VisitMemberExpression(MemberExpressionSyntaxNode * expr) override
+ RefPtr<ExpressionSyntaxNode> visit(MemberExpressionSyntaxNode * expr)
{
expr->BaseExpression = CheckExpr(expr->BaseExpression);
@@ -4881,7 +4926,7 @@ namespace Slang
//
- virtual RefPtr<ExpressionSyntaxNode> visitInitializerListExpr(InitializerListExpr* expr) override
+ RefPtr<ExpressionSyntaxNode> visit(InitializerListExpr* expr)
{
// When faced with an initializer list, we first just check the sub-expressions blindly.
// Actually making them conform to a desired type will wait for when we know the desired
@@ -4927,7 +4972,12 @@ namespace Slang
}
}
- virtual void visitImportDecl(ImportDecl* decl) override
+ void visit(EmptyDecl* /*decl*/)
+ {
+ // nothing to do
+ }
+
+ void visit(ImportDecl* decl)
{
if(decl->IsChecked(DeclCheckState::Checked))
return;
@@ -4957,12 +5007,15 @@ namespace Slang
}
};
- SyntaxVisitor* CreateSemanticsVisitor(
- DiagnosticSink* err,
- CompileRequest* request,
+ void checkTranslationUnit(
TranslationUnitRequest* translationUnit)
{
- return new SemanticsVisitor(err, request, translationUnit);
+ SemanticsVisitor visitor(
+ &translationUnit->compileRequest->mSink,
+ translationUnit->compileRequest,
+ translationUnit);
+
+ visitor.checkDecl(translationUnit->SyntaxNode);
}
//
diff --git a/source/slang/compiler.h b/source/slang/compiler.h
index a6f3eee0e..b3bcd7ba1 100644
--- a/source/slang/compiler.h
+++ b/source/slang/compiler.h
@@ -224,9 +224,6 @@ namespace Slang
void parseTranslationUnit(
TranslationUnitRequest* translationUnit);
- void CompileRequest::checkTranslationUnit(
- TranslationUnitRequest* translationUnit);
-
void checkAllTranslationUnits();
int executeActionsInner();
diff --git a/source/slang/decl-defs.h b/source/slang/decl-defs.h
new file mode 100644
index 000000000..f2405b0f0
--- /dev/null
+++ b/source/slang/decl-defs.h
@@ -0,0 +1,232 @@
+// decl-defs.h
+
+// Syntax class definitions for declarations.
+
+// A group of declarations that should be treated as a unit
+SYNTAX_CLASS(DeclGroup, DeclBase)
+ SYNTAX_FIELD(List<RefPtr<Decl>>, decls)
+END_SYNTAX_CLASS()
+
+// A "container" decl is a parent to other declarations
+ABSTRACT_SYNTAX_CLASS(ContainerDecl, Decl)
+ SYNTAX_FIELD(List<RefPtr<Decl>>, Members)
+
+ RAW(
+ template<typename T>
+ FilteredMemberList<T> getMembersOfType()
+ {
+ return FilteredMemberList<T>(Members);
+ }
+
+
+ // Dictionary for looking up members by name.
+ // This is built on demand before performing lookup.
+ Dictionary<String, Decl*> memberDictionary;
+
+ // Whether the `memberDictionary` is valid.
+ // Should be set to `false` if any members get added/remoed.
+ bool memberDictionaryIsValid = false;
+
+ // A list of transparent members, to be used in lookup
+ // Note: this is only valid if `memberDictionaryIsValid` is true
+ List<TransparentMemberInfo> transparentMembers;
+ )
+END_SYNTAX_CLASS()
+
+// Base class for all variable-like declarations
+ABSTRACT_SYNTAX_CLASS(VarDeclBase, Decl)
+
+ // Type of the variable
+ SYNTAX_FIELD(TypeExp, Type)
+
+ RAW(
+ ExpressionType* getType() { return Type.type.Ptr(); }
+ )
+
+ // Initializer expression (optional)
+ SYNTAX_FIELD(RefPtr<ExpressionSyntaxNode>, Expr)
+END_SYNTAX_CLASS()
+
+
+// A field of a `struct` type
+SIMPLE_SYNTAX_CLASS(StructField, VarDeclBase)
+
+// An `AggTypeDeclBase` captures the shared functionality
+// between true aggregate type declarations and extension
+// declarations:
+//
+// - Both can container members (they are `ContainerDecl`s)
+// - Both can have declared bases
+// - Both expose a `this` variable in their body
+//
+ABSTRACT_SYNTAX_CLASS(AggTypeDeclBase, ContainerDecl)
+END_SYNTAX_CLASS()
+
+// An extension to apply to an existing type
+SYNTAX_CLASS(ExtensionDecl, AggTypeDeclBase)
+ SYNTAX_FIELD(TypeExp, targetType)
+
+ // next extension attached to the same nominal type
+ DECL_FIELD(ExtensionDecl*, nextCandidateExtension RAW(= nullptr))
+END_SYNTAX_CLASS()
+
+// Declaration of a type that represents some sort of aggregate
+ABSTRACT_SYNTAX_CLASS(AggTypeDecl, AggTypeDeclBase)
+
+RAW(
+ // extensions that might apply to this declaration
+ ExtensionDecl* candidateExtensions = nullptr;
+ FilteredMemberList<StructField> GetFields()
+ {
+ return getMembersOfType<StructField>();
+ }
+ StructField* FindField(String name)
+ {
+ for (auto field : GetFields())
+ {
+ if (field->Name.Content == name)
+ return field.Ptr();
+ }
+ return nullptr;
+ }
+ int FindFieldIndex(String name)
+ {
+ int index = 0;
+ for (auto field : GetFields())
+ {
+ if (field->Name.Content == name)
+ return index;
+ index++;
+ }
+ return -1;
+ }
+ )
+END_SYNTAX_CLASS()
+
+SIMPLE_SYNTAX_CLASS(StructSyntaxNode, AggTypeDecl)
+
+SIMPLE_SYNTAX_CLASS(ClassSyntaxNode, AggTypeDecl)
+
+// An interface which other types can conform to
+SIMPLE_SYNTAX_CLASS(InterfaceDecl, AggTypeDecl)
+
+// A kind of pseudo-member that represents an explicit
+// or implicit inheritance relationship.
+//
+SYNTAX_CLASS(InheritanceDecl, Decl)
+ // The type expression as written
+ SYNTAX_FIELD(TypeExp, base)
+END_SYNTAX_CLASS()
+
+// TODO: may eventually need sub-classes for explicit/direct vs. implicit/indirect inheritance
+
+
+// A declaration that represents a simple (non-aggregate) type
+//
+// TODO: probably all types will be aggregate decls eventually,
+// so that we can easily store conformances/constraints on type variables
+ABSTRACT_SYNTAX_CLASS(SimpleTypeDecl, Decl)
+END_SYNTAX_CLASS()
+
+// A `typedef` declaration
+SYNTAX_CLASS(TypeDefDecl, SimpleTypeDecl)
+ SYNTAX_FIELD(TypeExp, Type)
+END_SYNTAX_CLASS()
+
+// A scope for local declarations (e.g., as part of a statement)
+SIMPLE_SYNTAX_CLASS(ScopeDecl, ContainerDecl)
+
+SIMPLE_SYNTAX_CLASS(ParameterSyntaxNode, VarDeclBase)
+
+// Base class for things that have parameter lists and can thus be applied to arguments ("called")
+ABSTRACT_SYNTAX_CLASS(CallableDecl, ContainerDecl)
+ RAW(
+ FilteredMemberList<ParameterSyntaxNode> GetParameters()
+ {
+ return getMembersOfType<ParameterSyntaxNode>();
+ })
+
+ SYNTAX_FIELD(TypeExp, ReturnType)
+END_SYNTAX_CLASS()
+
+// Base class for callable things that may also have a body that is evaluated to produce their result
+ABSTRACT_SYNTAX_CLASS(FunctionDeclBase, CallableDecl)
+ SYNTAX_FIELD(RefPtr<StatementSyntaxNode>, Body)
+END_SYNTAX_CLASS()
+
+// A constructor/initializer to create instances of a type
+SIMPLE_SYNTAX_CLASS(ConstructorDecl, FunctionDeclBase)
+
+// A subscript operation used to index instances of a type
+SIMPLE_SYNTAX_CLASS(SubscriptDecl, CallableDecl)
+
+// An "accessor" for a subscript or property
+SIMPLE_SYNTAX_CLASS(AccessorDecl, FunctionDeclBase)
+
+SIMPLE_SYNTAX_CLASS(GetterDecl, AccessorDecl)
+SIMPLE_SYNTAX_CLASS(SetterDecl, AccessorDecl)
+
+SIMPLE_SYNTAX_CLASS(FunctionSyntaxNode, FunctionDeclBase)
+
+SIMPLE_SYNTAX_CLASS(Variable, VarDeclBase);
+
+// A "module" of code (essentiately, a single translation unit)
+// that provides a scope for some number of declarations.
+SIMPLE_SYNTAX_CLASS(ProgramSyntaxNode, ContainerDecl)
+
+SYNTAX_CLASS(ImportDecl, Decl)
+ // The name of the module we are trying to import
+ FIELD(Token, nameToken)
+
+ // The scope that we want to import into
+ FIELD(RefPtr<Scope>, scope)
+
+ // The module that actually got imported
+ DECL_FIELD(RefPtr<ProgramSyntaxNode>, importedModuleDecl)
+END_SYNTAX_CLASS()
+
+// A generic declaration, parameterized on types/values
+SYNTAX_CLASS(GenericDecl, ContainerDecl)
+ // The decl that is genericized...
+ SYNTAX_FIELD(RefPtr<Decl>, inner)
+END_SYNTAX_CLASS()
+
+SYNTAX_CLASS(GenericTypeParamDecl, SimpleTypeDecl)
+ // The bound for the type parameter represents a trait that any
+ // type used as this parameter must conform to
+// TypeExp bound;
+
+ // The "initializer" for the parameter represents a default value
+ SYNTAX_FIELD(TypeExp, initType)
+END_SYNTAX_CLASS()
+
+// A constraint placed as part of a generic declaration
+SYNTAX_CLASS(GenericTypeConstraintDecl, Decl)
+ // A type constraint like `T : U` is constraining `T` to be "below" `U`
+ // on a lattice of types. This may not be a subtyping relationship
+ // per se, but it makes sense to use that terminology here, so we
+ // think of these fields as the sub-type and sup-ertype, respectively.
+ SYNTAX_FIELD(TypeExp, sub)
+ SYNTAX_FIELD(TypeExp, sup)
+END_SYNTAX_CLASS()
+
+SIMPLE_SYNTAX_CLASS(GenericValueParamDecl, VarDeclBase)
+
+// Declaration of a user-defined modifier
+SYNTAX_CLASS(ModifierDecl, Decl)
+ // The name of the C++ class to instantiate
+ // (this is a reference to a class in the compiler source code,
+ // and not the user's source code)
+ FIELD(Token, classNameToken)
+END_SYNTAX_CLASS()
+
+// An empty declaration (which might still have modifiers attached).
+//
+// An empty declaration is uncommon in HLSL, but
+// in GLSL it is often used at the global scope
+// to declare metadata that logically belongs
+// to the entry point, e.g.:
+//
+// layout(local_size_x = 16) in;
+//
+SIMPLE_SYNTAX_CLASS(EmptyDecl, Decl)
diff --git a/source/slang/expr-defs.h b/source/slang/expr-defs.h
new file mode 100644
index 000000000..59bad37e7
--- /dev/null
+++ b/source/slang/expr-defs.h
@@ -0,0 +1,109 @@
+// expr-defs.h
+
+// Syntax class definitions for expressions.
+
+
+// Base class for expressions that will reference declarations
+ABSTRACT_SYNTAX_CLASS(DeclRefExpr, ExpressionSyntaxNode)
+
+// The scope in which to perform lookup
+ FIELD(RefPtr<Scope>, scope)
+
+ // The declaration of the symbol being referenced
+ DECL_FIELD(DeclRef<Decl>, declRef)
+
+ // The name of the symbol being referenced
+ FIELD(String, name)
+END_SYNTAX_CLASS()
+
+SIMPLE_SYNTAX_CLASS(VarExpressionSyntaxNode, DeclRefExpr)
+
+// An expression that references an overloaded set of declarations
+// having the same name.
+SYNTAX_CLASS(OverloadedExpr, ExpressionSyntaxNode)
+
+ // Optional: the base expression is this overloaded result
+ // arose from a member-reference expression.
+ SYNTAX_FIELD(RefPtr<ExpressionSyntaxNode>, base)
+
+ // The lookup result that was ambiguous
+ FIELD(LookupResult, lookupResult2)
+END_SYNTAX_CLASS()
+
+SYNTAX_CLASS(ConstantExpressionSyntaxNode, ExpressionSyntaxNode)
+ FIELD(Token, token)
+
+ RAW(
+ enum class ConstantType
+ {
+ Int,
+ Bool,
+ Float,
+ String,
+ };
+ ConstantType ConstType;
+ union
+ {
+ IntegerLiteralValue integerValue;
+ FloatingPointLiteralValue floatingPointValue;
+ };
+ String stringValue;
+ )
+END_SYNTAX_CLASS()
+
+// An initializer list, e.g. `{ 1, 2, 3 }`
+SYNTAX_CLASS(InitializerListExpr, ExpressionSyntaxNode)
+ SYNTAX_FIELD(List<RefPtr<ExpressionSyntaxNode>>, args)
+END_SYNTAX_CLASS()
+
+// A base expression being applied to arguments: covers
+// both ordinary `()` function calls and `<>` generic application
+ABSTRACT_SYNTAX_CLASS(AppExprBase, ExpressionSyntaxNode)
+ SYNTAX_FIELD(RefPtr<ExpressionSyntaxNode>, FunctionExpr)
+ SYNTAX_FIELD(List<RefPtr<ExpressionSyntaxNode>>, Arguments)
+END_SYNTAX_CLASS()
+
+SIMPLE_SYNTAX_CLASS(InvokeExpressionSyntaxNode, AppExprBase)
+
+SIMPLE_SYNTAX_CLASS(OperatorExpressionSyntaxNode, InvokeExpressionSyntaxNode)
+
+SIMPLE_SYNTAX_CLASS(InfixExpr , OperatorExpressionSyntaxNode)
+SIMPLE_SYNTAX_CLASS(PrefixExpr , OperatorExpressionSyntaxNode)
+SIMPLE_SYNTAX_CLASS(PostfixExpr, OperatorExpressionSyntaxNode)
+
+SYNTAX_CLASS(IndexExpressionSyntaxNode, ExpressionSyntaxNode)
+ SYNTAX_FIELD(RefPtr<ExpressionSyntaxNode>, BaseExpression)
+ SYNTAX_FIELD(RefPtr<ExpressionSyntaxNode>, IndexExpression)
+END_SYNTAX_CLASS()
+
+SYNTAX_CLASS(MemberExpressionSyntaxNode, DeclRefExpr)
+ SYNTAX_FIELD(RefPtr<ExpressionSyntaxNode>, BaseExpression)
+END_SYNTAX_CLASS()
+
+SYNTAX_CLASS(SwizzleExpr, ExpressionSyntaxNode)
+ SYNTAX_FIELD(RefPtr<ExpressionSyntaxNode>, base)
+ FIELD(int, elementCount)
+ FIELD(int, elementIndices[4])
+END_SYNTAX_CLASS()
+
+// A dereference of a pointer or pointer-like type
+SYNTAX_CLASS(DerefExpr, ExpressionSyntaxNode)
+ SYNTAX_FIELD(RefPtr<ExpressionSyntaxNode>, base)
+END_SYNTAX_CLASS()
+
+SYNTAX_CLASS(TypeCastExpressionSyntaxNode, ExpressionSyntaxNode)
+ SYNTAX_FIELD(TypeExp, TargetType)
+ SYNTAX_FIELD(RefPtr<ExpressionSyntaxNode>, Expression)
+END_SYNTAX_CLASS()
+
+SIMPLE_SYNTAX_CLASS(SelectExpressionSyntaxNode, OperatorExpressionSyntaxNode)
+
+SIMPLE_SYNTAX_CLASS(GenericAppExpr, AppExprBase)
+
+// An expression representing re-use of the syntax for a type in more
+// than once conceptually-distinct declaration
+SYNTAX_CLASS(SharedTypeExpr, ExpressionSyntaxNode)
+ // The underlying type expression that we want to share
+ SYNTAX_FIELD(TypeExp, base)
+END_SYNTAX_CLASS()
+
diff --git a/source/slang/lookup.h b/source/slang/lookup.h
index 52eaa9804..60e39bfcf 100644
--- a/source/slang/lookup.h
+++ b/source/slang/lookup.h
@@ -5,7 +5,7 @@
namespace Slang {
-class SemanticsVisitor;
+struct SemanticsVisitor;
// Take an existing lookup result and refine it to only include
// results that pass the given `LookupMask`.
@@ -31,7 +31,6 @@ LookupResult LookUpLocal(
// TODO: this belongs somewhere else
-class SemanticsVisitor;
QualType getTypeForDeclRef(
SemanticsVisitor* sema,
DiagnosticSink* sink,
diff --git a/source/slang/modifier-defs.h b/source/slang/modifier-defs.h
new file mode 100644
index 000000000..a1da47fb7
--- /dev/null
+++ b/source/slang/modifier-defs.h
@@ -0,0 +1,271 @@
+// modifier-defs.h
+
+// Syntax class definitions for modifiers.
+
+// Simple modifiers have no state beyond their identity
+#define SIMPLE_MODIFIER(NAME) \
+ SIMPLE_SYNTAX_CLASS(NAME##Modifier, Modifier)
+
+SIMPLE_MODIFIER(Uniform);
+SIMPLE_MODIFIER(In);
+SIMPLE_MODIFIER(Out);
+SIMPLE_MODIFIER(Const);
+SIMPLE_MODIFIER(Instance);
+SIMPLE_MODIFIER(Builtin);
+SIMPLE_MODIFIER(Inline);
+SIMPLE_MODIFIER(Public);
+SIMPLE_MODIFIER(Require);
+SIMPLE_MODIFIER(Param);
+SIMPLE_MODIFIER(Extern);
+SIMPLE_MODIFIER(Input);
+SIMPLE_MODIFIER(Transparent);
+SIMPLE_MODIFIER(FromStdLib);
+SIMPLE_MODIFIER(Prefix);
+SIMPLE_MODIFIER(Postfix);
+SIMPLE_MODIFIER(Exported);
+
+#undef SIMPLE_MODIFIER
+
+// Base class for modifiers that mark something as "intrinsic"
+// and thus lacking a direct implementation in the language.
+ABSTRACT_SYNTAX_CLASS(IntrinsicModifierBase, Modifier)
+END_SYNTAX_CLASS()
+
+// A modifier that marks something as one of a small set of
+// truly intrinsic operations that the compiler knows about
+// directly.
+SYNTAX_CLASS(IntrinsicOpModifier, IntrinsicModifierBase)
+
+ // token that names the intrinsic op
+ FIELD(Token, opToken)
+
+ // The opcode for the intrinsic operation
+ FIELD_INIT(IntrinsicOp, op, IntrinsicOp::Unknown)
+END_SYNTAX_CLASS()
+
+// A modifier that marks something as an intrinsic function,
+// for some subset of targets.
+SYNTAX_CLASS(TargetIntrinsicModifier, IntrinsicModifierBase)
+ // Token that names the target that the operation
+ // is an intrisic for.
+ FIELD(Token, targetToken)
+
+ // A custom definition for the operation
+ FIELD(Token, definitionToken)
+END_SYNTAX_CLASS()
+
+SIMPLE_SYNTAX_CLASS(InOutModifier, OutModifier)
+
+// This is a special sentinel modifier that gets added
+// to the list when we have multiple variable declarations
+// all sharing the same modifiers:
+//
+// static uniform int a : FOO, *b : register(x0);
+//
+// In this case both `a` and `b` share the syntax
+// for part of their modifier list, but then have
+// their own modifiers as well:
+//
+// a: SemanticModifier("FOO") --> SharedModifiers --> StaticModifier --> UniformModifier
+// /
+// b: RegisterModifier("x0") /
+//
+SIMPLE_SYNTAX_CLASS(SharedModifiers, Modifier)
+
+// A GLSL `layout` modifier
+//
+// We use a distinct modifier for each key that
+// appears within the `layout(...)` construct,
+// and each key might have an optional value token.
+//
+// TODO: We probably want a notion of "modifier groups"
+// so that we can recover good source location info
+// for modifiers that were part of the same vs.
+// different constructs.
+ABSTRACT_SYNTAX_CLASS(GLSLLayoutModifier, Modifier)
+
+ // The token used to introduce the modifier is stored
+ // as the `nameToken` field.
+
+ // TODO: may want to accept a full expression here
+ FIELD(Token, valToken)
+END_SYNTAX_CLASS()
+
+// We divide GLSL `layout` modifiers into those we have parsed
+// (in the sense of having some notion of their semantics), and
+// those we have not.
+ABSTRACT_SYNTAX_CLASS(GLSLParsedLayoutModifier , GLSLLayoutModifier)
+END_SYNTAX_CLASS()
+
+SIMPLE_SYNTAX_CLASS(GLSLUnparsedLayoutModifier , GLSLLayoutModifier)
+
+// Specific cases for known GLSL `layout` modifiers that we need to work with
+SIMPLE_SYNTAX_CLASS(GLSLConstantIDLayoutModifier , GLSLParsedLayoutModifier)
+SIMPLE_SYNTAX_CLASS(GLSLBindingLayoutModifier , GLSLParsedLayoutModifier)
+SIMPLE_SYNTAX_CLASS(GLSLSetLayoutModifier , GLSLParsedLayoutModifier)
+SIMPLE_SYNTAX_CLASS(GLSLLocationLayoutModifier , GLSLParsedLayoutModifier)
+
+// A catch-all for single-keyword modifiers
+SIMPLE_SYNTAX_CLASS(SimpleModifier, Modifier)
+
+// Some GLSL-specific modifiers
+SIMPLE_SYNTAX_CLASS(GLSLBufferModifier , SimpleModifier)
+SIMPLE_SYNTAX_CLASS(GLSLWriteOnlyModifier, SimpleModifier)
+SIMPLE_SYNTAX_CLASS(GLSLReadOnlyModifier , SimpleModifier)
+SIMPLE_SYNTAX_CLASS(GLSLPatchModifier , SimpleModifier)
+
+// Indicates that this is a variable declaration that corresponds to
+// a parameter block declaration in the source program.
+SIMPLE_SYNTAX_CLASS(ImplicitParameterBlockVariableModifier , Modifier)
+
+// Indicates that this is a type that corresponds to the element
+// type of a parameter block declaration in the source program.
+SIMPLE_SYNTAX_CLASS(ImplicitParameterBlockElementTypeModifier, Modifier)
+
+// An HLSL semantic
+ABSTRACT_SYNTAX_CLASS(HLSLSemantic, Modifier)
+ FIELD(Token, name)
+END_SYNTAX_CLASS()
+
+// An HLSL semantic that affects layout
+SYNTAX_CLASS(HLSLLayoutSemantic, HLSLSemantic)
+
+ FIELD(Token, registerName)
+ FIELD(Token, componentMask)
+END_SYNTAX_CLASS()
+
+// An HLSL `register` semantic
+SIMPLE_SYNTAX_CLASS(HLSLRegisterSemantic, HLSLLayoutSemantic)
+
+// TODO(tfoley): `packoffset`
+SIMPLE_SYNTAX_CLASS(HLSLPackOffsetSemantic, HLSLLayoutSemantic)
+
+// An HLSL semantic that just associated a declaration with a semantic name
+SIMPLE_SYNTAX_CLASS(HLSLSimpleSemantic, HLSLSemantic)
+
+// GLSL
+
+// Directives that came in via the preprocessor, but
+// that we need to keep around for later steps
+SIMPLE_SYNTAX_CLASS(GLSLPreprocessorDirective, Modifier)
+
+// A GLSL `#version` directive
+SYNTAX_CLASS(GLSLVersionDirective, GLSLPreprocessorDirective)
+
+ // Token giving the version number to use
+ FIELD(Token, versionNumberToken)
+
+ // Optional token giving the sub-profile to be used
+ FIELD(Token, glslProfileToken)
+END_SYNTAX_CLASS()
+
+// A GLSL `#extension` directive
+SYNTAX_CLASS(GLSLExtensionDirective, GLSLPreprocessorDirective)
+
+ // Token giving the version number to use
+ FIELD(Token, extensionNameToken)
+
+ // Optional token giving the sub-profile to be used
+ FIELD(Token, dispositionToken)
+END_SYNTAX_CLASS()
+
+SYNTAX_CLASS(ParameterBlockReflectionName, Modifier)
+ FIELD(Token, nameToken)
+END_SYNTAX_CLASS()
+
+// A modifier that indicates a built-in base type (e.g., `float`)
+SYNTAX_CLASS(BuiltinTypeModifier, Modifier)
+ FIELD(BaseType, tag)
+END_SYNTAX_CLASS()
+
+// A modifier that indicates a built-in type that isn't a base type (e.g., `vector`)
+//
+// TODO(tfoley): This deserves a better name than "magic"
+SYNTAX_CLASS(MagicTypeModifier, Modifier)
+ FIELD(String, name)
+ FIELD(uint32_t, tag)
+END_SYNTAX_CLASS()
+
+// Modifiers that affect the storage layout for matrices
+SIMPLE_SYNTAX_CLASS(MatrixLayoutModifier, Modifier)
+
+// Modifiers that specify row- and column-major layout, respectively
+SIMPLE_SYNTAX_CLASS(RowMajorLayoutModifier, MatrixLayoutModifier)
+SIMPLE_SYNTAX_CLASS(ColumnMajorLayoutModifier, MatrixLayoutModifier)
+
+// The HLSL flavor of those modifiers
+SIMPLE_SYNTAX_CLASS(HLSLRowMajorLayoutModifier, RowMajorLayoutModifier)
+SIMPLE_SYNTAX_CLASS(HLSLColumnMajorLayoutModifier, ColumnMajorLayoutModifier)
+
+// The GLSL flavor of those modifiers
+//
+// Note(tfoley): The GLSL versions of these modifiers are "backwards"
+// in the sense that when a GLSL programmer requests row-major layout,
+// we actually interpret that as requesting column-major. This makes
+// sense because we interpret matrix conventions backwards from how
+// GLSL specifies them.
+SIMPLE_SYNTAX_CLASS(GLSLRowMajorLayoutModifier, ColumnMajorLayoutModifier)
+SIMPLE_SYNTAX_CLASS(GLSLColumnMajorLayoutModifier, RowMajorLayoutModifier)
+
+// More HLSL Keyword
+
+// HLSL `nointerpolation` modifier
+SIMPLE_SYNTAX_CLASS(HLSLNoInterpolationModifier, Modifier)
+
+// HLSL `linear` modifier
+SIMPLE_SYNTAX_CLASS(HLSLLinearModifier, Modifier)
+
+// HLSL `sample` modifier
+SIMPLE_SYNTAX_CLASS(HLSLSampleModifier, Modifier)
+
+// HLSL `centroid` modifier
+SIMPLE_SYNTAX_CLASS(HLSLCentroidModifier, Modifier)
+
+// HLSL `precise` modifier
+SIMPLE_SYNTAX_CLASS(HLSLPreciseModifier, Modifier)
+
+// HLSL `shared` modifier (which is used by the effect system,
+// and shouldn't be confused with `groupshared`)
+SIMPLE_SYNTAX_CLASS(HLSLEffectSharedModifier, Modifier)
+
+// HLSL `groupshared` modifier
+SIMPLE_SYNTAX_CLASS(HLSLGroupSharedModifier, Modifier)
+
+// HLSL `static` modifier (probably doesn't need to be
+// treated as HLSL-specific)
+SIMPLE_SYNTAX_CLASS(HLSLStaticModifier, Modifier)
+
+// HLSL `uniform` modifier (distinct meaning from GLSL
+// use of the keyword)
+SIMPLE_SYNTAX_CLASS(HLSLUniformModifier, Modifier)
+
+// HLSL `volatile` modifier (ignored)
+SIMPLE_SYNTAX_CLASS(HLSLVolatileModifier, Modifier)
+
+// An HLSL `[name(arg0, ...)]` style attribute.
+SYNTAX_CLASS(HLSLAttribute, Modifier)
+ FIELD(Token, nameToken)
+ SYNTAX_FIELD(List<RefPtr<ExpressionSyntaxNode>>, args)
+END_SYNTAX_CLASS()
+
+// An HLSL `[name(...)]` attribute that hasn't undergone
+// any semantic analysis.
+// After analysis, this might be transformed into a more specific case.
+SIMPLE_SYNTAX_CLASS(HLSLUncheckedAttribute, HLSLAttribute)
+
+// An HLSL `[numthreads(x,y,z)]` attribute
+SYNTAX_CLASS(HLSLNumThreadsAttribute, HLSLAttribute)
+ // The number of threads to use along each axis
+ FIELD(int32_t, x)
+ FIELD(int32_t, y)
+ FIELD(int32_t, z)
+END_SYNTAX_CLASS()
+
+// HLSL modifiers for geometry shader input topology
+SIMPLE_SYNTAX_CLASS(HLSLGeometryShaderInputPrimitiveTypeModifier, Modifier)
+SIMPLE_SYNTAX_CLASS(HLSLPointModifier , HLSLGeometryShaderInputPrimitiveTypeModifier)
+SIMPLE_SYNTAX_CLASS(HLSLLineModifier , HLSLGeometryShaderInputPrimitiveTypeModifier)
+SIMPLE_SYNTAX_CLASS(HLSLTriangleModifier , HLSLGeometryShaderInputPrimitiveTypeModifier)
+SIMPLE_SYNTAX_CLASS(HLSLLineAdjModifier , HLSLGeometryShaderInputPrimitiveTypeModifier)
+SIMPLE_SYNTAX_CLASS(HLSLTriangleAdjModifier , HLSLGeometryShaderInputPrimitiveTypeModifier)
+
diff --git a/source/slang/object-meta-begin.h b/source/slang/object-meta-begin.h
new file mode 100644
index 000000000..e4187a600
--- /dev/null
+++ b/source/slang/object-meta-begin.h
@@ -0,0 +1,36 @@
+// object-meta-begin.h
+
+#ifndef SYNTAX_CLASS
+#error The 'SYNTAX_CLASS' macro should be defined before including 'object-meta-begin.h'
+#endif
+
+#ifndef ABSTRACT_SYNTAX_CLASS
+#define ABSTRACT_SYNTAX_CLASS(NAME, BASE) SYNTAX_CLASS(NAME, BASE)
+#endif
+
+#ifndef END_SYNTAX_CLASS
+#define END_SYNTAX_CLASS() /* empty */
+#endif
+
+#ifndef DECL_FIELD
+#define DECL_FIELD(TYPE, NAME) SYNTAX_FIELD(TYPE, NAME)
+#endif
+
+#ifndef SYNTAX_FIELD
+#define SYNTAX_FIELD(TYPE, NAME) FIELD(TYPE, NAME)
+#endif
+
+#ifndef FIELD_INIT
+#define FIELD_INIT(TYPE, NAME, INIT) FIELD(TYPE, NAME)
+#endif
+
+#ifndef FIELD
+#define FIELD(...) /* empty */
+#endif
+
+#ifndef RAW
+#define RAW(...) /* empty */
+#endif
+
+#define SIMPLE_SYNTAX_CLASS(NAME, BASE) SYNTAX_CLASS(NAME, BASE) END_SYNTAX_CLASS()
+
diff --git a/source/slang/object-meta-end.h b/source/slang/object-meta-end.h
new file mode 100644
index 000000000..ccfd5f96e
--- /dev/null
+++ b/source/slang/object-meta-end.h
@@ -0,0 +1,11 @@
+// object-meta-end.h
+
+#undef SYNTAX_CLASS
+#undef ABSTRACT_SYNTAX_CLASS
+#undef END_SYNTAX_CLASS
+#undef SYNTAX_FIELD
+#undef FIELD
+#undef FIELD_INIT
+#undef DECL_FIELD
+#undef RAW
+#undef SIMPLE_SYNTAX_CLASS
diff --git a/source/slang/slang-stdlib.cpp b/source/slang/slang-stdlib.cpp
index b43387ddd..513fa3b96 100644
--- a/source/slang/slang-stdlib.cpp
+++ b/source/slang/slang-stdlib.cpp
@@ -1722,85 +1722,6 @@ namespace Slang
}
}
-#if 0
- for (auto op : intUnaryOps)
- {
- String opName = GetOperatorFunctionName(op);
- for (int i = 0; i < 4; i++)
- {
- auto itype = intTypes[i];
- auto utype = uintTypes[i];
- for (int j = 0; j < 2; j++)
- {
- auto retType = (op == Operator::Not) ? "bool" : j == 0 ? itype : utype;
- sb << "__intrinsic " << retType << " operator " << opName << "(" << (j == 0 ? itype : utype) << ");\n";
- }
- }
- }
-
- for (auto op : floatUnaryOps)
- {
- String opName = GetOperatorFunctionName(op);
- for (int i = 0; i < 4; i++)
- {
- auto type = floatTypes[i];
- auto retType = (op == Operator::Not) ? "bool" : type;
- sb << "__intrinsic " << retType << " operator " << opName << "(" << type << ");\n";
- }
- }
-
- for (auto op : floatOps)
- {
- String opName = GetOperatorFunctionName(op);
- for (int i = 0; i < 4; i++)
- {
- auto type = floatTypes[i];
- auto itype = intTypes[i];
- auto utype = uintTypes[i];
- auto retType = ((op >= Operator::Eql && op <= Operator::Leq) || op == Operator::And || op == Operator::Or) ? "bool" : type;
- sb << "__intrinsic " << retType << " operator " << opName << "(" << type << ", " << type << ");\n";
- sb << "__intrinsic " << retType << " operator " << opName << "(" << itype << ", " << type << ");\n";
- sb << "__intrinsic " << retType << " operator " << opName << "(" << utype << ", " << type << ");\n";
- sb << "__intrinsic " << retType << " operator " << opName << "(" << type << ", " << itype << ");\n";
- sb << "__intrinsic " << retType << " operator " << opName << "(" << type << ", " << utype << ");\n";
- if (i > 0)
- {
- sb << "__intrinsic " << retType << " operator " << opName << "(" << type << ", " << floatTypes[0] << ");\n";
- sb << "__intrinsic " << retType << " operator " << opName << "(" << floatTypes[0] << ", " << type << ");\n";
-
- sb << "__intrinsic " << retType << " operator " << opName << "(" << type << ", " << intTypes[0] << ");\n";
- sb << "__intrinsic " << retType << " operator " << opName << "(" << intTypes[0] << ", " << type << ");\n";
-
- sb << "__intrinsic " << retType << " operator " << opName << "(" << type << ", " << uintTypes[0] << ");\n";
- sb << "__intrinsic " << retType << " operator " << opName << "(" << uintTypes[0] << ", " << type << ");\n";
- }
- }
- }
-
- for (auto op : intOps)
- {
- String opName = GetOperatorFunctionName(op);
- for (int i = 0; i < 4; i++)
- {
- auto type = intTypes[i];
- auto utype = uintTypes[i];
- auto retType = ((op >= Operator::Eql && op <= Operator::Leq) || op == Operator::And || op == Operator::Or) ? "bool" : type;
- sb << "__intrinsic " << retType << " operator " << opName << "(" << type << ", " << type << ");\n";
- sb << "__intrinsic " << retType << " operator " << opName << "(" << utype << ", " << type << ");\n";
- sb << "__intrinsic " << retType << " operator " << opName << "(" << type << ", " << utype << ");\n";
- sb << "__intrinsic " << retType << " operator " << opName << "(" << utype << ", " << utype << ");\n";
- if (i > 0)
- {
- sb << "__intrinsic " << retType << " operator " << opName << "(" << type << ", " << intTypes[0] << ");\n";
- sb << "__intrinsic " << retType << " operator " << opName << "(" << intTypes[0] << ", " << type << ");\n";
-
- sb << "__intrinsic " << retType << " operator " << opName << "(" << type << ", " << uintTypes[0] << ");\n";
- sb << "__intrinsic " << retType << " operator " << opName << "(" << uintTypes[0] << ", " << type << ");\n";
- }
- }
- }
-#endif
-
// Output a suitable `#line` directive to point at our raw stdlib code above
sb << "\n#line " << kLibIncludeStringLine << " \"" << path << "\"\n";
@@ -1828,10 +1749,6 @@ namespace Slang
StringBuilder sb;
-#define RAW(TEXT) \
-EMIT_LINE_DIRECTIVE(); \
-sb << TEXT;
-
static const struct {
char const* name;
char const* glslPrefix;
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index cd48a4152..182a5818d 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -178,18 +178,6 @@ void CompileRequest::parseTranslationUnit(
}
}
-void CompileRequest::checkTranslationUnit(
- TranslationUnitRequest* translationUnit)
-{
- RefPtr<SyntaxVisitor> visitor = CreateSemanticsVisitor(
- &mSink,
- this,
- translationUnit);
-
- visitor->setSourceLanguage(translationUnit->sourceLanguage);
- translationUnit->SyntaxNode->Accept(visitor.Ptr());
-}
-
void CompileRequest::checkAllTranslationUnits()
{
for( auto& translationUnit : translationUnits )
diff --git a/source/slang/slang.vcxproj b/source/slang/slang.vcxproj
index ba97cb03a..3fde10e4b 100644
--- a/source/slang/slang.vcxproj
+++ b/source/slang/slang.vcxproj
@@ -167,12 +167,17 @@
<ClInclude Include="..\..\slang.h" />
<ClInclude Include="compiled-program.h" />
<ClInclude Include="compiler.h" />
+ <ClInclude Include="decl-defs.h" />
<ClInclude Include="diagnostic-defs.h" />
<ClInclude Include="diagnostics.h" />
<ClInclude Include="emit.h" />
+ <ClInclude Include="expr-defs.h" />
<ClInclude Include="intrinsic-defs.h" />
<ClInclude Include="lexer.h" />
<ClInclude Include="lookup.h" />
+ <ClInclude Include="modifier-defs.h" />
+ <ClInclude Include="object-meta-begin.h" />
+ <ClInclude Include="object-meta-end.h" />
<ClInclude Include="parameter-binding.h" />
<ClInclude Include="parser.h" />
<ClInclude Include="preprocessor.h" />
@@ -181,11 +186,17 @@
<ClInclude Include="reflection.h" />
<ClInclude Include="slang-stdlib.h" />
<ClInclude Include="source-loc.h" />
+ <ClInclude Include="stmt-defs.h" />
+ <ClInclude Include="syntax-base-defs.h" />
+ <ClInclude Include="syntax-defs.h" />
<ClInclude Include="syntax-visitors.h" />
<ClInclude Include="syntax.h" />
<ClInclude Include="token-defs.h" />
<ClInclude Include="token.h" />
+ <ClInclude Include="type-defs.h" />
<ClInclude Include="type-layout.h" />
+ <ClInclude Include="val-defs.h" />
+ <ClInclude Include="visitor.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="check.cpp" />
diff --git a/source/slang/slang.vcxproj.filters b/source/slang/slang.vcxproj.filters
index aa2edb34a..0ed4457dc 100644
--- a/source/slang/slang.vcxproj.filters
+++ b/source/slang/slang.vcxproj.filters
@@ -26,6 +26,17 @@
<ClInclude Include="token-defs.h" />
<ClInclude Include="type-layout.h" />
<ClInclude Include="..\..\slang.h" />
+ <ClInclude Include="syntax-defs.h" />
+ <ClInclude Include="decl-defs.h" />
+ <ClInclude Include="expr-defs.h" />
+ <ClInclude Include="modifier-defs.h" />
+ <ClInclude Include="stmt-defs.h" />
+ <ClInclude Include="object-meta-begin.h" />
+ <ClInclude Include="object-meta-end.h" />
+ <ClInclude Include="syntax-base-defs.h" />
+ <ClInclude Include="type-defs.h" />
+ <ClInclude Include="val-defs.h" />
+ <ClInclude Include="visitor.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="check.cpp" />
diff --git a/source/slang/stmt-defs.h b/source/slang/stmt-defs.h
new file mode 100644
index 000000000..9cc1978bd
--- /dev/null
+++ b/source/slang/stmt-defs.h
@@ -0,0 +1,101 @@
+// stmt-defs.h
+
+// Syntax class definitions for statements.
+
+ABSTRACT_SYNTAX_CLASS(ScopeStmt, StatementSyntaxNode)
+ SYNTAX_FIELD(RefPtr<ScopeDecl>, scopeDecl)
+END_SYNTAX_CLASS()
+
+SYNTAX_CLASS(BlockStatementSyntaxNode, ScopeStmt)
+ SYNTAX_FIELD(List<RefPtr<StatementSyntaxNode>>, Statements)
+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)
+
+SYNTAX_CLASS(VarDeclrStatementSyntaxNode, StatementSyntaxNode)
+ SYNTAX_FIELD(RefPtr<DeclBase>, decl)
+END_SYNTAX_CLASS()
+
+SYNTAX_CLASS(IfStatementSyntaxNode, StatementSyntaxNode)
+ SYNTAX_FIELD(RefPtr<ExpressionSyntaxNode>, Predicate)
+ SYNTAX_FIELD(RefPtr<StatementSyntaxNode>, PositiveStatement)
+ SYNTAX_FIELD(RefPtr<StatementSyntaxNode>, NegativeStatement)
+END_SYNTAX_CLASS()
+
+// A statement that can be escaped with a `break`
+ABSTRACT_SYNTAX_CLASS(BreakableStmt, ScopeStmt)
+END_SYNTAX_CLASS()
+
+SYNTAX_CLASS(SwitchStmt, BreakableStmt)
+ SYNTAX_FIELD(RefPtr<ExpressionSyntaxNode>, condition)
+ SYNTAX_FIELD(RefPtr<StatementSyntaxNode>, body)
+END_SYNTAX_CLASS()
+
+// A statement that is expected to appear lexically nested inside
+// some other construct, and thus needs to keep track of the
+// outer statement that it is associated with...
+ABSTRACT_SYNTAX_CLASS(ChildStmt, StatementSyntaxNode)
+ DECL_FIELD(StatementSyntaxNode*, parentStmt RAW(= nullptr))
+END_SYNTAX_CLASS()
+
+// a `case` or `default` statement inside a `switch`
+//
+// Note(tfoley): A correct AST for a C-like language would treat
+// these as a labelled statement, and so they would contain a
+// sub-statement. I'm leaving that out for now for simplicity.
+ABSTRACT_SYNTAX_CLASS(CaseStmtBase, ChildStmt)
+END_SYNTAX_CLASS()
+
+// a `case` statement inside a `switch`
+SYNTAX_CLASS(CaseStmt, CaseStmtBase)
+ SYNTAX_FIELD(RefPtr<ExpressionSyntaxNode>, expr)
+END_SYNTAX_CLASS()
+
+// a `default` statement inside a `switch`
+SIMPLE_SYNTAX_CLASS(DefaultStmt, CaseStmtBase)
+
+// A statement that represents a loop, and can thus be escaped with a `continue`
+ABSTRACT_SYNTAX_CLASS(LoopStmt, BreakableStmt)
+END_SYNTAX_CLASS()
+
+SYNTAX_CLASS(ForStatementSyntaxNode, LoopStmt)
+ SYNTAX_FIELD(RefPtr<StatementSyntaxNode>, InitialStatement)
+ SYNTAX_FIELD(RefPtr<ExpressionSyntaxNode>, SideEffectExpression)
+ SYNTAX_FIELD(RefPtr<ExpressionSyntaxNode>, PredicateExpression)
+ SYNTAX_FIELD(RefPtr<StatementSyntaxNode>, Statement)
+END_SYNTAX_CLASS()
+
+
+SYNTAX_CLASS(WhileStatementSyntaxNode, LoopStmt)
+ SYNTAX_FIELD(RefPtr<ExpressionSyntaxNode>, Predicate)
+ SYNTAX_FIELD(RefPtr<StatementSyntaxNode>, Statement)
+END_SYNTAX_CLASS()
+
+SYNTAX_CLASS(DoWhileStatementSyntaxNode, LoopStmt)
+ SYNTAX_FIELD(RefPtr<StatementSyntaxNode>, Statement)
+ SYNTAX_FIELD(RefPtr<ExpressionSyntaxNode>, Predicate)
+END_SYNTAX_CLASS()
+
+// The case of child statements that do control flow relative
+// to their parent statement.
+ABSTRACT_SYNTAX_CLASS(JumpStmt, ChildStmt)
+END_SYNTAX_CLASS()
+
+SIMPLE_SYNTAX_CLASS(BreakStatementSyntaxNode, JumpStmt)
+
+SIMPLE_SYNTAX_CLASS(ContinueStatementSyntaxNode, JumpStmt)
+
+SYNTAX_CLASS(ReturnStatementSyntaxNode, StatementSyntaxNode)
+ SYNTAX_FIELD(RefPtr<ExpressionSyntaxNode>, Expression)
+END_SYNTAX_CLASS()
+
+SYNTAX_CLASS(ExpressionStatementSyntaxNode, StatementSyntaxNode)
+ SYNTAX_FIELD(RefPtr<ExpressionSyntaxNode>, Expression)
+END_SYNTAX_CLASS()
diff --git a/source/slang/syntax-base-defs.h b/source/slang/syntax-base-defs.h
new file mode 100644
index 000000000..11ec30e62
--- /dev/null
+++ b/source/slang/syntax-base-defs.h
@@ -0,0 +1,261 @@
+// syntax-base-defs.h
+
+// This file defines the primary base classes for the hierarchy of
+// AST nodes and related objects. For example, this is where the
+// basic `Decl`, `Stmt`, `Expr`, `Type`, etc. definitions come from.
+
+// Base class for all nodes representing actual syntax
+// (thus having a location in the source code)
+ABSTRACT_SYNTAX_CLASS(SyntaxNodeBase, RefObject)
+
+ // The primary source location associated with this AST node
+ FIELD(CodePosition, Position)
+END_SYNTAX_CLASS()
+
+// Base class for compile-time values (most often a type).
+// These are *not* syntax nodes, because they do not have
+// a unique location, and any two `Val`s representing
+// the same value should be conceptually equal.
+ABSTRACT_SYNTAX_CLASS(Val, RefObject)
+ RAW(typedef IValVisitor Visitor;)
+
+ RAW(virtual void accept(IValVisitor* visitor, void* extra) = 0;)
+
+ RAW(
+ // construct a new value by applying a set of parameter
+ // substitutions to this one
+ RefPtr<Val> Substitute(Substitutions* subst);
+
+ // Lower-level interface for substition. Like the basic
+ // `Substitute` above, but also takes a by-reference
+ // integer parameter that should be incremented when
+ // returning a modified value (this can help the caller
+ // decide whether they need to do anything).
+ virtual RefPtr<Val> SubstituteImpl(Substitutions* subst, int* ioDiff);
+
+ virtual bool EqualsVal(Val* val) = 0;
+ virtual String ToString() = 0;
+ virtual int GetHashCode() = 0;
+ bool operator == (const Val & v)
+ {
+ return EqualsVal(const_cast<Val*>(&v));
+ }
+ )
+END_SYNTAX_CLASS()
+
+// A type, representing a classifier for some term in the AST.
+//
+// Types can include "sugar" in that they may refer to a
+// `typedef` which gives them a good name when printed as
+// part of diagnostic messages.
+//
+// In order to operation on types, though, we often want
+// to look past any sugar, and operate on an underlying
+// "canonical" type. The reprsentation caches a pointer to
+// a canonical type on every type, so we can easily
+// operate on the raw representation when needed.
+ABSTRACT_SYNTAX_CLASS(ExpressionType, Val)
+ RAW(typedef ITypeVisitor Visitor;)
+
+ RAW(virtual void accept(IValVisitor* visitor, void* extra) override;)
+ RAW(virtual void accept(ITypeVisitor* visitor, void* extra) = 0;)
+
+RAW(
+public:
+ static RefPtr<ExpressionType> Error;
+ static RefPtr<ExpressionType> initializerListType;
+ static RefPtr<ExpressionType> Overloaded;
+
+ static Dictionary<int, RefPtr<ExpressionType>> sBuiltinTypes;
+ static Dictionary<String, Decl*> sMagicDecls;
+
+ // Note: just exists to make sure we can clean up
+ // canonical types we create along the way
+ static List<RefPtr<ExpressionType>> sCanonicalTypes;
+
+
+
+ static ExpressionType* GetBool();
+ static ExpressionType* GetFloat();
+ static ExpressionType* getDoubleType();
+ static ExpressionType* GetInt();
+ static ExpressionType* GetUInt();
+ static ExpressionType* GetVoid();
+ static ExpressionType* getInitializerListType();
+ static ExpressionType* GetError();
+
+public:
+ virtual String ToString() = 0;
+
+ bool Equals(ExpressionType * type);
+ bool Equals(RefPtr<ExpressionType> type);
+
+ bool IsVectorType() { return As<VectorExpressionType>() != nullptr; }
+ bool IsArray() { return As<ArrayExpressionType>() != nullptr; }
+
+ template<typename T>
+ T* As()
+ {
+ return dynamic_cast<T*>(GetCanonicalType());
+ }
+
+ // Convenience/legacy wrappers for `As<>`
+ ArithmeticExpressionType * AsArithmeticType() { return As<ArithmeticExpressionType>(); }
+ BasicExpressionType * AsBasicType() { return As<BasicExpressionType>(); }
+ VectorExpressionType * AsVectorType() { return As<VectorExpressionType>(); }
+ MatrixExpressionType * AsMatrixType() { return As<MatrixExpressionType>(); }
+ ArrayExpressionType * AsArrayType() { return As<ArrayExpressionType>(); }
+
+ DeclRefType* AsDeclRefType() { return As<DeclRefType>(); }
+
+ NamedExpressionType* AsNamedType();
+
+ bool IsTextureOrSampler();
+ bool IsTexture() { return As<TextureType>() != nullptr; }
+ bool IsSampler() { return As<SamplerStateType>() != nullptr; }
+ bool IsStruct();
+ bool IsClass();
+ static void Init();
+ static void Finalize();
+ ExpressionType* GetCanonicalType();
+
+ virtual RefPtr<Val> SubstituteImpl(Substitutions* subst, int* ioDiff) override;
+
+ virtual bool EqualsVal(Val* val) override;
+protected:
+ virtual bool EqualsImpl(ExpressionType * type) = 0;
+
+ virtual ExpressionType* CreateCanonicalType() = 0;
+ ExpressionType* canonicalType = nullptr;
+ )
+END_SYNTAX_CLASS()
+
+// A substitution represents a binding of certain
+// type-level variables to concrete argument values
+SYNTAX_CLASS(Substitutions, RefObject)
+
+ // The generic declaration that defines the
+ // parametesr we are binding to arguments
+ DECL_FIELD(GenericDecl*, genericDecl)
+
+ // The actual values of the arguments
+ SYNTAX_FIELD(List<RefPtr<Val>>, args)
+
+ // Any further substitutions, relating to outer generic declarations
+ SYNTAX_FIELD(RefPtr<Substitutions>, outer)
+
+ RAW(
+ // Apply a set of substitutions to the bindings in this substitution
+ RefPtr<Substitutions> SubstituteImpl(Substitutions* subst, int* ioDiff);
+
+ // Check if these are equivalent substitutiosn to another set
+ bool Equals(Substitutions* subst);
+ bool operator == (const Substitutions & subst)
+ {
+ return Equals(const_cast<Substitutions*>(&subst));
+ }
+ int GetHashCode() const
+ {
+ int rs = 0;
+ for (auto && v : args)
+ {
+ rs ^= v->GetHashCode();
+ rs *= 16777619;
+ }
+ return rs;
+ }
+ )
+END_SYNTAX_CLASS()
+
+ABSTRACT_SYNTAX_CLASS(SyntaxNode, SyntaxNodeBase)
+END_SYNTAX_CLASS()
+
+//
+// All modifiers are represented as full-fledged objects in the AST
+// (that is, we don't use a bitfield, even for simple/common flags).
+// This ensures that we can track source locations for all modifiers.
+//
+ABSTRACT_SYNTAX_CLASS(Modifier, SyntaxNodeBase)
+ RAW(typedef IModifierVisitor Visitor;)
+
+ RAW(virtual void accept(IModifierVisitor* visitor, void* extra) = 0;)
+
+ // Next modifier in linked list of modifiers on same piece of syntax
+ SYNTAX_FIELD(RefPtr<Modifier>, next)
+
+ // The token that was used to name this modifier.
+ FIELD(Token, nameToken)
+END_SYNTAX_CLASS()
+
+// A syntax node which can have modifiers appled
+ABSTRACT_SYNTAX_CLASS(ModifiableSyntaxNode, SyntaxNode)
+
+ SYNTAX_FIELD(Modifiers, modifiers)
+
+ RAW(
+ template<typename T>
+ FilteredModifierList<T> GetModifiersOfType() { return FilteredModifierList<T>(modifiers.first.Ptr()); }
+
+ // Find the first modifier of a given type, or return `nullptr` if none is found.
+ template<typename T>
+ T* FindModifier()
+ {
+ return *GetModifiersOfType<T>().begin();
+ }
+
+ template<typename T>
+ bool HasModifier() { return FindModifier<T>() != nullptr; }
+ )
+END_SYNTAX_CLASS()
+
+
+// An intermediate type to represent either a single declaration, or a group of declarations
+ABSTRACT_SYNTAX_CLASS(DeclBase, ModifiableSyntaxNode)
+ RAW(typedef IDeclVisitor Visitor;)
+
+ RAW(virtual void accept(IDeclVisitor* visitor, void* extra) = 0;)
+
+
+END_SYNTAX_CLASS()
+
+ABSTRACT_SYNTAX_CLASS(Decl, DeclBase)
+ DECL_FIELD(ContainerDecl*, ParentDecl RAW(=nullptr))
+
+ FIELD(Token, Name)
+
+ RAW(
+ String const& getName() { return Name.Content; }
+ Token const& getNameToken() { return Name; }
+ )
+
+
+ FIELD_INIT(DeclCheckState, checkState, DeclCheckState::Unchecked)
+
+ // The next declaration defined in the same container with the same name
+ DECL_FIELD(Decl*, nextInContainerWithSameName RAW(= nullptr))
+
+ RAW(
+ bool IsChecked(DeclCheckState state) { return checkState >= state; }
+ void SetCheckState(DeclCheckState state)
+ {
+ assert(state >= checkState);
+ checkState = state;
+ }
+ )
+END_SYNTAX_CLASS()
+
+ABSTRACT_SYNTAX_CLASS(ExpressionSyntaxNode, SyntaxNode)
+ RAW(typedef IExprVisitor Visitor;)
+
+ FIELD(QualType, Type)
+
+ RAW(virtual void accept(IExprVisitor* visitor, void* extra) = 0;)
+
+END_SYNTAX_CLASS()
+
+ABSTRACT_SYNTAX_CLASS(StatementSyntaxNode, ModifiableSyntaxNode)
+ RAW(typedef IStmtVisitor Visitor;)
+
+ RAW(virtual void accept(IStmtVisitor* visitor, void* extra) = 0;)
+
+END_SYNTAX_CLASS()
diff --git a/source/slang/syntax-defs.h b/source/slang/syntax-defs.h
new file mode 100644
index 000000000..4ff4a55a6
--- /dev/null
+++ b/source/slang/syntax-defs.h
@@ -0,0 +1,10 @@
+// syntax-defs.h
+
+#include "syntax-base-defs.h"
+
+#include "expr-defs.h"
+#include "decl-defs.h"
+#include "modifier-defs.h"
+#include "stmt-defs.h"
+#include "type-defs.h"
+#include "val-defs.h"
diff --git a/source/slang/syntax-visitors.h b/source/slang/syntax-visitors.h
index 5d712b671..85a20a7cf 100644
--- a/source/slang/syntax-visitors.h
+++ b/source/slang/syntax-visitors.h
@@ -11,11 +11,10 @@ namespace Slang
class ShaderCompiler;
class ShaderLinkInfo;
class ShaderSymbol;
+
class TranslationUnitRequest;
- SyntaxVisitor* CreateSemanticsVisitor(
- DiagnosticSink* err,
- CompileRequest* request,
+ void checkTranslationUnit(
TranslationUnitRequest* translationUnit);
// Look for a module that matches the given name:
diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp
index cf529e55e..983f18bb7 100644
--- a/source/slang/syntax.cpp
+++ b/source/slang/syntax.cpp
@@ -1,5 +1,9 @@
#include "syntax.h"
-#include "syntax-visitors.h"
+
+#pragma warning AAA
+#include "visitor.h"
+#pragma warning BBB
+
#include <typeinfo>
#include <assert.h>
@@ -51,176 +55,47 @@ namespace Slang
return res.ProduceString();
}
- RefPtr<SyntaxNode> ProgramSyntaxNode::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitProgram(this);
- }
-
- RefPtr<SyntaxNode> FunctionSyntaxNode::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitFunction(this);
- }
-
- //
-
- RefPtr<SyntaxNode> ScopeDecl::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitScopeDecl(this);
- }
-
- //
+#pragma warning CCC
- RefPtr<SyntaxNode> BlockStatementSyntaxNode::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitBlockStatement(this);
- }
- RefPtr<SyntaxNode> BreakStatementSyntaxNode::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitBreakStatement(this);
- }
+ // Generate dispatch logic and other definitions for all syntax classes
+#define SYNTAX_CLASS(NAME, BASE) /* empty */
+#include "object-meta-begin.h"
- RefPtr<SyntaxNode> ContinueStatementSyntaxNode::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitContinueStatement(this);
- }
+#include "syntax-base-defs.h"
+#undef SYNTAX_CLASS
+#undef ABSTRACT_SYNTAX_CLASS
- RefPtr<SyntaxNode> DoWhileStatementSyntaxNode::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitDoWhileStatement(this);
- }
+#define ABSTRACT_SYNTAX_CLASS(NAME, BASE) /* empty */
+#define SYNTAX_CLASS(NAME, BASE) \
+ void NAME::accept(NAME::Visitor* visitor, void* extra) \
+ { visitor->dispatch_##NAME(this, extra); }
+#include "expr-defs.h"
+#include "decl-defs.h"
+#include "modifier-defs.h"
+#include "stmt-defs.h"
+#include "type-defs.h"
+#include "val-defs.h"
- RefPtr<SyntaxNode> EmptyStatementSyntaxNode::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitEmptyStatement(this);
- }
+#include "object-meta-end.h"
- RefPtr<SyntaxNode> ForStatementSyntaxNode::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitForStatement(this);
- }
+#pragma warning DDD
- RefPtr<SyntaxNode> IfStatementSyntaxNode::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitIfStatement(this);
- }
-
- RefPtr<SyntaxNode> ReturnStatementSyntaxNode::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitReturnStatement(this);
- }
-
- RefPtr<SyntaxNode> VarDeclrStatementSyntaxNode::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitVarDeclrStatement(this);
- }
-
- RefPtr<SyntaxNode> Variable::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitDeclrVariable(this);
- }
-
- RefPtr<SyntaxNode> WhileStatementSyntaxNode::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitWhileStatement(this);
- }
-
- RefPtr<SyntaxNode> ExpressionStatementSyntaxNode::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitExpressionStatement(this);
- }
-
- RefPtr<SyntaxNode> ConstantExpressionSyntaxNode::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitConstantExpression(this);
- }
-
- RefPtr<SyntaxNode> IndexExpressionSyntaxNode::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitIndexExpression(this);
- }
- RefPtr<SyntaxNode> MemberExpressionSyntaxNode::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitMemberExpression(this);
- }
-
- // SwizzleExpr
-
- RefPtr<SyntaxNode> SwizzleExpr::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitSwizzleExpression(this);
- }
-
- // DerefExpr
-
- RefPtr<SyntaxNode> DerefExpr::Accept(SyntaxVisitor * /*visitor*/)
- {
- // throw "unimplemented";
- return this;
- }
-
- //
-
- RefPtr<SyntaxNode> InvokeExpressionSyntaxNode::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitInvokeExpression(this);
- }
-
- RefPtr<SyntaxNode> TypeCastExpressionSyntaxNode::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitTypeCastExpression(this);
- }
-
- RefPtr<SyntaxNode> VarExpressionSyntaxNode::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitVarExpression(this);
- }
-
- // OverloadedExpr
-
- RefPtr<SyntaxNode> OverloadedExpr::Accept(SyntaxVisitor * /*visitor*/)
- {
-// throw "unimplemented";
- return this;
- }
-
- //
-
- RefPtr<SyntaxNode> ParameterSyntaxNode::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitParameter(this);
- }
-
- // ImportDecl
-
- RefPtr<SyntaxNode> ImportDecl::Accept(SyntaxVisitor * visitor)
- {
- visitor->visitImportDecl(this);
- return this;
- }
+void ExpressionType::accept(IValVisitor* visitor, void* extra)
+{
+ accept((ITypeVisitor*)visitor, extra);
+}
- //
+ // TypeExp
- RefPtr<SyntaxNode> StructField::Accept(SyntaxVisitor * visitor)
+ bool TypeExp::Equals(ExpressionType* other)
{
- return visitor->VisitStructField(this);
- }
- RefPtr<SyntaxNode> StructSyntaxNode::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitStruct(this);
- }
- RefPtr<SyntaxNode> ClassSyntaxNode::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitClass(this);
- }
- RefPtr<SyntaxNode> TypeDefDecl::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitTypeDefDecl(this);
+ return type->Equals(other);
}
- RefPtr<SyntaxNode> DiscardStatementSyntaxNode::Accept(SyntaxVisitor * visitor)
+ bool TypeExp::Equals(RefPtr<ExpressionType> other)
{
- return visitor->VisitDiscardStatement(this);
+ return type->Equals(other.Ptr());
}
// BasicExpressionType
@@ -358,10 +233,6 @@ namespace Slang
else
return BaseType->ToString() + "[]";
}
- RefPtr<SyntaxNode> GenericAppExpr::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitGenericApp(this);
- }
// DeclRefType
@@ -826,190 +697,6 @@ namespace Slang
return this->declRef.substitutions->args[2].As<IntVal>().Ptr();
}
- //
-
-#if 0
- String GetOperatorFunctionName(Operator op)
- {
- switch (op)
- {
- case Operator::Add:
- case Operator::AddAssign:
- return "+";
- case Operator::Sub:
- case Operator::SubAssign:
- return "-";
- case Operator::Neg:
- return "-";
- case Operator::Not:
- return "!";
- case Operator::BitNot:
- return "~";
- case Operator::PreInc:
- case Operator::PostInc:
- return "++";
- case Operator::PreDec:
- case Operator::PostDec:
- return "--";
- case Operator::Mul:
- case Operator::MulAssign:
- return "*";
- case Operator::Div:
- case Operator::DivAssign:
- return "/";
- case Operator::Mod:
- case Operator::ModAssign:
- return "%";
- case Operator::Lsh:
- case Operator::LshAssign:
- return "<<";
- case Operator::Rsh:
- case Operator::RshAssign:
- return ">>";
- case Operator::Eql:
- return "==";
- case Operator::Neq:
- return "!=";
- case Operator::Greater:
- return ">";
- case Operator::Less:
- return "<";
- case Operator::Geq:
- return ">=";
- case Operator::Leq:
- return "<=";
- case Operator::BitAnd:
- case Operator::AndAssign:
- return "&";
- case Operator::BitXor:
- case Operator::XorAssign:
- return "^";
- case Operator::BitOr:
- case Operator::OrAssign:
- return "|";
- case Operator::And:
- return "&&";
- case Operator::Or:
- return "||";
- case Operator::Sequence:
- return ",";
- case Operator::Select:
- return "?:";
- case Operator::Assign:
- return "=";
- default:
- return "";
- }
- }
-#endif
- String OperatorToString(Operator op)
- {
- switch (op)
- {
- case Slang::Operator::Neg:
- return "-";
- case Slang::Operator::Not:
- return "!";
- case Slang::Operator::PreInc:
- return "++";
- case Slang::Operator::PreDec:
- return "--";
- case Slang::Operator::PostInc:
- return "++";
- case Slang::Operator::PostDec:
- return "--";
- case Slang::Operator::Mul:
- case Slang::Operator::MulAssign:
- return "*";
- case Slang::Operator::Div:
- case Slang::Operator::DivAssign:
- return "/";
- case Slang::Operator::Mod:
- case Slang::Operator::ModAssign:
- return "%";
- case Slang::Operator::Add:
- case Slang::Operator::AddAssign:
- return "+";
- case Slang::Operator::Sub:
- case Slang::Operator::SubAssign:
- return "-";
- case Slang::Operator::Lsh:
- case Slang::Operator::LshAssign:
- return "<<";
- case Slang::Operator::Rsh:
- case Slang::Operator::RshAssign:
- return ">>";
- case Slang::Operator::Eql:
- return "==";
- case Slang::Operator::Neq:
- return "!=";
- case Slang::Operator::Greater:
- return ">";
- case Slang::Operator::Less:
- return "<";
- case Slang::Operator::Geq:
- return ">=";
- case Slang::Operator::Leq:
- return "<=";
- case Slang::Operator::BitAnd:
- case Slang::Operator::AndAssign:
- return "&";
- case Slang::Operator::BitXor:
- case Slang::Operator::XorAssign:
- return "^";
- case Slang::Operator::BitOr:
- case Slang::Operator::OrAssign:
- return "|";
- case Slang::Operator::And:
- return "&&";
- case Slang::Operator::Or:
- return "||";
- case Slang::Operator::Assign:
- return "=";
- default:
- return "ERROR";
- }
- }
-
- // TypeExp
-
- TypeExp TypeExp::Accept(SyntaxVisitor* visitor)
- {
- return visitor->VisitTypeExp(*this);
- }
-
- // BuiltinTypeModifier
-
- // MagicTypeModifier
-
- // GenericDecl
-
- RefPtr<SyntaxNode> GenericDecl::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitGenericDecl(this);
- }
-
- // GenericTypeParamDecl
-
- RefPtr<SyntaxNode> GenericTypeParamDecl::Accept(SyntaxVisitor * /*visitor*/) {
- //throw "unimplemented";
- return this;
- }
-
- // GenericTypeConstraintDecl
-
- RefPtr<SyntaxNode> GenericTypeConstraintDecl::Accept(SyntaxVisitor * visitor)
- {
- return this;
- }
-
- // GenericValueParamDecl
-
- RefPtr<SyntaxNode> GenericValueParamDecl::Accept(SyntaxVisitor * /*visitor*/) {
- //throw "unimplemented";
- return this;
- }
-
// GenericParamIntVal
bool GenericParamIntVal::EqualsVal(Val* val)
@@ -1069,38 +756,6 @@ namespace Slang
return this;
}
- // ExtensionDecl
-
- RefPtr<SyntaxNode> ExtensionDecl::Accept(SyntaxVisitor * visitor)
- {
- visitor->VisitExtensionDecl(this);
- return this;
- }
-
- // ConstructorDecl
-
- RefPtr<SyntaxNode> ConstructorDecl::Accept(SyntaxVisitor * visitor)
- {
- visitor->VisitConstructorDecl(this);
- return this;
- }
-
- // SubscriptDecl
-
- RefPtr<SyntaxNode> SubscriptDecl::Accept(SyntaxVisitor * visitor)
- {
- visitor->visitSubscriptDecl(this);
- return this;
- }
-
- // AccessorDecl
-
- RefPtr<SyntaxNode> AccessorDecl::Accept(SyntaxVisitor * visitor)
- {
- visitor->visitAccessorDecl(this);
- return this;
- }
-
// Substitutions
RefPtr<Substitutions> Substitutions::SubstituteImpl(Substitutions* subst, int* ioDiff)
@@ -1297,73 +952,6 @@ namespace Slang
return (int) value;
}
- // SwitchStmt
-
- RefPtr<SyntaxNode> SwitchStmt::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitSwitchStmt(this);
- }
-
- RefPtr<SyntaxNode> CaseStmt::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitCaseStmt(this);
- }
-
- RefPtr<SyntaxNode> DefaultStmt::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitDefaultStmt(this);
- }
-
- // InterfaceDecl
-
- RefPtr<SyntaxNode> InterfaceDecl::Accept(SyntaxVisitor * visitor)
- {
- visitor->visitInterfaceDecl(this);
- return this;
- }
-
- // InheritanceDecl
-
- RefPtr<SyntaxNode> InheritanceDecl::Accept(SyntaxVisitor * visitor)
- {
- visitor->visitInheritanceDecl(this);
- return this;
- }
-
- // SharedTypeExpr
-
- RefPtr<SyntaxNode> SharedTypeExpr::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitSharedTypeExpr(this);
- }
-
- // OperatorExpressionSyntaxNode
-
-#if 0
- void OperatorExpressionSyntaxNode::SetOperator(RefPtr<Scope> scope, Slang::Operator op)
- {
- this->Operator = op;
- auto opExpr = new VarExpressionSyntaxNode();
- opExpr->Variable = GetOperatorFunctionName(Operator);
- opExpr->scope = scope;
- opExpr->Position = this->Position;
- this->FunctionExpr = opExpr;
- }
-#endif
-
- RefPtr<SyntaxNode> OperatorExpressionSyntaxNode::Accept(SyntaxVisitor * visitor)
- {
- return visitor->VisitOperatorExpression(this);
- }
-
- // DeclGroup
-
- RefPtr<SyntaxNode> DeclGroup::Accept(SyntaxVisitor * visitor)
- {
- visitor->VisitDeclGroup(this);
- return this;
- }
-
//
void RegisterBuiltinDecl(
@@ -1429,34 +1017,6 @@ namespace Slang
//
- RefPtr<SyntaxNode> UnparsedStmt::Accept(SyntaxVisitor * visitor)
- {
- return this;
- }
-
- //
-
- RefPtr<SyntaxNode> InitializerListExpr::Accept(SyntaxVisitor * visitor)
- {
- return visitor->visitInitializerListExpr(this);
- }
-
- //
-
- RefPtr<SyntaxNode> ModifierDecl::Accept(SyntaxVisitor * visitor)
- {
- return this;
- }
-
- //
-
- RefPtr<SyntaxNode> EmptyDecl::Accept(SyntaxVisitor * visitor)
- {
- return this;
- }
-
- //
-
SyntaxNodeBase* createInstanceOfSyntaxClassByName(
String const& name)
{
diff --git a/source/slang/syntax.h b/source/slang/syntax.h
index b4d7e146e..47427b130 100644
--- a/source/slang/syntax.h
+++ b/source/slang/syntax.h
@@ -11,55 +11,22 @@
namespace Slang
{
+ class Substitutions;
class SyntaxVisitor;
class FunctionSyntaxNode;
- class SyntaxNodeBase : public RefObject
- {
- public:
- CodePosition Position;
- };
-
-
+ struct IExprVisitor;
+ struct IDeclVisitor;
+ struct IModifierVisitor;
+ struct IStmtVisitor;
+ struct ITypeVisitor;
+ struct IValVisitor;
-
- //
- // Other modifiers may have more elaborate data, and so
- // are represented as heap-allocated objects, in a linked
- // list.
- //
- class Modifier : public SyntaxNodeBase
- {
- public:
- // Next modifier in linked list of modifiers on same piece of syntax
- RefPtr<Modifier> next;
-
- // The token that was used to name this modifier.
- Token nameToken;
- };
-
-#define SIMPLE_MODIFIER(NAME) \
- class NAME##Modifier : public Modifier {}
-
- SIMPLE_MODIFIER(Uniform);
- SIMPLE_MODIFIER(In);
- SIMPLE_MODIFIER(Out);
- SIMPLE_MODIFIER(Const);
- SIMPLE_MODIFIER(Instance);
- SIMPLE_MODIFIER(Builtin);
- SIMPLE_MODIFIER(Inline);
- SIMPLE_MODIFIER(Public);
- SIMPLE_MODIFIER(Require);
- SIMPLE_MODIFIER(Param);
- SIMPLE_MODIFIER(Extern);
- SIMPLE_MODIFIER(Input);
- SIMPLE_MODIFIER(Transparent);
- SIMPLE_MODIFIER(FromStdLib);
- SIMPLE_MODIFIER(Prefix);
- SIMPLE_MODIFIER(Postfix);
- SIMPLE_MODIFIER(Exported);
-
-#undef SIMPLE_MODIFIER
+ // Forward-declare all syntax classes
+#define SYNTAX_CLASS(NAME, BASE, ...) class NAME;
+#include "object-meta-begin.h"
+#include "syntax-defs.h"
+#include "object-meta-end.h"
enum class IntrinsicOp
{
@@ -70,174 +37,6 @@ namespace Slang
IntrinsicOp findIntrinsicOp(char const* name);
- // Base class for modifiers that mark something as "intrinsic"
- // and thus lacking a direct implementation in the language.
- class IntrinsicModifierBase : public Modifier
- {
- };
-
- // A modifier that marks something as one of a small set of
- // truly intrinsic operations that the compiler knows about
- // directly.
- class IntrinsicOpModifier : public IntrinsicModifierBase
- {
- public:
- // token that names the intrinsic op
- Token opToken;
-
- // The opcode for the intrinsic operation
- IntrinsicOp op = IntrinsicOp::Unknown;
- };
-
- // A modifier that marks something as an intrinsic function,
- // for some subset of targets.
- class TargetIntrinsicModifier : public IntrinsicModifierBase
- {
- public:
- // Token that names the target that the operation
- // is an intrisic for.
- Token targetToken;
-
- // A custom definition for the operation
- Token definitionToken;
- };
-
-
-
- class InOutModifier : public OutModifier {};
-
- // This is a special sentinel modifier that gets added
- // to the list when we have multiple variable declarations
- // all sharing the same modifiers:
- //
- // static uniform int a : FOO, *b : register(x0);
- //
- // In this case both `a` and `b` share the syntax
- // for part of their modifier list, but then have
- // their own modifiers as well:
- //
- // a: SemanticModifier("FOO") --> SharedModifiers --> StaticModifier --> UniformModifier
- // /
- // b: RegisterModifier("x0") /
- //
- class SharedModifiers : public Modifier {};
-
- // A GLSL `layout` modifier
- //
- // We use a distinct modifier for each key that
- // appears within the `layout(...)` construct,
- // and each key might have an optional value token.
- //
- // TODO: We probably want a notion of "modifier groups"
- // so that we can recover good source location info
- // for modifiers that were part of the same vs.
- // different constructs.
- class GLSLLayoutModifier : public Modifier
- {
- public:
- // THe token used to introduce the modifier is stored
- // as the `nameToken` field.
-
- // TODO: may want to accept a full expression here
- Token valToken;
- };
-
- // We divide GLSL `layout` modifiers into those we have parsed
- // (in the sense of having some notion of their semantics), and
- // those we have not.
- class GLSLParsedLayoutModifier : public GLSLLayoutModifier {};
- class GLSLUnparsedLayoutModifier : public GLSLLayoutModifier {};
-
- // Specific cases for known GLSL `layout` modifiers that we need to work with
- class GLSLConstantIDLayoutModifier : public GLSLParsedLayoutModifier {};
- class GLSLBindingLayoutModifier : public GLSLParsedLayoutModifier {};
- class GLSLSetLayoutModifier : public GLSLParsedLayoutModifier {};
- class GLSLLocationLayoutModifier : public GLSLParsedLayoutModifier {};
-
- // A catch-all for single-keyword modifiers
- class SimpleModifier : public Modifier {};
-
- // Some GLSL-specific modifiers
- class GLSLBufferModifier : public SimpleModifier {};
- class GLSLWriteOnlyModifier : public SimpleModifier {};
- class GLSLReadOnlyModifier : public SimpleModifier {};
- class GLSLPatchModifier : public SimpleModifier {};
-
- // Indicates that this is a variable declaration that corresponds to
- // a parameter block declaration in the source program.
- class ImplicitParameterBlockVariableModifier : public Modifier {};
-
- // Indicates that this is a type that corresponds to the element
- // type of a parameter block declaration in the source program.
- class ImplicitParameterBlockElementTypeModifier : public Modifier {};
-
- // An HLSL semantic
- class HLSLSemantic : public Modifier
- {
- public:
- Token name;
- };
-
-
- // An HLSL semantic that affects layout
- class HLSLLayoutSemantic : public HLSLSemantic
- {
- public:
- Token registerName;
- Token componentMask;
- };
-
- // An HLSL `register` semantic
- class HLSLRegisterSemantic : public HLSLLayoutSemantic
- {
- };
-
- // TODO(tfoley): `packoffset`
- class HLSLPackOffsetSemantic : public HLSLLayoutSemantic
- {
- };
-
- // An HLSL semantic that just associated a declaration with a semantic name
- class HLSLSimpleSemantic : public HLSLSemantic
- {
- };
-
- // GLSL
-
- // Directives that came in via the preprocessor, but
- // that we need to keep around for later steps
- class GLSLPreprocessorDirective : public Modifier
- {
- };
-
- // A GLSL `#version` directive
- class GLSLVersionDirective : public GLSLPreprocessorDirective
- {
- public:
- // Token giving the version number to use
- Token versionNumberToken;
-
- // Optional token giving the sub-profile to be used
- Token glslProfileToken;
- };
-
- // A GLSL `#extension` directive
- class GLSLExtensionDirective : public GLSLPreprocessorDirective
- {
- public:
- // Token giving the version number to use
- Token extensionNameToken;
-
- // Optional token giving the sub-profile to be used
- Token dispositionToken;
- };
-
- class ParameterBlockReflectionName : public Modifier
- {
- public:
- Token nameToken;
- };
-
// Helper class for iterating over a list of heap-allocated modifiers
struct ModifierList
{
@@ -250,10 +49,12 @@ namespace Slang
return current;
}
- void operator++()
+ void operator++();
+#if 0
{
current = current->next.Ptr();
}
+#endif
bool operator!=(Iterator other)
{
@@ -376,213 +177,16 @@ namespace Slang
UInt64,
Float,
Double,
-#if 0
- Texture2D = 48,
- TextureCube = 49,
- Texture2DArray = 50,
- Texture2DShadow = 51,
- TextureCubeShadow = 52,
- Texture2DArrayShadow = 53,
- Texture3D = 54,
- SamplerState = 4096, SamplerComparisonState = 4097,
- Error = 16384,
-#endif
};
- class Decl;
- class StructSyntaxNode;
- class BasicExpressionType;
- class ArrayExpressionType;
- class TypeDefDecl;
- class DeclRefType;
class NamedExpressionType;
- class TypeType;
- class GenericDeclRefType;
- class VectorExpressionType;
- class MatrixExpressionType;
- class ArithmeticExpressionType;
class GenericDecl;
- class Substitutions;
- class TextureType;
- class SamplerStateType;
-
- // A compile-time constant value (usually a type)
- class Val : public RefObject
- {
- public:
- // construct a new value by applying a set of parameter
- // substitutions to this one
- RefPtr<Val> Substitute(Substitutions* subst);
-
- // Lower-level interface for substition. Like the basic
- // `Substitute` above, but also takes a by-reference
- // integer parameter that should be incremented when
- // returning a modified value (this can help the caller
- // decide whether they need to do anything).
- virtual RefPtr<Val> SubstituteImpl(Substitutions* subst, int* ioDiff);
-
- virtual bool EqualsVal(Val* val) = 0;
- virtual String ToString() = 0;
- virtual int GetHashCode() = 0;
- bool operator == (const Val & v)
- {
- return EqualsVal(const_cast<Val*>(&v));
- }
- };
-
- // A compile-time integer (may not have a specific concrete value)
- class IntVal : public Val
- {
- };
+ class ContainerDecl;
// Try to extract a simple integer value from an `IntVal`.
// This fill assert-fail if the object doesn't represent a literal value.
IntegerLiteralValue GetIntVal(RefPtr<IntVal> val);
- // Trivial case of a value that is just a constant integer
- class ConstantIntVal : public IntVal
- {
- public:
- IntegerLiteralValue value;
-
- ConstantIntVal(IntegerLiteralValue value)
- : value(value)
- {}
-
- virtual bool EqualsVal(Val* val) override;
- virtual String ToString() override;
- virtual int GetHashCode() override;
- };
-
- // TODO(tfoley): classes for more general compile-time integers,
- // including references to template parameters
-
- // A type, representing a classifier for some term in the AST.
- //
- // Types can include "sugar" in that they may refer to a
- // `typedef` which gives them a good name when printed as
- // part of diagnostic messages.
- //
- // In order to operation on types, though, we often want
- // to look past any sugar, and operate on an underlying
- // "canonical" type. The reprsentation caches a pointer to
- // a canonical type on every type, so we can easily
- // operate on the raw representation when needed.
- class ExpressionType : public Val
- {
- public:
- static RefPtr<ExpressionType> Error;
- static RefPtr<ExpressionType> initializerListType;
- static RefPtr<ExpressionType> Overloaded;
-
- static Dictionary<int, RefPtr<ExpressionType>> sBuiltinTypes;
- static Dictionary<String, Decl*> sMagicDecls;
-
- // Note: just exists to make sure we can clean up
- // canonical types we create along the way
- static List<RefPtr<ExpressionType>> sCanonicalTypes;
-
-
-
- static ExpressionType* GetBool();
- static ExpressionType* GetFloat();
- static ExpressionType* getDoubleType();
- static ExpressionType* GetInt();
- static ExpressionType* GetUInt();
- static ExpressionType* GetVoid();
- static ExpressionType* getInitializerListType();
- static ExpressionType* GetError();
-
- public:
- virtual String ToString() = 0;
-
- bool Equals(ExpressionType * type);
- bool Equals(RefPtr<ExpressionType> type);
-
- bool IsVectorType() { return As<VectorExpressionType>() != nullptr; }
- bool IsArray() { return As<ArrayExpressionType>() != nullptr; }
-
- template<typename T>
- T* As()
- {
- return dynamic_cast<T*>(GetCanonicalType());
- }
-
- // Convenience/legacy wrappers for `As<>`
- ArithmeticExpressionType * AsArithmeticType() { return As<ArithmeticExpressionType>(); }
- BasicExpressionType * AsBasicType() { return As<BasicExpressionType>(); }
- VectorExpressionType * AsVectorType() { return As<VectorExpressionType>(); }
- MatrixExpressionType * AsMatrixType() { return As<MatrixExpressionType>(); }
- ArrayExpressionType * AsArrayType() { return As<ArrayExpressionType>(); }
-
- DeclRefType* AsDeclRefType() { return As<DeclRefType>(); }
-
- NamedExpressionType* AsNamedType();
-
- bool IsTextureOrSampler();
- bool IsTexture() { return As<TextureType>() != nullptr; }
- bool IsSampler() { return As<SamplerStateType>() != nullptr; }
- bool IsStruct();
- bool IsClass();
- static void Init();
- static void Finalize();
- ExpressionType* GetCanonicalType();
-
- virtual RefPtr<Val> SubstituteImpl(Substitutions* subst, int* ioDiff) override;
-
- virtual bool EqualsVal(Val* val) override;
- protected:
- virtual bool EqualsImpl(ExpressionType * type) = 0;
-
- virtual ExpressionType* CreateCanonicalType() = 0;
- ExpressionType* canonicalType = nullptr;
- };
-
- // A substitution represents a binding of certain
- // type-level variables to concrete argument values
- class Substitutions : public RefObject
- {
- public:
- // The generic declaration that defines the
- // parametesr we are binding to arguments
- GenericDecl* genericDecl;
-
- // The actual values of the arguments
- List<RefPtr<Val>> args;
-
- // Any further substitutions, relating to outer generic declarations
- RefPtr<Substitutions> outer;
-
- // Apply a set of substitutions to the bindings in this substitution
- RefPtr<Substitutions> SubstituteImpl(Substitutions* subst, int* ioDiff);
-
- // Check if these are equivalent substitutiosn to another set
- bool Equals(Substitutions* subst);
- bool operator == (const Substitutions & subst)
- {
- return Equals(const_cast<Substitutions*>(&subst));
- }
- int GetHashCode() const
- {
- int rs = 0;
- for (auto && v : args)
- {
- rs ^= v->GetHashCode();
- rs *= 16777619;
- }
- return rs;
- }
- };
-
- class SyntaxNode : public SyntaxNodeBase
- {
- public:
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) = 0;
- };
-
- class ContainerDecl;
- class SpecializeModifier;
-
// Represents how much checking has been applied to a declaration.
enum class DeclCheckState : uint8_t
{
@@ -601,60 +205,10 @@ namespace Slang
Checked,
};
- // A syntax node which can have modifiers appled
- class ModifiableSyntaxNode : public SyntaxNode
- {
- public:
- Modifiers modifiers;
-
- template<typename T>
- FilteredModifierList<T> GetModifiersOfType() { return FilteredModifierList<T>(modifiers.first.Ptr()); }
-
- // Find the first modifier of a given type, or return `nullptr` if none is found.
- template<typename T>
- T* FindModifier()
- {
- return *GetModifiersOfType<T>().begin();
- }
-
- template<typename T>
- bool HasModifier() { return FindModifier<T>() != nullptr; }
- };
-
void addModifier(
RefPtr<ModifiableSyntaxNode> syntax,
RefPtr<Modifier> modifier);
-
- // An intermediate type to represent either a single declaration, or a group of declarations
- class DeclBase : public ModifiableSyntaxNode
- {
- public:
- };
-
- class Decl : public DeclBase
- {
- public:
- ContainerDecl* ParentDecl = nullptr;
-
- Token Name;
- String const& getName() { return Name.Content; }
- Token const& getNameToken() { return Name; }
-
-
- DeclCheckState checkState = DeclCheckState::Unchecked;
-
- // The next declaration defined in the same container with the same name
- Decl* nextInContainerWithSameName = nullptr;
-
- bool IsChecked(DeclCheckState state) { return checkState >= state; }
- void SetCheckState(DeclCheckState state)
- {
- assert(state >= checkState);
- checkState = state;
- }
- };
-
struct QualType
{
RefPtr<ExpressionType> type;
@@ -675,16 +229,6 @@ namespace Slang
RefPtr<ExpressionType> operator->() { return type; }
};
- class ExpressionSyntaxNode : public SyntaxNode
- {
- public:
- QualType Type;
- ExpressionSyntaxNode()
- {}
- };
-
-
-
// A reference to a declaration, which may include
// substitutions for generic parameters.
@@ -806,390 +350,6 @@ namespace Slang
};
- // The type of a reference to an overloaded name
- class OverloadGroupType : public ExpressionType
- {
- public:
- virtual String ToString() override;
-
- protected:
- virtual bool EqualsImpl(ExpressionType * type) override;
- virtual ExpressionType* CreateCanonicalType() override;
- virtual int GetHashCode() override;
- };
-
- // The type of an initializer-list expression (before it has
- // been coerced to some other type)
- class InitializerListType : public ExpressionType
- {
- public:
- virtual String ToString() override;
-
- protected:
- virtual bool EqualsImpl(ExpressionType * type) override;
- virtual ExpressionType* CreateCanonicalType() override;
- virtual int GetHashCode() override;
- };
-
- // The type of an expression that was erroneous
- class ErrorType : public ExpressionType
- {
- public:
- virtual String ToString() override;
-
- protected:
- virtual bool EqualsImpl(ExpressionType * type) override;
- virtual ExpressionType* CreateCanonicalType() override;
- virtual int GetHashCode() override;
- };
-
- // A type that takes the form of a reference to some declaration
- class DeclRefType : public ExpressionType
- {
- public:
- DeclRef<Decl> declRef;
-
- virtual String ToString() override;
- virtual RefPtr<Val> SubstituteImpl(Substitutions* subst, int* ioDiff) override;
-
- static DeclRefType* Create(DeclRef<Decl> declRef);
-
- protected:
- DeclRefType()
- {}
- DeclRefType(DeclRef<Decl> declRef)
- : declRef(declRef)
- {}
- virtual int GetHashCode() override;
- virtual bool EqualsImpl(ExpressionType * type) override;
- virtual ExpressionType* CreateCanonicalType() override;
- };
-
- // Base class for types that can be used in arithmetic expressions
- class ArithmeticExpressionType : public DeclRefType
- {
- public:
- virtual BasicExpressionType* GetScalarType() = 0;
- };
-
- class FunctionDeclBase;
-
- class BasicExpressionType : public ArithmeticExpressionType
- {
- public:
- BaseType BaseType;
-
- BasicExpressionType()
- {
- BaseType = Slang::BaseType::Int;
- }
- BasicExpressionType(Slang::BaseType baseType)
- {
- BaseType = baseType;
- }
- virtual Slang::String ToString() override;
- protected:
- virtual BasicExpressionType* GetScalarType() override;
- virtual bool EqualsImpl(ExpressionType * type) override;
- virtual ExpressionType* CreateCanonicalType() override;
- };
-
-
- class TextureTypeBase : public DeclRefType
- {
- public:
- // The type that results from fetching an element from this texture
- RefPtr<ExpressionType> elementType;
-
- // Bits representing the kind of texture type we are looking at
- // (e.g., `Texture2DMS` vs. `TextureCubeArray`)
- typedef uint16_t Flavor;
- Flavor flavor;
-
- enum
- {
- // Mask for the overall "shape" of the texture
- ShapeMask = SLANG_RESOURCE_BASE_SHAPE_MASK,
-
- // Flag for whether the shape has "array-ness"
- ArrayFlag = SLANG_TEXTURE_ARRAY_FLAG,
-
- // Whether or not the texture stores multiple samples per pixel
- MultisampleFlag = SLANG_TEXTURE_MULTISAMPLE_FLAG,
-
- // Whether or not this is a shadow texture
- //
- // TODO(tfoley): is this even meaningful/used?
- // ShadowFlag = 0x80,
- };
-
- enum Shape : uint8_t
- {
- Shape1D = SLANG_TEXTURE_1D,
- Shape2D = SLANG_TEXTURE_2D,
- Shape3D = SLANG_TEXTURE_3D,
- ShapeCube = SLANG_TEXTURE_CUBE,
-
- Shape1DArray = Shape1D | ArrayFlag,
- Shape2DArray = Shape2D | ArrayFlag,
- // No Shape3DArray
- ShapeCubeArray = ShapeCube | ArrayFlag,
- };
-
-
- Shape GetBaseShape() const { return Shape(flavor & ShapeMask); }
- bool isArray() const { return (flavor & ArrayFlag) != 0; }
- bool isMultisample() const { return (flavor & MultisampleFlag) != 0; }
-// bool isShadow() const { return (flavor & ShadowFlag) != 0; }
-
- SlangResourceShape getShape() const { return flavor & 0xFF; }
- SlangResourceAccess getAccess() const { return (flavor >> 8) & 0xFF; }
-
- TextureTypeBase(
- Flavor flavor,
- RefPtr<ExpressionType> elementType)
- : elementType(elementType)
- , flavor(flavor)
- {}
- };
-
- class TextureType : public TextureTypeBase
- {
- public:
- TextureType(
- Flavor flavor,
- RefPtr<ExpressionType> elementType)
- : TextureTypeBase(flavor, elementType)
- {}
- };
-
- // This is a base type for texture/sampler pairs,
- // as they exist in, e.g., GLSL
- class TextureSamplerType : public TextureTypeBase
- {
- public:
- TextureSamplerType(
- Flavor flavor,
- RefPtr<ExpressionType> elementType)
- : TextureTypeBase(flavor, elementType)
- {}
- };
-
- // This is a base type for `image*` types, as they exist in GLSL
- class GLSLImageType : public TextureTypeBase
- {
- public:
- GLSLImageType(
- Flavor flavor,
- RefPtr<ExpressionType> elementType)
- : TextureTypeBase(flavor, elementType)
- {}
- };
-
- class SamplerStateType : public DeclRefType
- {
- public:
- // What flavor of sampler state is this
- enum class Flavor : uint8_t
- {
- SamplerState,
- SamplerComparisonState,
- };
- Flavor flavor;
- };
-
- // Other cases of generic types known to the compiler
- class BuiltinGenericType : public DeclRefType
- {
- public:
- RefPtr<ExpressionType> elementType;
- };
-
- // Types that behave like pointers, in that they can be
- // dereferenced (implicitly) to access members defined
- // in the element type.
- class PointerLikeType : public BuiltinGenericType
- {};
-
- // Generic types used in existing Slang code
- // TODO(tfoley): check that these are actually working right...
- class PatchType : public PointerLikeType {};
- class StorageBufferType : public BuiltinGenericType {};
- class UniformBufferType : public PointerLikeType {};
- class PackedBufferType : public BuiltinGenericType {};
-
- // HLSL buffer-type resources
-
- class HLSLBufferType : public BuiltinGenericType {};
- class HLSLRWBufferType : public BuiltinGenericType {};
- class HLSLStructuredBufferType : public BuiltinGenericType {};
- class HLSLRWStructuredBufferType : public BuiltinGenericType {};
-
- class UntypedBufferResourceType : public DeclRefType {};
- class HLSLByteAddressBufferType : public UntypedBufferResourceType {};
- class HLSLRWByteAddressBufferType : public UntypedBufferResourceType {};
-
- class HLSLAppendStructuredBufferType : public BuiltinGenericType {};
- class HLSLConsumeStructuredBufferType : public BuiltinGenericType {};
-
- class HLSLPatchType : public DeclRefType
- {
- public:
- ExpressionType* getElementType();
- IntVal* getElementCount();
- };
-
- class HLSLInputPatchType : public HLSLPatchType {};
- class HLSLOutputPatchType : public HLSLPatchType {};
-
- // HLSL geometry shader output stream types
-
- class HLSLStreamOutputType : public BuiltinGenericType {};
- class HLSLPointStreamType : public HLSLStreamOutputType {};
- class HLSLLineStreamType : public HLSLStreamOutputType {};
- class HLSLTriangleStreamType : public HLSLStreamOutputType {};
-
- //
- class GLSLInputAttachmentType : public DeclRefType {};
-
- // Base class for types used when desugaring parameter block
- // declarations, includeing HLSL `cbuffer` or GLSL `uniform` blocks.
- class ParameterBlockType : public PointerLikeType {};
-
- class UniformParameterBlockType : public ParameterBlockType {};
- class VaryingParameterBlockType : public ParameterBlockType {};
-
- // Type for HLSL `cbuffer` declarations, and `ConstantBuffer<T>`
- // ALso used for GLSL `uniform` blocks.
- class ConstantBufferType : public UniformParameterBlockType {};
-
- // Type for HLSL `tbuffer` declarations, and `TextureBuffer<T>`
- class TextureBufferType : public UniformParameterBlockType {};
-
- // Type for GLSL `in` and `out` blocks
- class GLSLInputParameterBlockType : public VaryingParameterBlockType {};
- class GLSLOutputParameterBlockType : public VaryingParameterBlockType {};
-
- // Type for GLLSL `buffer` blocks
- class GLSLShaderStorageBufferType : public UniformParameterBlockType {};
-
- class ArrayExpressionType : public ExpressionType
- {
- public:
- RefPtr<ExpressionType> BaseType;
- RefPtr<IntVal> ArrayLength;
- virtual Slang::String ToString() override;
- protected:
- virtual bool EqualsImpl(ExpressionType * type) override;
- virtual ExpressionType* CreateCanonicalType() override;
- virtual int GetHashCode() override;
- };
-
- // The "type" of an expression that resolves to a type.
- // For example, in the expression `float(2)` the sub-expression,
- // `float` would have the type `TypeType(float)`.
- class TypeType : public ExpressionType
- {
- public:
- TypeType(RefPtr<ExpressionType> type)
- : type(type)
- {}
-
- // The type that this is the type of...
- RefPtr<ExpressionType> type;
-
-
- virtual String ToString() override;
-
- protected:
- virtual bool EqualsImpl(ExpressionType * type) override;
- virtual ExpressionType* CreateCanonicalType() override;
- virtual int GetHashCode() override;
- };
-
- class GenericDecl;
-
- // A vector type, e.g., `vector<T,N>`
- class VectorExpressionType : public ArithmeticExpressionType
- {
- public:
-#if 0
- VectorExpressionType(
- RefPtr<ExpressionType> elementType,
- RefPtr<IntVal> elementCount)
- : elementType(elementType)
- , elementCount(elementCount)
- {}
-#endif
-
- // The type of vector elements.
- // As an invariant, this should be a basic type or an alias.
- RefPtr<ExpressionType> elementType;
-
- // The number of elements
- RefPtr<IntVal> elementCount;
-
- virtual String ToString() override;
-
- protected:
- virtual BasicExpressionType* GetScalarType() override;
- };
-
- // A matrix type, e.g., `matrix<T,R,C>`
- class MatrixExpressionType : public ArithmeticExpressionType
- {
- public:
- // TODO: consider adding these back for convenience,
- // with a way to initialize them on-demand from the
- // real storage (which is in the `DeclRefType`
-#if 0
- // The type of vector elements.
- // As an invariant, this should be a basic type or an alias.
- RefPtr<ExpressionType> elementType;
-
- // The type of the matrix rows
- RefPtr<VectorExpressionType> rowType;
-
- // The number of rows and columns
- RefPtr<IntVal> rowCount;
- RefPtr<IntVal> colCount;
-#endif
- ExpressionType* getElementType();
- IntVal* getRowCount();
- IntVal* getColumnCount();
-
-
- virtual String ToString() override;
-
- protected:
- virtual BasicExpressionType* GetScalarType() override;
- };
-
- inline BaseType GetVectorBaseType(VectorExpressionType* vecType) {
- return vecType->elementType->AsBasicType()->BaseType;
- }
-
- inline int GetVectorSize(VectorExpressionType* vecType)
- {
- auto constantVal = vecType->elementCount.As<ConstantIntVal>();
- if (constantVal)
- return (int) constantVal->value;
- // TODO: what to do in this case?
- return 0;
- }
-
- class ContainerDecl;
-
-
- // A group of declarations that should be treated as a unit
- class DeclGroup : public DeclBase
- {
- public:
- List<RefPtr<Decl>> decls;
-
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
template<typename T>
struct FilteredMemberList
{
@@ -1284,32 +444,6 @@ namespace Slang
Decl* decl;
};
- // A "container" decl is a parent to other declarations
- class ContainerDecl : public Decl
- {
- public:
- List<RefPtr<Decl>> Members;
-
- template<typename T>
- FilteredMemberList<T> getMembersOfType()
- {
- return FilteredMemberList<T>(Members);
- }
-
-
- // Dictionary for looking up members by name.
- // This is built on demand before performing lookup.
- Dictionary<String, Decl*> memberDictionary;
-
- // Whether the `memberDictionary` is valid.
- // Should be set to `false` if any members get added/remoed.
- bool memberDictionaryIsValid = false;
-
- // A list of transparent members, to be used in lookup
- // Note: this is only valid if `memberDictionaryIsValid` is true
- List<TransparentMemberInfo> transparentMembers;
- };
-
template<typename T>
struct FilteredMemberRefList
{
@@ -1387,17 +521,6 @@ namespace Slang
}
};
- inline FilteredMemberRefList<Decl> getMembers(DeclRef<ContainerDecl> const& declRef)
- {
- return FilteredMemberRefList<Decl>(declRef.getDecl()->Members, declRef.substitutions);
- }
-
- template<typename T>
- inline FilteredMemberRefList<T> getMembersOfType(DeclRef<ContainerDecl> const& declRef)
- {
- return FilteredMemberRefList<T>(declRef.getDecl()->Members, declRef.substitutions);
- }
-
//
// Type Expressions
//
@@ -1422,12 +545,18 @@ namespace Slang
RefPtr<ExpressionSyntaxNode> exp;
RefPtr<ExpressionType> type;
- bool Equals(ExpressionType* other) {
+ bool Equals(ExpressionType* other);
+#if 0
+ {
return type->Equals(other);
}
- bool Equals(RefPtr<ExpressionType> other) {
+#endif
+ bool Equals(RefPtr<ExpressionType> other);
+#if 0
+ {
return type->Equals(other.Ptr());
}
+#endif
ExpressionType* Ptr() { return type.Ptr(); }
operator ExpressionType*()
{
@@ -1439,320 +568,6 @@ namespace Slang
};
- //
- // Declarations
- //
-
- // Base class for all variable-like declarations
- class VarDeclBase : public Decl
- {
- public:
- // Type of the variable
- TypeExp Type;
-
- ExpressionType* getType() { return Type.type.Ptr(); }
-
- // Initializer expression (optional)
- RefPtr<ExpressionSyntaxNode> Expr;
- };
-
- inline RefPtr<ExpressionType> GetType(DeclRef<VarDeclBase> const& declRef)
- {
- return declRef.Substitute(declRef.getDecl()->Type.Ptr());
- }
-
- inline RefPtr<ExpressionSyntaxNode> getInitExpr(DeclRef<VarDeclBase> const& declRef)
- {
- return declRef.Substitute(declRef.getDecl()->Expr);
- }
-
- // A field of a `struct` type
- class StructField : public VarDeclBase
- {
- public:
- StructField()
- {}
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- // An `AggTypeDeclBase` captures the shared functionality
- // between true aggregate type declarations and extension
- // declarations:
- //
- // - Both can container members (they are `ContainerDecl`s)
- // - Both can have declared bases
- // - Both expose a `this` variable in their body
- //
- class AggTypeDeclBase : public ContainerDecl
- {
- public:
- };
-
- // An extension to apply to an existing type
- class ExtensionDecl : public AggTypeDeclBase
- {
- public:
- TypeExp targetType;
-
- // next extension attached to the same nominal type
- ExtensionDecl* nextCandidateExtension = nullptr;
-
-
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
-
- inline RefPtr<ExpressionType> GetTargetType(DeclRef<ExtensionDecl> const& declRef)
- {
- return declRef.Substitute(declRef.getDecl()->targetType.Ptr());
- }
-
- // Declaration of a type that represents some sort of aggregate
- class AggTypeDecl : public AggTypeDeclBase
- {
- public:
-
- // extensions that might apply to this declaration
- ExtensionDecl* candidateExtensions = nullptr;
- FilteredMemberList<StructField> GetFields()
- {
- return getMembersOfType<StructField>();
- }
- StructField* FindField(String name)
- {
- for (auto field : GetFields())
- {
- if (field->Name.Content == name)
- return field.Ptr();
- }
- return nullptr;
- }
- int FindFieldIndex(String name)
- {
- int index = 0;
- for (auto field : GetFields())
- {
- if (field->Name.Content == name)
- return index;
- index++;
- }
- return -1;
- }
- };
-
- inline ExtensionDecl* GetCandidateExtensions(DeclRef<AggTypeDecl> const& declRef)
- {
- return declRef.getDecl()->candidateExtensions;
- }
-
- class StructSyntaxNode : public AggTypeDecl
- {
- public:
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- inline FilteredMemberRefList<StructField> GetFields(DeclRef<StructSyntaxNode> const& declRef)
- {
- return getMembersOfType<StructField>(declRef);
- }
-
- class ClassSyntaxNode : public AggTypeDecl
- {
- public:
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- // An interface which other types can conform to
- class InterfaceDecl : public AggTypeDecl
- {
- public:
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- // A kind of pseudo-member that represents an explicit
- // or implicit inheritance relationship.
- //
- class InheritanceDecl : public Decl
- {
- public:
- // The type expression as written
- TypeExp base;
-
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- inline RefPtr<ExpressionType> getBaseType(DeclRef<InheritanceDecl> const& declRef)
- {
- return declRef.Substitute(declRef.getDecl()->base.type);
- }
-
- // TODO: may eventually need sub-classes for explicit/direct vs. implicit/indirect inheritance
-
-
- // A declaration that represents a simple (non-aggregate) type
- class SimpleTypeDecl : public Decl
- {
- };
-
- // A `typedef` declaration
- class TypeDefDecl : public SimpleTypeDecl
- {
- public:
- TypeExp Type;
-
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- inline RefPtr<ExpressionType> GetType(DeclRef<TypeDefDecl> const& declRef)
- {
- return declRef.Substitute(declRef.getDecl()->Type.Ptr());
- }
-
- // A type alias of some kind (e.g., via `typedef`)
- class NamedExpressionType : public ExpressionType
- {
- public:
- NamedExpressionType(DeclRef<TypeDefDecl> declRef)
- : declRef(declRef)
- {}
-
- DeclRef<TypeDefDecl> declRef;
-
- virtual String ToString() override;
-
- protected:
- virtual bool EqualsImpl(ExpressionType * type) override;
- virtual ExpressionType* CreateCanonicalType() override;
- virtual int GetHashCode() override;
- };
-
-
- class StatementSyntaxNode : public ModifiableSyntaxNode
- {
- public:
- };
-
- // A scope for local declarations (e.g., as part of a statement)
- class ScopeDecl : public ContainerDecl
- {
- public:
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- class ScopeStmt : public StatementSyntaxNode
- {
- public:
- RefPtr<ScopeDecl> scopeDecl;
- };
-
- class BlockStatementSyntaxNode : public ScopeStmt
- {
- public:
- List<RefPtr<StatementSyntaxNode>> Statements;
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- class UnparsedStmt : public StatementSyntaxNode
- {
- public:
- // The tokens that were contained between `{` and `}`
- List<Token> tokens;
-
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- class ParameterSyntaxNode : public VarDeclBase
- {
- public:
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- // Base class for things that have parameter lists and can thus be applied to arguments ("called")
- class CallableDecl : public ContainerDecl
- {
- public:
- FilteredMemberList<ParameterSyntaxNode> GetParameters()
- {
- return getMembersOfType<ParameterSyntaxNode>();
- }
- TypeExp ReturnType;
- };
-
- inline RefPtr<ExpressionType> GetResultType(DeclRef<CallableDecl> const& declRef)
- {
- return declRef.Substitute(declRef.getDecl()->ReturnType.type.Ptr());
- }
-
- inline FilteredMemberRefList<ParameterSyntaxNode> GetParameters(DeclRef<CallableDecl> const& declRef)
- {
- return getMembersOfType<ParameterSyntaxNode>(declRef);
- }
-
- // Base class for callable things that may also have a body that is evaluated to produce their result
- class FunctionDeclBase : public CallableDecl
- {
- public:
- RefPtr<StatementSyntaxNode> Body;
- };
-
- // Function types are currently used for references to symbols that name
- // either ordinary functions, or "component functions."
- // We do not directly store a representation of the type, and instead
- // use a reference to the symbol to stand in for its logical type
- class FuncType : public ExpressionType
- {
- public:
- DeclRef<CallableDecl> declRef;
-
- virtual String ToString() override;
- protected:
- virtual bool EqualsImpl(ExpressionType * type) override;
- virtual ExpressionType* CreateCanonicalType() override;
- virtual int GetHashCode() override;
- };
-
- // A constructor/initializer to create instances of a type
- class ConstructorDecl : public FunctionDeclBase
- {
- public:
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- // A subscript operation used to index instances of a type
- class SubscriptDecl : public CallableDecl
- {
- public:
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- // An "accessor" for a subscript or property
- class AccessorDecl : public FunctionDeclBase
- {
- public:
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- class GetterDecl : public AccessorDecl
- {
- };
-
- class SetterDecl : public AccessorDecl
- {
- };
-
- //
-
- class FunctionSyntaxNode : public FunctionDeclBase
- {
- public:
- String InternalName;
- bool IsInline() { return HasModifier<InlineModifier>(); }
- bool IsExtern() { return HasModifier<ExternModifier>(); }
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- FunctionSyntaxNode()
- {
- }
- };
struct Scope : public RefObject
{
@@ -1770,26 +585,6 @@ namespace Slang
ContainerDecl* containerDecl;
};
- // Base class for expressions that will reference declarations
- class DeclRefExpr : public ExpressionSyntaxNode
- {
- public:
- // The scope in which to perform lookup
- RefPtr<Scope> scope;
-
- // The declaration of the symbol being referenced
- DeclRef<Decl> declRef;
-
- // The name of the symbol being referenced
- String name;
- };
-
- class VarExpressionSyntaxNode : public DeclRefExpr
- {
- public:
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
// Masks to be applied when lookup up declarations
enum class LookupMask : uint8_t
{
@@ -1871,7 +666,7 @@ namespace Slang
bool isOverloaded() const { return items.Count() > 1; }
};
- class SemanticsVisitor;
+ struct SemanticsVisitor;
struct LookupRequest
{
@@ -1883,43 +678,6 @@ namespace Slang
LookupMask mask = LookupMask::All;
};
- // An expression that references an overloaded set of declarations
- // having the same name.
- class OverloadedExpr : public ExpressionSyntaxNode
- {
- public:
- // Optional: the base expression is this overloaded result
- // arose from a member-reference expression.
- RefPtr<ExpressionSyntaxNode> base;
-
- // The lookup result that was ambiguous
- LookupResult lookupResult2;
-
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- class ConstantExpressionSyntaxNode : public ExpressionSyntaxNode
- {
- public:
- Token token;
-
- enum class ConstantType
- {
- Int,
- Bool,
- Float,
- String,
- };
- ConstantType ConstType;
- union
- {
- IntegerLiteralValue integerValue;
- FloatingPointLiteralValue floatingPointValue;
- };
- String stringValue;
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
enum class Operator
{
Neg, Not, BitNot, PreInc, PreDec, PostInc, PostDec,
@@ -1935,476 +693,35 @@ namespace Slang
Assign = 200, AddAssign, SubAssign, MulAssign, DivAssign, ModAssign,
LshAssign, RshAssign, OrAssign, AndAssign, XorAssign,
};
- String GetOperatorFunctionName(Operator op);
- String OperatorToString(Operator op);
-
- // An initializer list, e.g. `{ 1, 2, 3 }`
- class InitializerListExpr : public ExpressionSyntaxNode
- {
- public:
- List<RefPtr<ExpressionSyntaxNode>> args;
-
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- // A base expression being applied to arguments: covers
- // both ordinary `()` function calls and `<>` generic application
- class AppExprBase : public ExpressionSyntaxNode
- {
- public:
- RefPtr<ExpressionSyntaxNode> FunctionExpr;
- List<RefPtr<ExpressionSyntaxNode>> Arguments;
- };
-
-
- class InvokeExpressionSyntaxNode : public AppExprBase
- {
- public:
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- class OperatorExpressionSyntaxNode : public InvokeExpressionSyntaxNode
- {
- public:
-// Operator Operator;
-// void SetOperator(RefPtr<Scope> scope, Slang::Operator op);
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- class InfixExpr : public OperatorExpressionSyntaxNode {};
- class PrefixExpr : public OperatorExpressionSyntaxNode {};
- class PostfixExpr : public OperatorExpressionSyntaxNode {};
-
- class IndexExpressionSyntaxNode : public ExpressionSyntaxNode
- {
- public:
- RefPtr<ExpressionSyntaxNode> BaseExpression;
- RefPtr<ExpressionSyntaxNode> IndexExpression;
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- class MemberExpressionSyntaxNode : public DeclRefExpr
- {
- public:
- RefPtr<ExpressionSyntaxNode> BaseExpression;
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- class SwizzleExpr : public ExpressionSyntaxNode
- {
- public:
- RefPtr<ExpressionSyntaxNode> base;
- int elementCount;
- int elementIndices[4];
-
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- // A dereference of a pointer or pointer-like type
- class DerefExpr : public ExpressionSyntaxNode
- {
- public:
- RefPtr<ExpressionSyntaxNode> base;
-
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- class TypeCastExpressionSyntaxNode : public ExpressionSyntaxNode
- {
- public:
- TypeExp TargetType;
- RefPtr<ExpressionSyntaxNode> Expression;
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- class SelectExpressionSyntaxNode : public OperatorExpressionSyntaxNode
- {
- public:
- };
-
-
- class EmptyStatementSyntaxNode : public StatementSyntaxNode
- {
- public:
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- class DiscardStatementSyntaxNode : public StatementSyntaxNode
- {
- public:
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- struct Variable : public VarDeclBase
- {
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- class VarDeclrStatementSyntaxNode : public StatementSyntaxNode
- {
- public:
- RefPtr<DeclBase> decl;
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- // A "module" of code (essentiately, a single translation unit)
- // that provides a scope for some number of declarations.
- class ProgramSyntaxNode : public ContainerDecl
- {
- public:
- // Access members of specific types
- FilteredMemberList<FunctionSyntaxNode> GetFunctions()
- {
- return getMembersOfType<FunctionSyntaxNode>();
- }
-
- FilteredMemberList<ClassSyntaxNode> GetClasses()
- {
- return getMembersOfType<ClassSyntaxNode>();
- }
- FilteredMemberList<StructSyntaxNode> GetStructs()
- {
- return getMembersOfType<StructSyntaxNode>();
- }
- FilteredMemberList<TypeDefDecl> GetTypeDefs()
- {
- return getMembersOfType<TypeDefDecl>();
- }
-
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- class ImportDecl : public Decl
- {
- public:
- // The name of the module we are trying to import
- Token nameToken;
-
- // The scope that we want to import into
- RefPtr<Scope> scope;
-
- // The module that actually got imported
- RefPtr<ProgramSyntaxNode> importedModuleDecl;
-
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
-
- class IfStatementSyntaxNode : public StatementSyntaxNode
- {
- public:
- RefPtr<ExpressionSyntaxNode> Predicate;
- RefPtr<StatementSyntaxNode> PositiveStatement;
- RefPtr<StatementSyntaxNode> NegativeStatement;
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- // A statement that can be escaped with a `break`
- class BreakableStmt : public ScopeStmt
- {};
-
- class SwitchStmt : public BreakableStmt
- {
- public:
- RefPtr<ExpressionSyntaxNode> condition;
- RefPtr<StatementSyntaxNode> body;
-
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- // A statement that is expected to appear lexically nested inside
- // some other construct, and thus needs to keep track of the
- // outer statement that it is associated with...
- class ChildStmt : public StatementSyntaxNode
- {
- public:
- StatementSyntaxNode* parentStmt = nullptr;
- };
-
- // a `case` or `default` statement inside a `switch`
- //
- // Note(tfoley): A correct AST for a C-like language would treat
- // these as a labelled statement, and so they would contain a
- // sub-statement. I'm leaving that out for now for simplicity.
- class CaseStmtBase : public ChildStmt
- {
- public:
- };
-
- // a `case` statement inside a `switch`
- class CaseStmt : public CaseStmtBase
- {
- public:
- RefPtr<ExpressionSyntaxNode> expr;
-
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- // a `default` statement inside a `switch`
- class DefaultStmt : public CaseStmtBase
- {
- public:
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- // A statement that represents a loop, and can thus be escaped with a `continue`
- class LoopStmt : public BreakableStmt
- {};
-
- class ForStatementSyntaxNode : public LoopStmt
- {
- public:
- RefPtr<StatementSyntaxNode> InitialStatement;
- RefPtr<ExpressionSyntaxNode> SideEffectExpression, PredicateExpression;
- RefPtr<StatementSyntaxNode> Statement;
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- class WhileStatementSyntaxNode : public LoopStmt
- {
- public:
- RefPtr<ExpressionSyntaxNode> Predicate;
- RefPtr<StatementSyntaxNode> Statement;
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- class DoWhileStatementSyntaxNode : public LoopStmt
- {
- public:
- RefPtr<StatementSyntaxNode> Statement;
- RefPtr<ExpressionSyntaxNode> Predicate;
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- // The case of child statements that do control flow relative
- // to their parent statement.
- class JumpStmt : public ChildStmt
- {
- public:
- StatementSyntaxNode* parentStmt = nullptr;
- };
-
- class BreakStatementSyntaxNode : public JumpStmt
- {
- public:
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- class ContinueStatementSyntaxNode : public JumpStmt
- {
- public:
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- class ReturnStatementSyntaxNode : public StatementSyntaxNode
- {
- public:
- RefPtr<ExpressionSyntaxNode> Expression;
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- class ExpressionStatementSyntaxNode : public StatementSyntaxNode
- {
- public:
- RefPtr<ExpressionSyntaxNode> Expression;
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- // Note(tfoley): Moved this further down in the file because it depends on
- // `ExpressionSyntaxNode` and a forward reference just isn't good enough
- // for `RefPtr`.
- //
- class GenericAppExpr : public AppExprBase
- {
- public:
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- // An expression representing re-use of the syntax for a type in more
- // than once conceptually-distinct declaration
- class SharedTypeExpr : public ExpressionSyntaxNode
- {
- public:
- // The underlying type expression that we want to share
- TypeExp base;
-
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
-
- // A modifier that indicates a built-in base type (e.g., `float`)
- class BuiltinTypeModifier : public Modifier
- {
- public:
- BaseType tag;
- };
-
- // A modifier that indicates a built-in type that isn't a base type (e.g., `vector`)
- //
- // TODO(tfoley): This deserves a better name than "magic"
- class MagicTypeModifier : public Modifier
- {
- public:
- String name;
- uint32_t tag;
- };
-
- // Modifiers that affect the storage layout for matrices
- class MatrixLayoutModifier : public Modifier {};
-
- // Modifiers that specify row- and column-major layout, respectively
- class RowMajorLayoutModifier : public MatrixLayoutModifier {};
- class ColumnMajorLayoutModifier : public MatrixLayoutModifier {};
-
- // The HLSL flavor of those modifiers
- class HLSLRowMajorLayoutModifier : public RowMajorLayoutModifier {};
- class HLSLColumnMajorLayoutModifier : public ColumnMajorLayoutModifier {};
-
- // The GLSL flavor of those modifiers
- //
- // Note(tfoley): The GLSL versions of these modifiers are "backwards"
- // in the sense that when a GLSL programmer requests row-major layout,
- // we actually interpret that as requesting column-major. This makes
- // sense because we interpret matrix conventions backwards from how
- // GLSL specifies them.
- class GLSLRowMajorLayoutModifier : public ColumnMajorLayoutModifier {};
- class GLSLColumnMajorLayoutModifier : public RowMajorLayoutModifier {};
-
- // More HLSL Keyword
-
- // HLSL `nointerpolation` modifier
- class HLSLNoInterpolationModifier : public Modifier {};
-
- // HLSL `linear` modifier
- class HLSLLinearModifier : public Modifier {};
-
- // HLSL `sample` modifier
- class HLSLSampleModifier : public Modifier {};
-
- // HLSL `centroid` modifier
- class HLSLCentroidModifier : public Modifier {};
-
- // HLSL `precise` modifier
- class HLSLPreciseModifier : public Modifier {};
-
- // HLSL `shared` modifier (which is used by the effect system,
- // and shouldn't be confused with `groupshared`)
- class HLSLEffectSharedModifier : public Modifier {};
-
- // HLSL `groupshared` modifier
- class HLSLGroupSharedModifier : public Modifier {};
-
- // HLSL `static` modifier (probably doesn't need to be
- // treated as HLSL-specific)
- class HLSLStaticModifier : public Modifier {};
-
- // HLSL `uniform` modifier (distinct meaning from GLSL
- // use of the keyword)
- class HLSLUniformModifier : public Modifier {};
-
- // HLSL `volatile` modifier (ignored)
- class HLSLVolatileModifier : public Modifier {};
-
- // An HLSL `[name(arg0, ...)]` style attribute.
- class HLSLAttribute : public Modifier
- {
- public:
- Token nameToken;
- List<RefPtr<ExpressionSyntaxNode>> args;
- };
-
- // An HLSL `[name(...)]` attribute that hasn't undergone
- // any semantic analysis.
- // After analysis, this might be transformed into a more specific case.
- class HLSLUncheckedAttribute : public HLSLAttribute
- {
- public:
- };
-
- // An HLSL `[numthreads(x,y,z)]` attribute
- class HLSLNumThreadsAttribute : public HLSLAttribute
- {
- public:
- // The number of threads to use along each axis
- int32_t x;
- int32_t y;
- int32_t z;
- };
-
- // HLSL modifiers for geometry shader input topology
- class HLSLGeometryShaderInputPrimitiveTypeModifier : public Modifier {};
- class HLSLPointModifier : public HLSLGeometryShaderInputPrimitiveTypeModifier {};
- class HLSLLineModifier : public HLSLGeometryShaderInputPrimitiveTypeModifier {};
- class HLSLTriangleModifier : public HLSLGeometryShaderInputPrimitiveTypeModifier {};
- class HLSLLineAdjModifier : public HLSLGeometryShaderInputPrimitiveTypeModifier {};
- class HLSLTriangleAdjModifier : public HLSLGeometryShaderInputPrimitiveTypeModifier {};
-
- //
-
- // A generic declaration, parameterized on types/values
- class GenericDecl : public ContainerDecl
- {
- public:
- // The decl that is genericized...
- RefPtr<Decl> inner;
-
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- inline Decl* GetInner(DeclRef<GenericDecl> const& declRef)
- {
- // TODO: Should really return a `DeclRef<Decl>` for the inner
- // declaration, and not just a raw pointer
- return declRef.getDecl()->inner.Ptr();
- }
-
- // The "type" of an expression that names a generic declaration.
- class GenericDeclRefType : public ExpressionType
- {
- public:
- GenericDeclRefType(DeclRef<GenericDecl> declRef)
- : declRef(declRef)
- {}
-
- DeclRef<GenericDecl> declRef;
- DeclRef<GenericDecl> const& GetDeclRef() const { return declRef; }
-
- virtual String ToString() override;
-
- protected:
- virtual bool EqualsImpl(ExpressionType * type) override;
- virtual int GetHashCode() override;
- virtual ExpressionType* CreateCanonicalType() override;
- };
-
-
-
- class GenericTypeParamDecl : public SimpleTypeDecl
- {
- public:
- // The bound for the type parameter represents a trait that any
- // type used as this parameter must conform to
-// TypeExp bound;
-
- // The "initializer" for the parameter represents a default value
- TypeExp initType;
-
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
- // A constraint placed as part of a generic declaration
- class GenericTypeConstraintDecl : public Decl
- {
- public:
- // A type constraint like `T : U` is constraining `T` to be "below" `U`
- // on a lattice of types. This may not be a subtyping relationship
- // per se, but it makes sense to use that terminology here, so we
- // think of these fields as the sub-type and sup-ertype, respectively.
- TypeExp sub;
- TypeExp sup;
-
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
+ // Generate class definition for all syntax classes
+#define SYNTAX_FIELD(TYPE, NAME) TYPE NAME;
+#define FIELD(TYPE, NAME) TYPE NAME;
+#define FIELD_INIT(TYPE, NAME, INIT) TYPE NAME = INIT;
+#define RAW(...) __VA_ARGS__
+#define END_SYNTAX_CLASS() };
+#define SYNTAX_CLASS(NAME, BASE, ...) class NAME : public BASE {public:
+#include "object-meta-begin.h"
+
+#include "syntax-base-defs.h"
+#undef SYNTAX_CLASS
+
+#undef ABSTRACT_SYNTAX_CLASS
+#define ABSTRACT_SYNTAX_CLASS(NAME, BASE, ...) \
+ class NAME : public BASE { \
+ public: /* ... */
+#define SYNTAX_CLASS(NAME, BASE, ...) \
+ class NAME : public BASE { \
+ virtual void accept(NAME::Visitor* visitor, void* extra) override; \
+ public: /* ... */
+#include "expr-defs.h"
+#include "decl-defs.h"
+#include "modifier-defs.h"
+#include "stmt-defs.h"
+#include "type-defs.h"
+#include "val-defs.h"
+
+#include "object-meta-end.h"
inline RefPtr<ExpressionType> GetSub(DeclRef<GenericTypeConstraintDecl> const& declRef)
{
@@ -2416,56 +733,8 @@ namespace Slang
return declRef.Substitute(declRef.getDecl()->sup.Ptr());
}
- class GenericValueParamDecl : public VarDeclBase
- {
- public:
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- // The logical "value" of a rererence to a generic value parameter
- class GenericParamIntVal : public IntVal
- {
- public:
- DeclRef<VarDeclBase> declRef;
-
- GenericParamIntVal(DeclRef<VarDeclBase> declRef)
- : declRef(declRef)
- {}
-
- virtual bool EqualsVal(Val* val) override;
- virtual String ToString() override;
- virtual int GetHashCode() override;
- virtual RefPtr<Val> SubstituteImpl(Substitutions* subst, int* ioDiff) override;
- };
-
- // Declaration of a user-defined modifier
- class ModifierDecl : public Decl
- {
- public:
- // The name of the C++ class to instantiate
- // (this is a reference to a class in the compiler source code,
- // and not the user's source code)
- Token classNameToken;
-
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
- // An empty declaration (which might still have modifiers attached).
- //
- // An empty declaration is uncommon in HLSL, but
- // in GLSL it is often used at the global scope
- // to declare metadata that logically belongs
- // to the entry point, e.g.:
- //
- // layout(local_size_x = 16) in;
- //
- class EmptyDecl : public Decl
- {
- public:
- virtual RefPtr<SyntaxNode> Accept(SyntaxVisitor * visitor) override;
- };
-
//
+#if 0
class SyntaxVisitor : public RefObject
{
@@ -2742,6 +1011,8 @@ namespace Slang
virtual RefPtr<ExpressionSyntaxNode> visitInitializerListExpr(InitializerListExpr* expr) = 0;
};
+#endif
+
// Note(tfoley): These logically belong to `ExpressionType`,
// but order-of-declaration stuff makes that tricky
//
@@ -2762,6 +1033,88 @@ namespace Slang
SyntaxNodeBase* createInstanceOfSyntaxClassByName(
String const& name);
+ //
+
+ inline BaseType GetVectorBaseType(VectorExpressionType* vecType) {
+ return vecType->elementType->AsBasicType()->BaseType;
+ }
+
+ inline int GetVectorSize(VectorExpressionType* vecType)
+ {
+ auto constantVal = vecType->elementCount.As<ConstantIntVal>();
+ if (constantVal)
+ return (int) constantVal->value;
+ // TODO: what to do in this case?
+ return 0;
+ }
+
+ //
+ // Declarations
+ //
+
+ inline FilteredMemberRefList<Decl> getMembers(DeclRef<ContainerDecl> const& declRef)
+ {
+ return FilteredMemberRefList<Decl>(declRef.getDecl()->Members, declRef.substitutions);
+ }
+
+ template<typename T>
+ inline FilteredMemberRefList<T> getMembersOfType(DeclRef<ContainerDecl> const& declRef)
+ {
+ return FilteredMemberRefList<T>(declRef.getDecl()->Members, declRef.substitutions);
+ }
+
+ inline RefPtr<ExpressionType> GetType(DeclRef<VarDeclBase> const& declRef)
+ {
+ return declRef.Substitute(declRef.getDecl()->Type.Ptr());
+ }
+
+ inline RefPtr<ExpressionSyntaxNode> getInitExpr(DeclRef<VarDeclBase> const& declRef)
+ {
+ return declRef.Substitute(declRef.getDecl()->Expr);
+ }
+
+ inline RefPtr<ExpressionType> GetTargetType(DeclRef<ExtensionDecl> const& declRef)
+ {
+ return declRef.Substitute(declRef.getDecl()->targetType.Ptr());
+ }
+
+ inline ExtensionDecl* GetCandidateExtensions(DeclRef<AggTypeDecl> const& declRef)
+ {
+ return declRef.getDecl()->candidateExtensions;
+ }
+
+ inline FilteredMemberRefList<StructField> GetFields(DeclRef<StructSyntaxNode> const& declRef)
+ {
+ return getMembersOfType<StructField>(declRef);
+ }
+
+ inline RefPtr<ExpressionType> getBaseType(DeclRef<InheritanceDecl> const& declRef)
+ {
+ return declRef.Substitute(declRef.getDecl()->base.type);
+ }
+
+ inline RefPtr<ExpressionType> GetType(DeclRef<TypeDefDecl> const& declRef)
+ {
+ return declRef.Substitute(declRef.getDecl()->Type.Ptr());
+ }
+
+ inline RefPtr<ExpressionType> GetResultType(DeclRef<CallableDecl> const& declRef)
+ {
+ return declRef.Substitute(declRef.getDecl()->ReturnType.type.Ptr());
+ }
+
+ inline FilteredMemberRefList<ParameterSyntaxNode> GetParameters(DeclRef<CallableDecl> const& declRef)
+ {
+ return getMembersOfType<ParameterSyntaxNode>(declRef);
+ }
+
+ inline Decl* GetInner(DeclRef<GenericDecl> const& declRef)
+ {
+ // TODO: Should really return a `DeclRef<Decl>` for the inner
+ // declaration, and not just a raw pointer
+ return declRef.getDecl()->inner.Ptr();
+ }
+
} // namespace Slang
#endif \ No newline at end of file
diff --git a/source/slang/type-defs.h b/source/slang/type-defs.h
new file mode 100644
index 000000000..a01b49277
--- /dev/null
+++ b/source/slang/type-defs.h
@@ -0,0 +1,393 @@
+// type-defs.h
+
+// Syntax class definitions for types.
+
+// The type of a reference to an overloaded name
+SYNTAX_CLASS(OverloadGroupType, ExpressionType)
+RAW(
+public:
+ virtual String ToString() override;
+
+protected:
+ virtual bool EqualsImpl(ExpressionType * type) override;
+ virtual ExpressionType* CreateCanonicalType() override;
+ virtual int GetHashCode() override;
+)
+END_SYNTAX_CLASS()
+
+// The type of an initializer-list expression (before it has
+// been coerced to some other type)
+SYNTAX_CLASS(InitializerListType, ExpressionType)
+RAW(
+ virtual String ToString() override;
+
+protected:
+ virtual bool EqualsImpl(ExpressionType * type) override;
+ virtual ExpressionType* CreateCanonicalType() override;
+ virtual int GetHashCode() override;
+)
+END_SYNTAX_CLASS()
+
+// The type of an expression that was erroneous
+SYNTAX_CLASS(ErrorType, ExpressionType)
+RAW(
+public:
+ virtual String ToString() override;
+
+protected:
+ virtual bool EqualsImpl(ExpressionType * type) override;
+ virtual ExpressionType* CreateCanonicalType() override;
+ virtual int GetHashCode() override;
+)
+END_SYNTAX_CLASS()
+
+// A type that takes the form of a reference to some declaration
+SYNTAX_CLASS(DeclRefType, ExpressionType)
+ DECL_FIELD(DeclRef<Decl>, declRef)
+
+RAW(
+ virtual String ToString() override;
+ virtual RefPtr<Val> SubstituteImpl(Substitutions* subst, int* ioDiff) override;
+
+ static DeclRefType* Create(DeclRef<Decl> declRef);
+
+protected:
+ DeclRefType()
+ {}
+ DeclRefType(DeclRef<Decl> declRef)
+ : declRef(declRef)
+ {}
+ virtual int GetHashCode() override;
+ virtual bool EqualsImpl(ExpressionType * type) override;
+ virtual ExpressionType* CreateCanonicalType() override;
+)
+END_SYNTAX_CLASS()
+
+// Base class for types that can be used in arithmetic expressions
+SYNTAX_CLASS(ArithmeticExpressionType, DeclRefType)
+RAW(
+ virtual BasicExpressionType* GetScalarType() = 0;
+)
+END_SYNTAX_CLASS()
+
+SYNTAX_CLASS(BasicExpressionType, ArithmeticExpressionType)
+
+ FIELD(BaseType, BaseType)
+
+RAW(
+ BasicExpressionType()
+ {
+ BaseType = Slang::BaseType::Int;
+ }
+ BasicExpressionType(Slang::BaseType baseType)
+ {
+ BaseType = baseType;
+ }
+ virtual Slang::String ToString() override;
+protected:
+ virtual BasicExpressionType* GetScalarType() override;
+ virtual bool EqualsImpl(ExpressionType * type) override;
+ virtual ExpressionType* CreateCanonicalType() override;
+)
+END_SYNTAX_CLASS()
+
+
+SYNTAX_CLASS(TextureTypeBase, DeclRefType)
+ // The type that results from fetching an element from this texture
+ SYNTAX_FIELD(RefPtr<ExpressionType>, elementType)
+
+ // Bits representing the kind of texture type we are looking at
+ // (e.g., `Texture2DMS` vs. `TextureCubeArray`)
+ RAW(typedef uint16_t Flavor;)
+ FIELD(Flavor, flavor)
+
+RAW(
+ enum
+ {
+ // Mask for the overall "shape" of the texture
+ ShapeMask = SLANG_RESOURCE_BASE_SHAPE_MASK,
+
+ // Flag for whether the shape has "array-ness"
+ ArrayFlag = SLANG_TEXTURE_ARRAY_FLAG,
+
+ // Whether or not the texture stores multiple samples per pixel
+ MultisampleFlag = SLANG_TEXTURE_MULTISAMPLE_FLAG,
+
+ // Whether or not this is a shadow texture
+ //
+ // TODO(tfoley): is this even meaningful/used?
+ // ShadowFlag = 0x80,
+ };
+
+ enum Shape : uint8_t
+ {
+ Shape1D = SLANG_TEXTURE_1D,
+ Shape2D = SLANG_TEXTURE_2D,
+ Shape3D = SLANG_TEXTURE_3D,
+ ShapeCube = SLANG_TEXTURE_CUBE,
+
+ Shape1DArray = Shape1D | ArrayFlag,
+ Shape2DArray = Shape2D | ArrayFlag,
+ // No Shape3DArray
+ ShapeCubeArray = ShapeCube | ArrayFlag,
+ };
+
+
+ Shape GetBaseShape() const { return Shape(flavor & ShapeMask); }
+ bool isArray() const { return (flavor & ArrayFlag) != 0; }
+ bool isMultisample() const { return (flavor & MultisampleFlag) != 0; }
+// bool isShadow() const { return (flavor & ShadowFlag) != 0; }
+
+ SlangResourceShape getShape() const { return flavor & 0xFF; }
+ SlangResourceAccess getAccess() const { return (flavor >> 8) & 0xFF; }
+
+ TextureTypeBase(
+ Flavor flavor,
+ RefPtr<ExpressionType> elementType)
+ : elementType(elementType)
+ , flavor(flavor)
+ {}
+)
+END_SYNTAX_CLASS()
+
+SYNTAX_CLASS(TextureType, TextureTypeBase)
+RAW(
+ TextureType(
+ Flavor flavor,
+ RefPtr<ExpressionType> elementType)
+ : TextureTypeBase(flavor, elementType)
+ {}
+)
+END_SYNTAX_CLASS()
+
+// This is a base type for texture/sampler pairs,
+// as they exist in, e.g., GLSL
+SYNTAX_CLASS(TextureSamplerType, TextureTypeBase)
+RAW(
+ TextureSamplerType(
+ Flavor flavor,
+ RefPtr<ExpressionType> elementType)
+ : TextureTypeBase(flavor, elementType)
+ {}
+)
+END_SYNTAX_CLASS()
+
+// This is a base type for `image*` types, as they exist in GLSL
+SYNTAX_CLASS(GLSLImageType, TextureTypeBase)
+RAW(
+ GLSLImageType(
+ Flavor flavor,
+ RefPtr<ExpressionType> elementType)
+ : TextureTypeBase(flavor, elementType)
+ {}
+)
+END_SYNTAX_CLASS()
+
+SYNTAX_CLASS(SamplerStateType, DeclRefType)
+
+ // What flavor of sampler state is this
+ RAW(enum class Flavor : uint8_t
+ {
+ SamplerState,
+ SamplerComparisonState,
+ };)
+ FIELD(Flavor, flavor)
+END_SYNTAX_CLASS()
+
+// Other cases of generic types known to the compiler
+SYNTAX_CLASS(BuiltinGenericType, DeclRefType)
+ SYNTAX_FIELD(RefPtr<ExpressionType>, elementType)
+END_SYNTAX_CLASS()
+
+// Types that behave like pointers, in that they can be
+// dereferenced (implicitly) to access members defined
+// in the element type.
+SIMPLE_SYNTAX_CLASS(PointerLikeType, BuiltinGenericType)
+
+// Generic types used in existing Slang code
+// TODO(tfoley): check that these are actually working right...
+SIMPLE_SYNTAX_CLASS(PatchType, PointerLikeType)
+SIMPLE_SYNTAX_CLASS(StorageBufferType, BuiltinGenericType)
+SIMPLE_SYNTAX_CLASS(UniformBufferType, PointerLikeType)
+SIMPLE_SYNTAX_CLASS(PackedBufferType, BuiltinGenericType)
+
+// HLSL buffer-type resources
+
+SIMPLE_SYNTAX_CLASS(HLSLBufferType, BuiltinGenericType)
+SIMPLE_SYNTAX_CLASS(HLSLRWBufferType, BuiltinGenericType)
+SIMPLE_SYNTAX_CLASS(HLSLStructuredBufferType, BuiltinGenericType)
+SIMPLE_SYNTAX_CLASS(HLSLRWStructuredBufferType, BuiltinGenericType)
+
+SIMPLE_SYNTAX_CLASS(UntypedBufferResourceType, DeclRefType)
+SIMPLE_SYNTAX_CLASS(HLSLByteAddressBufferType, UntypedBufferResourceType)
+SIMPLE_SYNTAX_CLASS(HLSLRWByteAddressBufferType, UntypedBufferResourceType)
+
+SIMPLE_SYNTAX_CLASS(HLSLAppendStructuredBufferType, BuiltinGenericType)
+SIMPLE_SYNTAX_CLASS(HLSLConsumeStructuredBufferType, BuiltinGenericType)
+
+SYNTAX_CLASS(HLSLPatchType, DeclRefType)
+RAW(
+ ExpressionType* getElementType();
+ IntVal* getElementCount();
+)
+END_SYNTAX_CLASS()
+
+SIMPLE_SYNTAX_CLASS(HLSLInputPatchType, HLSLPatchType)
+SIMPLE_SYNTAX_CLASS(HLSLOutputPatchType, HLSLPatchType)
+
+// HLSL geometry shader output stream types
+
+SIMPLE_SYNTAX_CLASS(HLSLStreamOutputType, BuiltinGenericType)
+SIMPLE_SYNTAX_CLASS(HLSLPointStreamType, HLSLStreamOutputType)
+SIMPLE_SYNTAX_CLASS(HLSLLineStreamType, HLSLStreamOutputType)
+SIMPLE_SYNTAX_CLASS(HLSLTriangleStreamType, HLSLStreamOutputType)
+
+//
+SIMPLE_SYNTAX_CLASS(GLSLInputAttachmentType, DeclRefType)
+
+// Base class for types used when desugaring parameter block
+// declarations, includeing HLSL `cbuffer` or GLSL `uniform` blocks.
+SIMPLE_SYNTAX_CLASS(ParameterBlockType, PointerLikeType)
+
+SIMPLE_SYNTAX_CLASS(UniformParameterBlockType, ParameterBlockType)
+SIMPLE_SYNTAX_CLASS(VaryingParameterBlockType, ParameterBlockType)
+
+// Type for HLSL `cbuffer` declarations, and `ConstantBuffer<T>`
+// ALso used for GLSL `uniform` blocks.
+SIMPLE_SYNTAX_CLASS(ConstantBufferType, UniformParameterBlockType)
+
+// Type for HLSL `tbuffer` declarations, and `TextureBuffer<T>`
+SIMPLE_SYNTAX_CLASS(TextureBufferType, UniformParameterBlockType)
+
+// Type for GLSL `in` and `out` blocks
+SIMPLE_SYNTAX_CLASS(GLSLInputParameterBlockType, VaryingParameterBlockType)
+SIMPLE_SYNTAX_CLASS(GLSLOutputParameterBlockType, VaryingParameterBlockType)
+
+// Type for GLLSL `buffer` blocks
+SIMPLE_SYNTAX_CLASS(GLSLShaderStorageBufferType, UniformParameterBlockType)
+
+SYNTAX_CLASS(ArrayExpressionType, ExpressionType)
+ SYNTAX_FIELD(RefPtr<ExpressionType>, BaseType)
+ SYNTAX_FIELD(RefPtr<IntVal>, ArrayLength)
+
+RAW(
+ virtual Slang::String ToString() override;
+protected:
+ virtual bool EqualsImpl(ExpressionType * type) override;
+ virtual ExpressionType* CreateCanonicalType() override;
+ virtual int GetHashCode() override;
+)
+END_SYNTAX_CLASS()
+
+// The "type" of an expression that resolves to a type.
+// For example, in the expression `float(2)` the sub-expression,
+// `float` would have the type `TypeType(float)`.
+SYNTAX_CLASS(TypeType, ExpressionType)
+ // The type that this is the type of...
+ SYNTAX_FIELD(RefPtr<ExpressionType>, type)
+
+RAW(
+public:
+ TypeType(RefPtr<ExpressionType> type)
+ : type(type)
+ {}
+
+ virtual String ToString() override;
+
+protected:
+ virtual bool EqualsImpl(ExpressionType * type) override;
+ virtual ExpressionType* CreateCanonicalType() override;
+ virtual int GetHashCode() override;
+)
+END_SYNTAX_CLASS()
+
+// A vector type, e.g., `vector<T,N>`
+SYNTAX_CLASS(VectorExpressionType, ArithmeticExpressionType)
+
+ // The type of vector elements.
+ // As an invariant, this should be a basic type or an alias.
+ SYNTAX_FIELD(RefPtr<ExpressionType>, elementType)
+
+ // The number of elements
+ SYNTAX_FIELD(RefPtr<IntVal>, elementCount)
+
+RAW(
+ virtual String ToString() override;
+
+protected:
+ virtual BasicExpressionType* GetScalarType() override;
+)
+END_SYNTAX_CLASS()
+
+// A matrix type, e.g., `matrix<T,R,C>`
+SYNTAX_CLASS(MatrixExpressionType, ArithmeticExpressionType)
+RAW(
+ ExpressionType* getElementType();
+ IntVal* getRowCount();
+ IntVal* getColumnCount();
+
+
+ virtual String ToString() override;
+
+protected:
+ virtual BasicExpressionType* GetScalarType() override;
+)
+END_SYNTAX_CLASS()
+
+// A type alias of some kind (e.g., via `typedef`)
+SYNTAX_CLASS(NamedExpressionType, ExpressionType)
+ DECL_FIELD(DeclRef<TypeDefDecl>, declRef)
+
+RAW(
+ NamedExpressionType(DeclRef<TypeDefDecl> declRef)
+ : declRef(declRef)
+ {}
+
+
+ virtual String ToString() override;
+
+protected:
+ virtual bool EqualsImpl(ExpressionType * type) override;
+ virtual ExpressionType* CreateCanonicalType() override;
+ virtual int GetHashCode() override;
+)
+END_SYNTAX_CLASS()
+
+// Function types are currently used for references to symbols that name
+// either ordinary functions, or "component functions."
+// We do not directly store a representation of the type, and instead
+// use a reference to the symbol to stand in for its logical type
+SYNTAX_CLASS(FuncType, ExpressionType)
+ DECL_FIELD(DeclRef<CallableDecl>, declRef)
+
+RAW(
+ virtual String ToString() override;
+protected:
+ virtual bool EqualsImpl(ExpressionType * type) override;
+ virtual ExpressionType* CreateCanonicalType() override;
+ virtual int GetHashCode() override;
+)
+END_SYNTAX_CLASS()
+
+// The "type" of an expression that names a generic declaration.
+SYNTAX_CLASS(GenericDeclRefType, ExpressionType)
+
+ DECL_FIELD(DeclRef<GenericDecl>, declRef)
+
+ RAW(
+ GenericDeclRefType(DeclRef<GenericDecl> declRef)
+ : declRef(declRef)
+ {}
+
+
+ DeclRef<GenericDecl> const& GetDeclRef() const { return declRef; }
+
+ virtual String ToString() override;
+
+protected:
+ virtual bool EqualsImpl(ExpressionType * type) override;
+ virtual int GetHashCode() override;
+ virtual ExpressionType* CreateCanonicalType() override;
+)
+END_SYNTAX_CLASS()
+
diff --git a/source/slang/val-defs.h b/source/slang/val-defs.h
new file mode 100644
index 000000000..316981842
--- /dev/null
+++ b/source/slang/val-defs.h
@@ -0,0 +1,37 @@
+// val-defs.h
+
+// Syntax class definitions for compile-time values.
+
+// A compile-time integer (may not have a specific concrete value)
+SIMPLE_SYNTAX_CLASS(IntVal, Val)
+
+// Trivial case of a value that is just a constant integer
+SYNTAX_CLASS(ConstantIntVal, IntVal)
+ FIELD(IntegerLiteralValue, value)
+
+ RAW(
+ ConstantIntVal(IntegerLiteralValue value)
+ : value(value)
+ {}
+
+ virtual bool EqualsVal(Val* val) override;
+ virtual String ToString() override;
+ virtual int GetHashCode() override;
+ )
+END_SYNTAX_CLASS()
+
+// The logical "value" of a rererence to a generic value parameter
+SYNTAX_CLASS(GenericParamIntVal, IntVal)
+ DECL_FIELD(DeclRef<VarDeclBase>, declRef)
+
+ RAW(
+ GenericParamIntVal(DeclRef<VarDeclBase> declRef)
+ : declRef(declRef)
+ {}
+
+ virtual bool EqualsVal(Val* val) override;
+ virtual String ToString() override;
+ virtual int GetHashCode() override;
+ virtual RefPtr<Val> SubstituteImpl(Substitutions* subst, int* ioDiff) override;
+)
+END_SYNTAX_CLASS()
diff --git a/source/slang/visitor.h b/source/slang/visitor.h
new file mode 100644
index 000000000..391769eca
--- /dev/null
+++ b/source/slang/visitor.h
@@ -0,0 +1,346 @@
+// visitor.h
+#ifndef SLANG_VISITOR_H_INCLUDED
+#define SLANG_VISITOR_H_INCLUDED
+
+// This file defines the basic "Visitor" pattern for doing dispatch
+// over the various categories of syntax node.
+
+#include "syntax.h"
+
+namespace Slang {
+
+//
+// Type Visitors
+//
+
+struct ITypeVisitor
+{
+#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
+#define SYNTAX_CLASS(NAME, BASE) \
+ virtual void dispatch_##NAME(NAME* obj, void* extra) = 0;
+
+#include "object-meta-begin.h"
+#include "type-defs.h"
+#include "object-meta-end.h"
+};
+
+template<typename Derived, typename Result = void>
+struct TypeVisitor : ITypeVisitor
+{
+ Result dispatch(ExpressionType* type)
+ {
+ Result result;
+ type->accept(this, &result);
+ return result;
+ }
+
+#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
+#define SYNTAX_CLASS(NAME, BASE) \
+ virtual void dispatch_##NAME(NAME* obj, void* extra) override \
+ { *(Result*)extra = ((Derived*) this)->visit(obj); }
+
+#include "object-meta-begin.h"
+#include "type-defs.h"
+#include "object-meta-end.h"
+
+};
+
+template<typename Derived>
+struct TypeVisitor<Derived,void> : ITypeVisitor
+{
+ void dispatch(ExpressionType* type)
+ {
+ type->accept(this, 0);
+ }
+
+#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
+#define SYNTAX_CLASS(NAME, BASE) \
+ virtual void dispatch_##NAME(NAME* obj, void*) override \
+ { ((Derived*) this)->visit(obj); }
+
+#include "object-meta-begin.h"
+#include "type-defs.h"
+#include "object-meta-end.h"
+
+};
+
+//
+// Expression Visitors
+//
+
+struct IExprVisitor
+{
+#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
+#define SYNTAX_CLASS(NAME, BASE) \
+ virtual void dispatch_##NAME(NAME* obj, void* extra) = 0;
+
+#include "object-meta-begin.h"
+#include "expr-defs.h"
+#include "object-meta-end.h"
+};
+
+template<typename Derived, typename Result = void>
+struct ExprVisitor : IExprVisitor
+{
+ Result dispatch(ExpressionSyntaxNode* expr)
+ {
+ Result result;
+ expr->accept(this, &result);
+ return result;
+ }
+
+#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
+#define SYNTAX_CLASS(NAME, BASE) \
+ virtual void dispatch_##NAME(NAME* obj, void* extra) override \
+ { *(Result*)extra = ((Derived*) this)->visit(obj); }
+
+#include "object-meta-begin.h"
+#include "expr-defs.h"
+#include "object-meta-end.h"
+
+};
+
+template<typename Derived>
+struct ExprVisitor<Derived,void> : IExprVisitor
+{
+ void dispatch(ExpressionSyntaxNode* expr)
+ {
+ expr->accept(this, 0);
+ }
+
+#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
+#define SYNTAX_CLASS(NAME, BASE) \
+ virtual void dispatch_##NAME(NAME* obj, void*) override \
+ { ((Derived*) this)->visit(obj); }
+
+#include "object-meta-begin.h"
+#include "expr-defs.h"
+#include "object-meta-end.h"
+
+};
+
+//
+// Statement Visitors
+//
+
+struct IStmtVisitor
+{
+#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
+#define SYNTAX_CLASS(NAME, BASE) \
+ virtual void dispatch_##NAME(NAME* obj, void* extra) = 0;
+
+#include "object-meta-begin.h"
+#include "stmt-defs.h"
+#include "object-meta-end.h"
+};
+
+template<typename Derived, typename Result = void>
+struct StmtVisitor : IStmtVisitor
+{
+ Result dispatch(StatementSyntaxNode* stmt)
+ {
+ Result result;
+ stmt->accept(this, &result);
+ return result;
+ }
+
+#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
+#define SYNTAX_CLASS(NAME, BASE) \
+ virtual void dispatch_##NAME(NAME* obj, void* extra) override \
+ { *(Result*)extra = ((Derived*) this)->visit(obj); }
+
+#include "object-meta-begin.h"
+#include "stmt-defs.h"
+#include "object-meta-end.h"
+
+};
+
+template<typename Derived>
+struct StmtVisitor<Derived,void> : IStmtVisitor
+{
+ void dispatch(StatementSyntaxNode* stmt)
+ {
+ stmt->accept(this, 0);
+ }
+
+#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
+#define SYNTAX_CLASS(NAME, BASE) \
+ virtual void dispatch_##NAME(NAME* obj, void*) override \
+ { ((Derived*) this)->visit(obj); }
+
+#include "object-meta-begin.h"
+#include "stmt-defs.h"
+#include "object-meta-end.h"
+
+};
+
+//
+// Declaration Visitors
+//
+
+struct IDeclVisitor
+{
+#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
+#define SYNTAX_CLASS(NAME, BASE) \
+ virtual void dispatch_##NAME(NAME* obj, void* extra) = 0;
+
+#include "object-meta-begin.h"
+#include "decl-defs.h"
+#include "object-meta-end.h"
+};
+
+template<typename Derived, typename Result = void>
+struct DeclVisitor : IDeclVisitor
+{
+ Result dispatch(DeclBase* decl)
+ {
+ Result result;
+ decl->accept(this, &result);
+ return result;
+ }
+
+#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
+#define SYNTAX_CLASS(NAME, BASE) \
+ virtual void dispatch_##NAME(NAME* obj, void* extra) override \
+ { *(Result*)extra = ((Derived*) this)->visit(obj); }
+
+#include "object-meta-begin.h"
+#include "decl-defs.h"
+#include "object-meta-end.h"
+
+};
+
+template<typename Derived>
+struct DeclVisitor<Derived,void> : IDeclVisitor
+{
+ void dispatch(DeclBase* decl)
+ {
+ decl->accept(this, 0);
+ }
+
+#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
+#define SYNTAX_CLASS(NAME, BASE) \
+ virtual void dispatch_##NAME(NAME* obj, void*) override \
+ { ((Derived*) this)->visit(obj); }
+
+#include "object-meta-begin.h"
+#include "decl-defs.h"
+#include "object-meta-end.h"
+
+};
+
+//
+// Modifier Visitors
+//
+
+struct IModifierVisitor
+{
+#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
+#define SYNTAX_CLASS(NAME, BASE) \
+ virtual void dispatch_##NAME(NAME* obj, void* extra) = 0;
+
+#include "object-meta-begin.h"
+#include "modifier-defs.h"
+#include "object-meta-end.h"
+};
+
+template<typename Derived, typename Result = void>
+struct ModifierVisitor : IModifierVisitor
+{
+ Result dispatch(Modifier* modifier)
+ {
+ Result result;
+ modifier->accept(this, &result);
+ return result;
+ }
+
+#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
+#define SYNTAX_CLASS(NAME, BASE) \
+ virtual void dispatch_##NAME(NAME* obj, void* extra) override \
+ { *(Result*)extra = ((Derived*) this)->visit(obj); }
+
+#include "object-meta-begin.h"
+#include "modifier-defs.h"
+#include "object-meta-end.h"
+
+};
+
+template<typename Derived>
+struct ModifierVisitor<Derived, void> : IModifierVisitor
+{
+ void dispatch(Modifier* modifier)
+ {
+ modifier->accept(this, 0);
+ }
+
+#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
+#define SYNTAX_CLASS(NAME, BASE) \
+ virtual void dispatch_##NAME(NAME* obj, void*) override \
+ { ((Derived*) this)->visit(obj); }
+
+#include "object-meta-begin.h"
+#include "modifier-defs.h"
+#include "object-meta-end.h"
+
+};
+
+//
+// Val Visitors
+//
+
+struct IValVisitor : ITypeVisitor
+{
+#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
+#define SYNTAX_CLASS(NAME, BASE) \
+ virtual void dispatch_##NAME(NAME* obj, void* extra) = 0;
+
+#include "object-meta-begin.h"
+#include "val-defs.h"
+#include "object-meta-end.h"
+};
+
+template<typename Derived, typename Result = void>
+struct ValVisitor : IValVisitor
+{
+ Result dispatch(Val* val)
+ {
+ Result result;
+ val->accept(this, &result);
+ return result;
+ }
+
+#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
+#define SYNTAX_CLASS(NAME, BASE) \
+ virtual void dispatch_##NAME(NAME* obj, void* extra) override \
+ { *(Result*)extra = ((Derived*) this)->visit(obj); }
+
+#include "object-meta-begin.h"
+#include "val-defs.h"
+#include "type-defs.h"
+#include "object-meta-end.h"
+
+};
+
+template<typename Derived>
+struct ValVisitor<Derived, void> : IValVisitor
+{
+ void dispatch(Val* val)
+ {
+ val->accept(this, 0);
+ }
+
+#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */
+#define SYNTAX_CLASS(NAME, BASE) \
+ virtual void dispatch_##NAME(NAME* obj, void*) override \
+ { ((Derived*) this)->visit(obj); }
+
+#include "object-meta-begin.h"
+#include "val-defs.h"
+#include "type-defs.h"
+#include "object-meta-end.h"
+
+};
+
+}
+
+#endif \ No newline at end of file
diff --git a/tests/diagnostics/while-predicate-type.slang.expected b/tests/diagnostics/while-predicate-type.slang.expected
index d921c588e..c65cb6ef8 100644
--- a/tests/diagnostics/while-predicate-type.slang.expected
+++ b/tests/diagnostics/while-predicate-type.slang.expected
@@ -1,6 +1,6 @@
result code = -1
standard error = {
-tests/diagnostics/while-predicate-type.slang(9): error 30010: 'while': expression must evaluate to int.
+tests/diagnostics/while-predicate-type.slang(9): error 30019: expected an expression of type 'bool', got 'S'
}
standard output = {
}