diff options
| author | Tim Foley <tfoleyNV@users.noreply.github.com> | 2017-08-11 14:04:24 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-08-11 14:04:24 -0700 |
| commit | 495f88167527945e680e091d49b5705f5f1af1f9 (patch) | |
| tree | 8be4a0505bd121edbbcf5dd5b3cd9d43c51ec377 /source | |
| parent | db4079f7e3635a6a61b8725643b1d7ecf68b97d8 (diff) | |
| parent | b2febc7966c2533f756a6829656423f05b2f21e5 (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.cpp | 5 | ||||
| -rw-r--r-- | source/slang/compiler.h | 1 | ||||
| -rw-r--r-- | source/slang/decl-defs.h | 11 | ||||
| -rw-r--r-- | source/slang/emit.cpp | 1 | ||||
| -rw-r--r-- | source/slang/lexer.cpp | 2 | ||||
| -rw-r--r-- | source/slang/lower.cpp | 5 | ||||
| -rw-r--r-- | source/slang/parser.cpp | 492 | ||||
| -rw-r--r-- | source/slang/parser.h | 5 | ||||
| -rw-r--r-- | source/slang/slang.cpp | 8 | ||||
| -rw-r--r-- | source/slang/syntax.cpp | 40 | ||||
| -rw-r--r-- | source/slang/syntax.h | 50 |
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> |
