summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2017-08-11 14:04:24 -0700
committerGitHub <noreply@github.com>2017-08-11 14:04:24 -0700
commit495f88167527945e680e091d49b5705f5f1af1f9 (patch)
tree8be4a0505bd121edbbcf5dd5b3cd9d43c51ec377 /source
parentdb4079f7e3635a6a61b8725643b1d7ecf68b97d8 (diff)
parentb2febc7966c2533f756a6829656423f05b2f21e5 (diff)
Merge pull request #157 from tfoleyNV/syntax-lookup
Look up declaration keywords using ordinary scoping.
Diffstat (limited to 'source')
-rw-r--r--source/slang/check.cpp5
-rw-r--r--source/slang/compiler.h1
-rw-r--r--source/slang/decl-defs.h11
-rw-r--r--source/slang/emit.cpp1
-rw-r--r--source/slang/lexer.cpp2
-rw-r--r--source/slang/lower.cpp5
-rw-r--r--source/slang/parser.cpp492
-rw-r--r--source/slang/parser.h5
-rw-r--r--source/slang/slang.cpp8
-rw-r--r--source/slang/syntax.cpp40
-rw-r--r--source/slang/syntax.h50
11 files changed, 353 insertions, 267 deletions
diff --git a/source/slang/check.cpp b/source/slang/check.cpp
index 23394e107..9f7a13230 100644
--- a/source/slang/check.cpp
+++ b/source/slang/check.cpp
@@ -1197,6 +1197,11 @@ namespace Slang
return constIntVal;
}
+ void visitSyntaxDecl(SyntaxDecl*)
+ {
+ // These are only used in the stdlib, so no checking is needed
+ }
+
void visitModifierDecl(ModifierDecl*)
{
// These are only used in the stdlib, so no checking is needed
diff --git a/source/slang/compiler.h b/source/slang/compiler.h
index 5a6cb5c19..4e779348d 100644
--- a/source/slang/compiler.h
+++ b/source/slang/compiler.h
@@ -323,6 +323,7 @@ namespace Slang
public:
//
+ RefPtr<Scope> baseLanguageScope;
RefPtr<Scope> coreLanguageScope;
RefPtr<Scope> hlslLanguageScope;
RefPtr<Scope> slangLanguageScope;
diff --git a/source/slang/decl-defs.h b/source/slang/decl-defs.h
index 4f219e63c..dc1647fd5 100644
--- a/source/slang/decl-defs.h
+++ b/source/slang/decl-defs.h
@@ -230,3 +230,14 @@ END_SYNTAX_CLASS()
// layout(local_size_x = 16) in;
//
SIMPLE_SYNTAX_CLASS(EmptyDecl, Decl)
+
+// A declaration used by the implementation to put syntax keywords
+// into the current scope.
+//
+SYNTAX_CLASS(SyntaxDecl, Decl)
+ // What type of syntax node will be produced when parsing with this keyword?
+ FIELD(SyntaxClass<SyntaxNode>, syntaxClass)
+
+ // Callback to invoke in order to parse syntax with this keyword.
+ FIELD(SyntaxParseCallback, parserCallback)
+END_SYNTAX_CLASS()
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index 2a5f40787..816e37391 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -2747,6 +2747,7 @@ struct EmitVisitor
// Only used by stdlib
IGNORED(ModifierDecl)
+ IGNORED(SyntaxDecl)
// Don't emit generic decls directly; we will only
// ever emit particular instantiations of them.
diff --git a/source/slang/lexer.cpp b/source/slang/lexer.cpp
index fe01878d1..351e3f664 100644
--- a/source/slang/lexer.cpp
+++ b/source/slang/lexer.cpp
@@ -833,7 +833,7 @@ namespace Slang
// Now we look at another character to figure out the kind of
// escape sequence we are dealing with:
- int d = *cursor++;
+ char d = *cursor++;
switch(d)
{
diff --git a/source/slang/lower.cpp b/source/slang/lower.cpp
index e253abca6..72b577259 100644
--- a/source/slang/lower.cpp
+++ b/source/slang/lower.cpp
@@ -2633,6 +2633,11 @@ struct LoweringVisitor
// Catch-all
+ LoweredDecl visitSyntaxDecl(SyntaxDecl*)
+ {
+ return LoweredDecl();
+ }
+
LoweredDecl visitModifierDecl(ModifierDecl*)
{
// should not occur in user code
diff --git a/source/slang/parser.cpp b/source/slang/parser.cpp
index cc6a0dd6f..dd379df0e 100644
--- a/source/slang/parser.cpp
+++ b/source/slang/parser.cpp
@@ -528,18 +528,15 @@ namespace Slang
return ParseProgram();
}
- RefPtr<TypeDefDecl> ParseTypeDef(Parser* parser)
+ RefPtr<SyntaxNode> ParseTypeDef(Parser* parser)
{
RefPtr<TypeDefDecl> typeDefDecl = new TypeDefDecl();
- typeDefDecl->Position = parser->tokenReader.PeekLoc();
-
- // Consume the `typedef` keyword
- parser->ReadToken("typedef");
// TODO(tfoley): parse an actual declarator
auto type = parser->ParseTypeExp();
auto nameToken = parser->ReadToken(TokenType::Identifier);
+ typeDefDecl->Position = nameToken.Position;
typeDefDecl->Name = nameToken;
typeDefDecl->type = type;
@@ -871,13 +868,11 @@ namespace Slang
return parser->tokenReader.PeekTokenType();
}
- static RefPtr<Decl> parseImportDecl(
+ static RefPtr<SyntaxNode> parseImportDecl(
Parser* parser)
{
parser->haveSeenAnyImportDecls = true;
- parser->ReadToken("__import");
-
auto decl = new ImportDecl();
decl->scope = parser->currentScope;
@@ -1758,7 +1753,8 @@ namespace Slang
}
static RefPtr<Decl> ParseHLSLBufferDecl(
- Parser* parser)
+ Parser* parser,
+ String bufferWrapperTypeName)
{
// An HLSL declaration of a constant buffer like this:
//
@@ -1774,22 +1770,7 @@ namespace Slang
// declaration is made to be "transparent" so that lookup
// will see through it to the members inside.
- // We first look at the declaration keywrod to determine
- // the type of buffer to declare:
- String bufferWrapperTypeName;
- SourceLoc bufferWrapperTypeNamePos = parser->tokenReader.PeekLoc();
- if (AdvanceIf(parser, "cbuffer"))
- {
- bufferWrapperTypeName = "ConstantBuffer";
- }
- else if (AdvanceIf(parser, "tbuffer"))
- {
- bufferWrapperTypeName = "TextureBuffer";
- }
- else
- {
- Unexpected(parser);
- }
+ auto bufferWrapperTypeNamePos = parser->tokenReader.PeekLoc();
// We are going to represent each buffer as a pair of declarations.
// The first is a type declaration that holds all the members, while
@@ -1872,7 +1853,19 @@ namespace Slang
return bufferVarDecl;
}
-
+
+ static RefPtr<SyntaxNode> parseHLSLCBufferDecl(
+ Parser* parser)
+ {
+ return ParseHLSLBufferDecl(parser, "ConstantBuffer");
+ }
+
+ static RefPtr<SyntaxNode> parseHLSLTBufferDecl(
+ Parser* parser)
+ {
+ return ParseHLSLBufferDecl(parser, "TextureBuffer");
+ }
+
static void removeModifier(
Modifiers& modifiers,
RefPtr<Modifier> modifier)
@@ -2098,13 +2091,13 @@ namespace Slang
}
}
- static RefPtr<Decl> ParseGenericDecl(
+ static RefPtr<SyntaxNode> ParseGenericDecl(
Parser* parser)
{
RefPtr<GenericDecl> decl = new GenericDecl();
parser->FillPosition(decl.Ptr());
parser->PushScope(decl.Ptr());
- parser->ReadToken("__generic");
+
parser->ReadToken(TokenType::OpLess);
parser->genericDepth++;
while (!parser->LookAheadToken(TokenType::OpGreater))
@@ -2123,17 +2116,20 @@ namespace Slang
// A generic decl hijacks the name of the declaration
// it wraps, so that lookup can find it.
- decl->Name = decl->inner->Name;
+ if (decl->inner)
+ {
+ decl->Name = decl->inner->Name;
+ decl->Position = decl->inner->Position;
+ }
parser->PopScope();
return decl;
}
- static RefPtr<ExtensionDecl> ParseExtensionDecl(Parser* parser)
+ static RefPtr<SyntaxNode> ParseExtensionDecl(Parser* parser)
{
RefPtr<ExtensionDecl> decl = new ExtensionDecl();
parser->FillPosition(decl.Ptr());
- parser->ReadToken("__extension");
decl->targetType = parser->ParseTypeExp();
parseAggTypeDeclBody(parser, decl.Ptr());
@@ -2159,11 +2155,10 @@ namespace Slang
}
}
- static RefPtr<InterfaceDecl> parseInterfaceDecl(Parser* parser)
+ static RefPtr<SyntaxNode> parseInterfaceDecl(Parser* parser)
{
RefPtr<InterfaceDecl> decl = new InterfaceDecl();
parser->FillPosition(decl.Ptr());
- parser->ReadToken("interface");
decl->Name = parser->ReadToken(TokenType::Identifier);
parseOptionalInheritanceClause(parser, decl.Ptr());
@@ -2173,11 +2168,10 @@ namespace Slang
return decl;
}
- static RefPtr<ConstructorDecl> ParseConstructorDecl(Parser* parser)
+ static RefPtr<SyntaxNode> ParseConstructorDecl(Parser* parser)
{
RefPtr<ConstructorDecl> decl = new ConstructorDecl();
parser->FillPosition(decl.Ptr());
- parser->ReadToken("__init");
parseParameterList(parser, decl);
@@ -2221,11 +2215,10 @@ namespace Slang
return decl;
}
- static RefPtr<SubscriptDecl> ParseSubscriptDecl(Parser* parser)
+ static RefPtr<SyntaxNode> ParseSubscriptDecl(Parser* parser)
{
RefPtr<SubscriptDecl> decl = new SubscriptDecl();
parser->FillPosition(decl.Ptr());
- parser->ReadToken("__subscript");
// TODO: the use of this name here is a bit magical...
decl->Name.Content = "operator[]";
@@ -2257,13 +2250,10 @@ namespace Slang
}
// Parse a declaration of a new modifier keyword
- static RefPtr<ModifierDecl> parseModifierDecl(Parser* parser)
+ static RefPtr<SyntaxNode> parseModifierDecl(Parser* parser)
{
RefPtr<ModifierDecl> decl = new ModifierDecl();
- // read the `__modifier` keyword
- parser->ReadToken(TokenType::Identifier);
-
parser->ReadToken(TokenType::LParent);
decl->classNameToken = parser->ReadToken(TokenType::Identifier);
parser->ReadToken(TokenType::RParent);
@@ -2293,6 +2283,44 @@ namespace Slang
}
}
+ static Token advanceToken(Parser* parser)
+ {
+ return parser->ReadToken();
+ }
+
+ static Token peekToken(Parser* parser)
+ {
+ return parser->tokenReader.PeekToken();
+ }
+
+ static SyntaxDecl* tryLookUpSyntaxDecl(
+ Parser* parser,
+ String const& name)
+ {
+ // Let's look up the name and see what we find.
+
+ auto lookupResult = LookUp(
+ parser->getSession(),
+ nullptr, // no semantics visitor available yet
+ name,
+ parser->currentScope);
+
+ // If we didn't find anything, or the result was overloaded,
+ // then we aren't going to be able to extract a single decl.
+ if(!lookupResult.isValid() || lookupResult.isOverloaded())
+ return nullptr;
+
+ auto decl = lookupResult.item.declRef.getDecl();
+ if( auto syntaxDecl = dynamic_cast<SyntaxDecl*>(decl) )
+ {
+ return syntaxDecl;
+ }
+ else
+ {
+ return nullptr;
+ }
+ }
+
static RefPtr<DeclBase> ParseDeclWithModifiers(
Parser* parser,
ContainerDecl* containerDecl,
@@ -2302,47 +2330,105 @@ namespace Slang
auto loc = parser->tokenReader.PeekLoc();
- // TODO: actual dispatch!
- if (parser->LookAheadToken("struct"))
- decl = ParseDeclaratorDecl(parser, containerDecl);
- else if (parser->LookAheadToken("class"))
- decl = ParseDeclaratorDecl(parser, containerDecl);
- else if (parser->LookAheadToken("typedef"))
- decl = ParseTypeDef(parser);
- else if (parser->LookAheadToken("cbuffer") || parser->LookAheadToken("tbuffer"))
- decl = ParseHLSLBufferDecl(parser);
- else if (parser->LookAheadToken("__generic"))
- decl = ParseGenericDecl(parser);
- else if (parser->LookAheadToken("__extension"))
- decl = ParseExtensionDecl(parser);
- else if (parser->LookAheadToken("__init"))
- decl = ParseConstructorDecl(parser);
- else if (parser->LookAheadToken("__subscript"))
- decl = ParseSubscriptDecl(parser);
- else if (parser->LookAheadToken("interface"))
- decl = parseInterfaceDecl(parser);
- else if(parser->LookAheadToken("__modifier"))
- decl = parseModifierDecl(parser);
- else if(parser->LookAheadToken("__import"))
- decl = parseImportDecl(parser);
- else if(parser->LookAheadToken(TokenType::PoundImport))
- decl = parsePoundImportDecl(parser);
- else if (AdvanceIf(parser, TokenType::Semicolon))
+ switch (peekTokenType(parser))
{
- decl = new EmptyDecl();
- decl->Position = loc;
- }
- // GLSL requires that we be able to parse "block" declarations,
- // which look superficially similar to declarator declarations
- else if( parser->LookAheadToken(TokenType::Identifier)
- && parser->LookAheadToken(TokenType::LBrace, 1) )
- {
- decl = parseGLSLBlockDecl(parser, modifiers);
- }
- else
- {
- // Default case: just parse a declarator-based declaration
+ case TokenType::Identifier:
+ {
+ // A declaration that starts with an identifier might be:
+ //
+ // - A keyword-based declaration (e.g., `cbuffer ...`)
+ // - The begining of a type in a declarator-based declaration (e.g., `int ...`)
+ // - A GLSL block declaration (e.g., `uniform Foo { ... }`)
+
+ // Let's deal with the GLSL block case first. This is something like:
+ //
+ // uniform Foo { ... };
+ //
+ // The `uniform` keyword has already been parsed as a modifier,
+ // so the identifier we are looking at is `Foo`. If the token
+ // after that is `{`, we assume this is a block.
+ //
+ // Of course, we only want to allow this syntax when parsing GLSL...
+ if (parser->translationUnit->sourceLanguage == SourceLanguage::GLSL)
+ {
+ if( parser->LookAheadToken(TokenType::LBrace, 1) )
+ {
+ decl = parseGLSLBlockDecl(parser, modifiers);
+ break;
+ }
+ }
+
+ // We will look up the name that was given, and try to see
+ // if it names a syntactic keyword that will tell us how to parse
+ // things.
+ auto nameToken = peekToken(parser);
+ auto name = nameToken.Content;
+ auto syntaxDecl = tryLookUpSyntaxDecl(parser, name);
+
+ // TODO: confirm that the syntax is for a declaration?
+ if (syntaxDecl && syntaxDecl->syntaxClass.isSubClassOf<Decl>())
+ {
+ // Consume the keyword token, so that the callback doesn't
+ // need to deal with it.
+ advanceToken(parser);
+
+ auto parsedSyntax = syntaxDecl->parserCallback(parser);
+ if (parsedSyntax)
+ {
+ if (!parsedSyntax->Position.isValid())
+ {
+ parsedSyntax->Position = nameToken.Position;
+ }
+
+ auto parsedDecl = parsedSyntax->As<Decl>();
+ if (parsedDecl)
+ {
+ decl = parsedDecl;
+ }
+ else
+ {
+ // TODO: diagnose!
+ }
+ }
+
+ }
+ else
+ {
+ // If the idenfier given doesn't name a declaration keyword,
+ // then we will try to parse things as a declarator decl.
+
+ decl = ParseDeclaratorDecl(parser, containerDecl);
+ break;
+ }
+
+ }
+ break;
+
+ // It is valid in HLSL/GLSL to have an "empty" declaration
+ // that consists of just a semicolon. In particular, this
+ // gets used a lot in GLSL to attach custom semantics to
+ // shader input or output.
+ //
+ case TokenType::Semicolon:
+ {
+ advanceToken(parser);
+
+ decl = new EmptyDecl();
+ decl->Position = loc;
+ }
+ break;
+
+ // The preprocessor will generate a custom token to represent
+ // the site of a `#import` directive, so that we can catch
+ // it downstream in the parser, here.
+ case TokenType::PoundImport:
+ decl = parsePoundImportDecl(parser);
+ break;
+
+ // If nothing else matched, we try to parse an "ordinary" declarator-based declaration
+ default:
decl = ParseDeclaratorDecl(parser, containerDecl);
+ break;
}
if (decl)
@@ -3669,180 +3755,6 @@ namespace Slang
RefPtr<Expr> Parser::ParseLeafExpression()
{
return parsePrefixExpr(this);
-
-#if 0
- RefPtr<Expr> rs;
- if (LookAheadToken(TokenType::OpInc) ||
- LookAheadToken(TokenType::OpDec) ||
- LookAheadToken(TokenType::OpNot) ||
- LookAheadToken(TokenType::OpBitNot) ||
- LookAheadToken(TokenType::OpSub))
- {
- RefPtr<OperatorExpr> unaryExpr = new PrefixExpr();
- FillPosition(unaryExpr.Ptr());
- unaryExpr->FunctionExpr = parseOperator(this);
- unaryExpr->Arguments.Add(ParseLeafExpression());
- rs = unaryExpr;
- return rs;
- }
-
- if (LookAheadToken(TokenType::LParent))
- {
- ReadToken(TokenType::LParent);
- RefPtr<Expr> expr;
- if (peekTypeName(this) && LookAheadToken(TokenType::RParent, 1))
- {
- RefPtr<TypeCastExpr> tcexpr = new TypeCastExpr();
- FillPosition(tcexpr.Ptr());
- tcexpr->TargetType = ParseTypeExp();
- ReadToken(TokenType::RParent);
- tcexpr->Expression = ParseExpression(Precedence::Multiplicative); // Note(tfoley): need to double-check this
- expr = tcexpr;
- }
- else
- {
- expr = ParseExpression();
- ReadToken(TokenType::RParent);
- }
- rs = expr;
- }
- else if( LookAheadToken(TokenType::LBrace) )
- {
- RefPtr<InitializerListExpr> initExpr = new InitializerListExpr();
- FillPosition(initExpr.Ptr());
-
- // Initializer list
- ReadToken(TokenType::LBrace);
-
- List<RefPtr<Expr>> exprs;
-
- for(;;)
- {
- if(AdvanceIfMatch(this, TokenType::RBrace))
- break;
-
- auto expr = ParseArgExpr();
- if( expr )
- {
- initExpr->args.Add(expr);
- }
-
- if(AdvanceIfMatch(this, TokenType::RBrace))
- break;
-
- ReadToken(TokenType::Comma);
- }
- rs = initExpr;
- }
-
- else if (LookAheadToken(TokenType::IntegerLiteral) ||
- LookAheadToken(TokenType::FloatingPointLiteral))
- {
- RefPtr<ConstantExpr> constExpr = new ConstantExpr();
- auto token = tokenReader.AdvanceToken();
- FillPosition(constExpr.Ptr());
- if (token.type == TokenType::IntegerLiteral)
- {
- constExpr->ConstType = ConstantExpr::ConstantType::Int;
- constExpr->IntValue = StringToInt(token.Content);
- }
- else if (token.type == TokenType::FloatingPointLiteral)
- {
- constExpr->ConstType = ConstantExpr::ConstantType::Float;
- constExpr->FloatValue = (FloatingPointLiteralValue) StringToDouble(token.Content);
- }
- rs = constExpr;
- }
- else if (LookAheadToken("true") || LookAheadToken("false"))
- {
- RefPtr<ConstantExpr> constExpr = new ConstantExpr();
- auto token = tokenReader.AdvanceToken();
- FillPosition(constExpr.Ptr());
- constExpr->ConstType = ConstantExpr::ConstantType::Bool;
- constExpr->IntValue = token.Content == "true" ? 1 : 0;
- rs = constExpr;
- }
- else if (LookAheadToken(TokenType::Identifier))
- {
- RefPtr<VarExpr> varExpr = new VarExpr();
- varExpr->scope = currentScope.Ptr();
- FillPosition(varExpr.Ptr());
- auto token = ReadToken(TokenType::Identifier);
- varExpr->name = token.Content;
- rs = varExpr;
- }
-
- while (!tokenReader.IsAtEnd() &&
- (LookAheadToken(TokenType::OpInc) ||
- LookAheadToken(TokenType::OpDec) ||
- LookAheadToken(TokenType::Dot) ||
- LookAheadToken(TokenType::LBracket) ||
- LookAheadToken(TokenType::LParent)))
- {
- if (LookAheadToken(TokenType::OpInc))
- {
- RefPtr<OperatorExpr> unaryExpr = new PostfixExpr();
- FillPosition(unaryExpr.Ptr());
- unaryExpr->FunctionExpr = parseOperator(this);
- unaryExpr->Arguments.Add(rs);
- rs = unaryExpr;
- }
- else if (LookAheadToken(TokenType::OpDec))
- {
- RefPtr<OperatorExpr> unaryExpr = new PostfixExpr();
- FillPosition(unaryExpr.Ptr());
- unaryExpr->FunctionExpr = parseOperator(this);
- unaryExpr->Arguments.Add(rs);
- rs = unaryExpr;
- }
- else if (LookAheadToken(TokenType::LBracket))
- {
- RefPtr<IndexExpr> indexExpr = new IndexExpr();
- indexExpr->BaseExpression = rs;
- FillPosition(indexExpr.Ptr());
- ReadToken(TokenType::LBracket);
- indexExpr->IndexExpression = ParseExpression();
- ReadToken(TokenType::RBracket);
- rs = indexExpr;
- }
- else if (LookAheadToken(TokenType::LParent))
- {
- RefPtr<InvokeExpr> invokeExpr = new InvokeExpr();
- invokeExpr->FunctionExpr = rs;
- FillPosition(invokeExpr.Ptr());
- ReadToken(TokenType::LParent);
- while (!tokenReader.IsAtEnd())
- {
- if (!LookAheadToken(TokenType::RParent))
- invokeExpr->Arguments.Add(ParseArgExpr());
- else
- {
- break;
- }
- if (!LookAheadToken(TokenType::Comma))
- break;
- ReadToken(TokenType::Comma);
- }
- ReadToken(TokenType::RParent);
- rs = invokeExpr;
- }
- else if (LookAheadToken(TokenType::Dot))
- {
- RefPtr<MemberExpr> memberExpr = new MemberExpr();
- memberExpr->scope = currentScope.Ptr();
- FillPosition(memberExpr.Ptr());
- memberExpr->BaseExpression = rs;
- ReadToken(TokenType::Dot);
- memberExpr->name = ReadToken(TokenType::Identifier).Content;
- rs = memberExpr;
- }
- }
- if (!rs)
- {
- sink->diagnose(tokenReader.PeekLoc(), Diagnostics::syntaxError);
- }
- return rs;
-#endif
}
// Parse a source file into an existing translation unit
@@ -3858,4 +3770,76 @@ namespace Slang
return parser.parseSourceFile(translationUnit->SyntaxNode.Ptr());
}
+
+ static void addBuiltinSyntaxImpl(
+ Session* /*session*/,
+ Scope* scope,
+ char const* nameText,
+ SyntaxParseCallback callback,
+ SyntaxClass<SyntaxNode> syntaxClass)
+ {
+ String name(nameText);
+
+ RefPtr<SyntaxDecl> syntaxDecl = new SyntaxDecl();
+ syntaxDecl->Name.Content = name;
+ syntaxDecl->syntaxClass = syntaxClass;
+ syntaxDecl->parserCallback = callback;
+
+ AddMember(scope, syntaxDecl);
+ }
+
+ template<typename T>
+ static void addBuiltinSyntax(
+ Session* session,
+ Scope* scope,
+ char const* name,
+ SyntaxParseCallback callback)
+ {
+ addBuiltinSyntaxImpl(session, scope, name, callback, getClass<T>());
+ }
+
+ RefPtr<ModuleDecl> populateBaseLanguageModule(
+ Session* session,
+ RefPtr<Scope> scope)
+ {
+ RefPtr<ModuleDecl> moduleDecl = new ModuleDecl();
+ scope->containerDecl = moduleDecl;
+
+ addBuiltinSyntax<Decl>(session, scope, "typedef", &ParseTypeDef);
+ addBuiltinSyntax<Decl>(session, scope, "cbuffer", &parseHLSLCBufferDecl);
+ addBuiltinSyntax<Decl>(session, scope, "tbuffer", &parseHLSLTBufferDecl);
+ addBuiltinSyntax<Decl>(session, scope, "__generic", &ParseGenericDecl);
+ addBuiltinSyntax<Decl>(session, scope, "__extension", &ParseExtensionDecl);
+ addBuiltinSyntax<Decl>(session, scope, "__init", &ParseConstructorDecl);
+ addBuiltinSyntax<Decl>(session, scope, "__subscript", &ParseSubscriptDecl);
+ addBuiltinSyntax<Decl>(session, scope, "interface", &parseInterfaceDecl);
+ addBuiltinSyntax<Decl>(session, scope, "__modifier", &parseModifierDecl);
+ addBuiltinSyntax<Decl>(session, scope, "__import", &parseImportDecl);
+
+#if 0
+ // TODO: actual dispatch!
+ if (parser->LookAheadToken("struct"))
+ decl = ParseDeclaratorDecl(parser, containerDecl);
+ else if (parser->LookAheadToken("class"))
+ decl = ParseDeclaratorDecl(parser, containerDecl);
+ else if (parser->LookAheadToken("__generic"))
+ decl = ParseGenericDecl(parser);
+ else if (parser->LookAheadToken("__extension"))
+ decl = ParseExtensionDecl(parser);
+ else if (parser->LookAheadToken("__init"))
+ decl = ParseConstructorDecl(parser);
+ else if (parser->LookAheadToken("__subscript"))
+ decl = ParseSubscriptDecl(parser);
+ else if (parser->LookAheadToken("interface"))
+ decl = parseInterfaceDecl(parser);
+ else if(parser->LookAheadToken("__modifier"))
+ decl = parseModifierDecl(parser);
+ else if(parser->LookAheadToken("__import"))
+ decl = parseImportDecl(parser);
+#endif
+
+
+ return moduleDecl;
+ }
+
}
diff --git a/source/slang/parser.h b/source/slang/parser.h
index 41a82602a..60fe4b3ae 100644
--- a/source/slang/parser.h
+++ b/source/slang/parser.h
@@ -13,7 +13,10 @@ namespace Slang
TokenSpan const& tokens,
DiagnosticSink* sink,
RefPtr<Scope> const& outerScope);
-;
+
+ RefPtr<ModuleDecl> populateBaseLanguageModule(
+ Session* session,
+ RefPtr<Scope> scope);
}
#endif \ No newline at end of file
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index e66884923..11d9e6e86 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -31,7 +31,15 @@ Session::Session()
// TODO: load these on-demand to avoid parsing
// stdlib code for languages the user won't use.
+ baseLanguageScope = new Scope();
+
+ auto baseModuleDecl = populateBaseLanguageModule(
+ this,
+ baseLanguageScope);
+ loadedModuleCode.Add(baseModuleDecl);
+
coreLanguageScope = new Scope();
+ coreLanguageScope->nextSibling = baseLanguageScope;
hlslLanguageScope = new Scope();
hlslLanguageScope->nextSibling = coreLanguageScope;
diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp
index 33fa5be20..0135e2316 100644
--- a/source/slang/syntax.cpp
+++ b/source/slang/syntax.cpp
@@ -62,11 +62,14 @@ namespace Slang
#undef SYNTAX_CLASS
#undef ABSTRACT_SYNTAX_CLASS
-#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); } \
- void* SyntaxClassBase::Impl<NAME>::createFunc() { return new NAME(); }
+#define ABSTRACT_SYNTAX_CLASS(NAME, BASE) \
+ SyntaxClassBase::ClassInfo const SyntaxClassBase::Impl<NAME>::kClassInfo = { #NAME, &SyntaxClassBase::Impl<BASE>::kClassInfo, nullptr };
+
+#define SYNTAX_CLASS(NAME, BASE) \
+ void NAME::accept(NAME::Visitor* visitor, void* extra) \
+ { visitor->dispatch_##NAME(this, extra); } \
+ void* SyntaxClassBase::Impl<NAME>::createFunc() { return new NAME(); } \
+ SyntaxClassBase::ClassInfo const SyntaxClassBase::Impl<NAME>::kClassInfo = { #NAME, &SyntaxClassBase::Impl<BASE>::kClassInfo, &SyntaxClassBase::Impl<NAME>::createFunc };
#include "expr-defs.h"
#include "decl-defs.h"
#include "modifier-defs.h"
@@ -74,8 +77,35 @@ namespace Slang
#include "type-defs.h"
#include "val-defs.h"
+SyntaxClassBase::ClassInfo const SyntaxClassBase::Impl<RefObject>::kClassInfo = { "RefObject", nullptr, nullptr };
+
+ABSTRACT_SYNTAX_CLASS(SyntaxNodeBase, RefObject);
+ABSTRACT_SYNTAX_CLASS(SyntaxNode, SyntaxNodeBase);
+ABSTRACT_SYNTAX_CLASS(ModifiableSyntaxNode, SyntaxNode);
+ABSTRACT_SYNTAX_CLASS(DeclBase, ModifiableSyntaxNode);
+ABSTRACT_SYNTAX_CLASS(Decl, DeclBase);
+ABSTRACT_SYNTAX_CLASS(Stmt, ModifiableSyntaxNode);
+ABSTRACT_SYNTAX_CLASS(Val, RefObject);
+ABSTRACT_SYNTAX_CLASS(Type, Val);
+ABSTRACT_SYNTAX_CLASS(Modifier, SyntaxNodeBase);
+ABSTRACT_SYNTAX_CLASS(Expr, SyntaxNode);
+
#include "object-meta-end.h"
+bool SyntaxClassBase::isSubClassOfImpl(SyntaxClassBase const& super) const
+{
+ SyntaxClassBase::ClassInfo const* info = classInfo;
+ while (info)
+ {
+ if (info == super.classInfo)
+ return true;
+
+ info = info->baseClass;
+ }
+
+ return false;
+}
+
void Type::accept(IValVisitor* visitor, void* extra)
{
accept((ITypeVisitor*)visitor, extra);
diff --git a/source/slang/syntax.h b/source/slang/syntax.h
index 059327e6f..250c4b3cc 100644
--- a/source/slang/syntax.h
+++ b/source/slang/syntax.h
@@ -24,6 +24,10 @@ namespace Slang
struct ITypeVisitor;
struct IValVisitor;
+ class Parser;
+ class SyntaxNode;
+ typedef RefPtr<SyntaxNode> (*SyntaxParseCallback)(Parser* parser);
+
// Forward-declare all syntax classes
#define SYNTAX_CLASS(NAME, BASE, ...) class NAME;
#include "object-meta-begin.h"
@@ -238,24 +242,46 @@ namespace Slang
{
typedef void* (*CreateFunc)();
+ // Run-time type representation for syntax nodes
+ struct ClassInfo
+ {
+ // Textual class name, for debugging
+ char const* name;
+
+ // Base class for runtime queries
+ ClassInfo const* baseClass;
+
+ // Callback to use when creating instances
+ CreateFunc createFunc;
+ };
+
SyntaxClassBase()
{}
- SyntaxClassBase(CreateFunc createFunc)
- : createFunc(createFunc)
+ SyntaxClassBase(ClassInfo const* classInfo)
+ : classInfo(classInfo)
{}
void* createInstanceImpl() const
{
- return createFunc ? createFunc() : nullptr;
+ auto ci = classInfo;
+ if (!ci) return nullptr;
+
+ auto cf = ci->createFunc;
+ if (!cf) return nullptr;
+
+ return cf();
}
- CreateFunc createFunc = nullptr;
+ bool isSubClassOfImpl(SyntaxClassBase const& super) const;
+
+ ClassInfo const* classInfo = nullptr;
template<typename T>
struct Impl
{
static void* createFunc();
+ static const ClassInfo kClassInfo;
};
};
@@ -268,7 +294,7 @@ namespace Slang
template <typename U>
SyntaxClass(SyntaxClass<U> const& other,
typename EnableIf<IsConvertible<T*, U*>::Value, void>::type* = 0)
- : SyntaxClassBase(other.createFunc)
+ : SyntaxClassBase(other.classInfo)
{
}
@@ -280,9 +306,21 @@ namespace Slang
static SyntaxClass<T> getClass()
{
SyntaxClass<T> result;
- result.createFunc = &SyntaxClass::Impl<T>::createFunc;
+ result.classInfo = &SyntaxClass::Impl<T>::kClassInfo;
return result;
}
+
+ template<typename U>
+ bool isSubClassOf(SyntaxClass<U> super)
+ {
+ return isSubClassOfImpl(super);
+ }
+
+ template<typename U>
+ bool isSubClassOf()
+ {
+ return isSubClassOf(SyntaxClass<U>::getClass());
+ }
};
template<typename T>