From 798f3bc2236ce81499b05662dc11e7c071e7cde8 Mon Sep 17 00:00:00 2001 From: jsmall-nvidia Date: Fri, 8 May 2020 14:31:40 -0400 Subject: AST nodes using C++ Extractor (#1341) * Extractor builds without any reference to syntax (as it will be helping to produce this!). * Change macros to include the super class. * WIP replacing defs files. * Added indexOf(const UnownedSubString& in) to UnownedSubString. Refactored extractor * Output a macro for each type with the extracted info - can be used during injection in class * Simplify the header file - as can get super type and last from macro now * Store the 'origin' of a definition * Some small tidy ups to the extractor. * Improve comments on the extractor options. * Made CPPExtractor own SourceOrigins * Small fixes around SourceOrigin. * Small tidy up around macroOrign * WIP Visitor seems now to work correctly. Split out types used by ast into slang-ast-support-types.h * Fix remaining problems with C++ extractor being used with AST nodes. Add CountOf to extractor type ids. Added ReflectClassInfo::getInfo to turn an ASTNodeType into a ReflectClassInfo * Fix compiling on linux. Fix typo in memset. * Small tidy up around comments/layout. Moved NodeBase casting to NodeBase. * Make premake generate project that builds with cpp-extractor for AST. * Get the source directory from the filter in premake. * Fix typo in source path * Explicitly set the source path for premake generation for AST. * Special case handling of override to apease Clang. * Use a more general way to find the slang-ast-reflect.h file to run the extractor. * Appveyor is not triggering slang-cpp-extractor - try putting dependson together. * Put building slang-cpp-extractor first. * Disable some project options to stop MSBuild producing internal compiler errors. * Try reordering the projects in premake5.lua * Hack to try and make slang-cpp-extractor built on appveyor. * Disable flags - not required for MSBuild on appveyor. * Disable flags not required for build on AppVeyor. * Updated Visual Studio projects with slang-cpp-extractor. * Added Visual Studio slang-cpp-extractor project. --- source/slang/slang-ast-all.h | 12 + source/slang/slang-ast-base.h | 370 +++++++++ source/slang/slang-ast-decl.h | 464 +++++++++++ source/slang/slang-ast-expr.h | 311 +++++++ source/slang/slang-ast-modifier.h | 883 ++++++++++++++++++++ source/slang/slang-ast-reflect.cpp | 70 ++ source/slang/slang-ast-reflect.h | 37 + source/slang/slang-ast-stmt.h | 213 +++++ source/slang/slang-ast-support-types.h | 1330 ++++++++++++++++++++++++++++++ source/slang/slang-ast-type.h | 690 ++++++++++++++++ source/slang/slang-ast-val.h | 206 +++++ source/slang/slang-decl-defs.h | 345 -------- source/slang/slang-expr-defs.h | 216 ----- source/slang/slang-modifier-defs.h | 495 ------------ source/slang/slang-object-meta-begin.h | 43 - source/slang/slang-object-meta-end.h | 17 - source/slang/slang-parser.cpp | 2 +- source/slang/slang-stmt-defs.h | 124 --- source/slang/slang-syntax-base-defs.h | 306 ------- source/slang/slang-syntax-defs.h | 10 - source/slang/slang-syntax.cpp | 196 +---- source/slang/slang-syntax.h | 1389 +------------------------------- source/slang/slang-type-defs.h | 522 ------------ source/slang/slang-val-defs.h | 173 ---- source/slang/slang-visitor.h | 371 ++------- source/slang/slang.cpp | 14 +- source/slang/slang.vcxproj | 35 +- source/slang/slang.vcxproj.filters | 72 +- 28 files changed, 4756 insertions(+), 4160 deletions(-) create mode 100644 source/slang/slang-ast-all.h create mode 100644 source/slang/slang-ast-base.h create mode 100644 source/slang/slang-ast-decl.h create mode 100644 source/slang/slang-ast-expr.h create mode 100644 source/slang/slang-ast-modifier.h create mode 100644 source/slang/slang-ast-reflect.cpp create mode 100644 source/slang/slang-ast-reflect.h create mode 100644 source/slang/slang-ast-stmt.h create mode 100644 source/slang/slang-ast-support-types.h create mode 100644 source/slang/slang-ast-type.h create mode 100644 source/slang/slang-ast-val.h delete mode 100644 source/slang/slang-decl-defs.h delete mode 100644 source/slang/slang-expr-defs.h delete mode 100644 source/slang/slang-modifier-defs.h delete mode 100644 source/slang/slang-object-meta-begin.h delete mode 100644 source/slang/slang-object-meta-end.h delete mode 100644 source/slang/slang-stmt-defs.h delete mode 100644 source/slang/slang-syntax-base-defs.h delete mode 100644 source/slang/slang-syntax-defs.h delete mode 100644 source/slang/slang-type-defs.h delete mode 100644 source/slang/slang-val-defs.h (limited to 'source') diff --git a/source/slang/slang-ast-all.h b/source/slang/slang-ast-all.h new file mode 100644 index 000000000..096c95f53 --- /dev/null +++ b/source/slang/slang-ast-all.h @@ -0,0 +1,12 @@ +// slang-ast-all.h + +#pragma once + +#include "slang-ast-base.h" + +#include "slang-ast-expr.h" +#include "slang-ast-decl.h" +#include "slang-ast-modifier.h" +#include "slang-ast-stmt.h" +#include "slang-ast-type.h" +#include "slang-ast-val.h" diff --git a/source/slang/slang-ast-base.h b/source/slang/slang-ast-base.h new file mode 100644 index 000000000..ee044eae3 --- /dev/null +++ b/source/slang/slang-ast-base.h @@ -0,0 +1,370 @@ +// slang-ast-base.h + +#pragma once + +#include "slang-ast-support-types.h" + +#include "slang-ast-generated.h" +#include "slang-ast-reflect.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. + +namespace Slang +{ + +#define SLANG_ABSTRACT_CLASS(x) SLANG_ABSTRACT_CLASS_REFLECT(x) +// We don't use SLANG_CLASS_REFLECT_WITH_ACCEPT(x), as we don't want accept method on these classes +#define SLANG_CLASS(x) SLANG_CLASS_REFLECT_DEFAULT(x) + +// Signals to C++ extractor that RefObject is a base class, that isn't reflected to C++ extractor +SLANG_REFLECT_BASE_CLASS(RefObject) + +struct ReflectClassInfo; + +class NodeBase : public RefObject +{ + SLANG_ABSTRACT_CLASS(NodeBase) + + SyntaxClass getClass() { return SyntaxClass(&getClassInfo()); } +}; + +// Casting of NodeBase + +template +SLANG_FORCE_INLINE T* dynamicCast(NodeBase* node) +{ + return (node && node->getClassInfo().isSubClassOf(T::kReflectClassInfo)) ? static_cast(node) : nullptr; +} + +template +SLANG_FORCE_INLINE const T* dynamicCast(const NodeBase* node) +{ + return (node && node->getClassInfo().isSubClassOf(T::kReflectClassInfo)) ? static_cast(node) : nullptr; +} + +template +SLANG_FORCE_INLINE T* as(NodeBase* node) +{ + return (node && node->getClassInfo().isSubClassOf(T::kReflectClassInfo)) ? static_cast(node) : nullptr; +} + +template +SLANG_FORCE_INLINE const T* as(const NodeBase* node) +{ + return (node && node->getClassInfo().isSubClassOf(T::kReflectClassInfo)) ? static_cast(node) : nullptr; +} + + +// Base class for all nodes representing actual syntax +// (thus having a location in the source code) +class SyntaxNodeBase : public NodeBase +{ + SLANG_ABSTRACT_CLASS(SyntaxNodeBase) + + // The primary source location associated with this AST node + SourceLoc loc; +}; + +// 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. + +class Val : public NodeBase +{ + SLANG_ABSTRACT_CLASS(Val) + + typedef IValVisitor Visitor; + + virtual void accept(IValVisitor* visitor, void* extra) = 0; + + // construct a new value by applying a set of parameter + // substitutions to this one + RefPtr Substitute(SubstitutionSet subst); + + // Lower-level interface for substitution. 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 SubstituteImpl(SubstitutionSet 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(&v)); + } +}; + +class Type; + +template +SLANG_FORCE_INLINE T* as(Type* obj); +template +SLANG_FORCE_INLINE const T* as(const Type* obj); + +// 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 representation caches a pointer to +// a canonical type on every type, so we can easily +// operate on the raw representation when needed. +class Type: public Val +{ + SLANG_ABSTRACT_CLASS(Type) + + typedef ITypeVisitor Visitor; + + virtual void accept(IValVisitor* visitor, void* extra) override; + virtual void accept(ITypeVisitor* visitor, void* extra) = 0; + +public: + Session* getSession() { return this->session; } + void setSession(Session* s) { this->session = s; } + + bool Equals(Type* type); + + Type* GetCanonicalType(); + + virtual RefPtr SubstituteImpl(SubstitutionSet subst, int* ioDiff) override; + + virtual bool EqualsVal(Val* val) override; + + ~Type(); + +protected: + virtual bool EqualsImpl(Type* type) = 0; + + virtual RefPtr CreateCanonicalType() = 0; + Type* canonicalType = nullptr; + + Session* session = nullptr; +}; + +template +SLANG_FORCE_INLINE T* as(Type* obj) { return obj ? dynamicCast(obj->GetCanonicalType()) : nullptr; } +template +SLANG_FORCE_INLINE const T* as(const Type* obj) { return obj ? dynamicCast(const_cast(obj)->GetCanonicalType()) : nullptr; } + +// A substitution represents a binding of certain +// type-level variables to concrete argument values +class Substitutions: public RefObject +{ + SLANG_ABSTRACT_CLASS(Substitutions) + + // The next outer that this one refines. + RefPtr outer; + + // Apply a set of substitutions to the bindings in this substitution + virtual RefPtr applySubstitutionsShallow(SubstitutionSet substSet, RefPtr substOuter, int* ioDiff) = 0; + + // Check if these are equivalent substitutions to another set + virtual bool Equals(Substitutions* subst) = 0; + virtual int GetHashCode() const = 0; +}; + +class GenericSubstitution : public Substitutions +{ + SLANG_CLASS(GenericSubstitution) + + // The generic declaration that defines the + // parameters we are binding to arguments + GenericDecl* genericDecl; + + // The actual values of the arguments + List > args; + + // Apply a set of substitutions to the bindings in this substitution + virtual RefPtr applySubstitutionsShallow(SubstitutionSet substSet, RefPtr substOuter, int* ioDiff) override; + + // Check if these are equivalent substitutions to another set + virtual bool Equals(Substitutions* subst) override; + + virtual int GetHashCode() const override + { + int rs = 0; + for (auto && v : args) + { + rs ^= v->GetHashCode(); + rs *= 16777619; + } + return rs; + } +}; + +class ThisTypeSubstitution : public Substitutions +{ + SLANG_CLASS(ThisTypeSubstitution) + + // The declaration of the interface that we are specializing + InterfaceDecl* interfaceDecl = nullptr; + + // A witness that shows that the concrete type used to + // specialize the interface conforms to the interface. + RefPtr witness; + + // The actual type that provides the lookup scope for an associated type + // Apply a set of substitutions to the bindings in this substitution + virtual RefPtr applySubstitutionsShallow(SubstitutionSet substSet, RefPtr substOuter, int* ioDiff) override; + + // Check if these are equivalent substitutions to another set + virtual bool Equals(Substitutions* subst) override; + + virtual int GetHashCode() const override; +}; + +class GlobalGenericParamSubstitution : public Substitutions +{ + SLANG_CLASS(GlobalGenericParamSubstitution) + // the type_param decl to be substituted + GlobalGenericParamDecl* paramDecl; + + // the actual type to substitute in + RefPtr actualType; + + struct ConstraintArg + { + RefPtr decl; + RefPtr val; + }; + + // the values that satisfy any constraints on the type parameter + List constraintArgs; + + // Apply a set of substitutions to the bindings in this substitution + virtual RefPtr applySubstitutionsShallow(SubstitutionSet substSet, RefPtr substOuter, int* ioDiff) override; + + // Check if these are equivalent substitutions to another set + virtual bool Equals(Substitutions* subst) override; + + virtual int GetHashCode() const override + { + int rs = actualType->GetHashCode(); + for (auto && a : constraintArgs) + { + rs = combineHash(rs, a.val->GetHashCode()); + } + return rs; + } +}; + +class SyntaxNode : public SyntaxNodeBase +{ + SLANG_ABSTRACT_CLASS(SyntaxNode); +}; + +// +// 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. +// +class Modifier : public SyntaxNode +{ + SLANG_ABSTRACT_CLASS(Modifier) + typedef IModifierVisitor Visitor; + + virtual void accept(IModifierVisitor* visitor, void* extra) = 0; + + // Next modifier in linked list of modifiers on same piece of syntax + RefPtr next; + + // The keyword that was used to introduce t that was used to name this modifier. + Name* name; + + Name* getName() { return name; } + NameLoc getNameAndLoc() { return NameLoc(name, loc); } +}; + +// A syntax node which can have modifiers applied +class ModifiableSyntaxNode : public SyntaxNode +{ + SLANG_ABSTRACT_CLASS(ModifiableSyntaxNode) + + Modifiers modifiers; + + template + FilteredModifierList GetModifiersOfType() { return FilteredModifierList(modifiers.first.Ptr()); } + + // Find the first modifier of a given type, or return `nullptr` if none is found. + template + T* FindModifier() + { + return *GetModifiersOfType().begin(); + } + + template + bool HasModifier() { return FindModifier() != nullptr; } +}; + + +// An intermediate type to represent either a single declaration, or a group of declarations +class DeclBase : public ModifiableSyntaxNode +{ + SLANG_ABSTRACT_CLASS(DeclBase) + + typedef IDeclVisitor Visitor; + + virtual void accept(IDeclVisitor* visitor, void* extra) = 0; +}; + +class Decl : public DeclBase +{ +public: + SLANG_ABSTRACT_CLASS(Decl) + + ContainerDecl* ParentDecl = nullptr; + + NameLoc nameAndLoc; + + Name* getName() { return nameAndLoc.name; } + SourceLoc getNameLoc() { return nameAndLoc.loc ; } + NameLoc getNameAndLoc() { return nameAndLoc ; } + + + DeclCheckStateExt 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) + { + SLANG_RELEASE_ASSERT(state >= checkState.getState()); + checkState.setState(state); + } +}; + +class Expr : public SyntaxNode +{ + SLANG_ABSTRACT_CLASS(Expr) + + typedef IExprVisitor Visitor; + + QualType type; + + virtual void accept(IExprVisitor* visitor, void* extra) = 0; +}; + +class Stmt : public ModifiableSyntaxNode +{ + SLANG_ABSTRACT_CLASS(Stmt) + + typedef IStmtVisitor Visitor; + + virtual void accept(IStmtVisitor* visitor, void* extra) = 0; +}; + +#undef SLANG_ABSTRACT_CLASS +#undef SLANG_CLASS + + +} // namespace Slang diff --git a/source/slang/slang-ast-decl.h b/source/slang/slang-ast-decl.h new file mode 100644 index 000000000..f151b6ca0 --- /dev/null +++ b/source/slang/slang-ast-decl.h @@ -0,0 +1,464 @@ +// slang-decl-defs.h + +#pragma once + +#include "slang-ast-base.h" + +namespace Slang { + +#define SLANG_ABSTRACT_CLASS(x) SLANG_ABSTRACT_CLASS_REFLECT(x) +#define SLANG_CLASS(x) SLANG_CLASS_REFLECT_WITH_ACCEPT(x) + +// Syntax class definitions for declarations. + +// A group of declarations that should be treated as a unit +class DeclGroup: public DeclBase +{ + SLANG_CLASS(DeclGroup) + + List> decls; +}; + + +// A "container" decl is a parent to other declarations +class ContainerDecl: public Decl +{ + SLANG_ABSTRACT_CLASS(ContainerDecl) + + List> Members; + + template + FilteredMemberList getMembersOfType() + { + return FilteredMemberList(Members); + } + + bool isMemberDictionaryValid() const { return dictionaryLastCount == Members.getCount(); } + + void invalidateMemberDictionary() { dictionaryLastCount = -1; } + + // Denotes how much of Members has been placed into the dictionary/transparentMembers. + // If this value equals the Members.getCount(), the dictionary is completely full and valid. + // If it's >= 0, then the Members after dictionaryLastCount are all that need to be added. + // If it < 0 it means that the dictionary/transparentMembers is invalid and needs to be recreated. + Index dictionaryLastCount = 0; + + // Dictionary for looking up members by name. + // This is built on demand before performing lookup. + Dictionary memberDictionary; + + // A list of transparent members, to be used in lookup + // Note: this is only valid if `memberDictionaryIsValid` is true + List transparentMembers; +}; + +// Base class for all variable declarations +class VarDeclBase : public Decl +{ + SLANG_ABSTRACT_CLASS(VarDeclBase) + + // type of the variable + TypeExp type; + + Type* getType() { return (Type*)type.type.Ptr(); } + + // Initializer expression (optional) + RefPtr initExpr; +}; + +// Ordinary potentially-mutable variables (locals, globals, and member variables) +class VarDecl : public VarDeclBase +{ + SLANG_CLASS(VarDecl) +}; + +// A variable declaration that is always immutable (whether local, global, or member variable) +class LetDecl : public VarDecl +{ + SLANG_CLASS(LetDecl) +}; + +// 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 +{ + SLANG_ABSTRACT_CLASS(AggTypeDeclBase); +}; + +// An extension to apply to an existing type +class ExtensionDecl : public AggTypeDeclBase +{ + SLANG_CLASS(ExtensionDecl) + + TypeExp targetType; + + // next extension attached to the same nominal type + ExtensionDecl* nextCandidateExtension = nullptr; +}; + +// Declaration of a type that represents some sort of aggregate +class AggTypeDecl : public AggTypeDeclBase +{ + SLANG_ABSTRACT_CLASS(AggTypeDecl) + + // extensions that might apply to this declaration + ExtensionDecl* candidateExtensions = nullptr; + + FilteredMemberList GetFields() + { + return getMembersOfType(); + } +}; + +class StructDecl: public AggTypeDecl +{ + SLANG_CLASS(StructDecl); +}; + +class ClassDecl : public AggTypeDecl +{ + SLANG_CLASS(ClassDecl) +}; + + +// TODO: Is it appropriate to treat an `enum` as an aggregate type? +// Most code that looks for, e.g., conformances assumes user-defined +// types are all `AggTypeDecl`, so this is the right choice for now +// if we want `enum` types to be able to implement interfaces, etc. +// +class EnumDecl : public AggTypeDecl +{ + SLANG_CLASS(EnumDecl) + + RefPtr tagType; +}; + +// A single case in an enum. +// +// E.g., in a declaration like: +// +// enum Color { Red = 0, Green, Blue }; +// +// The `Red = 0` is the declaration of the `Red` +// case, with `0` as an explicit expression for its +// _tag value_. +// +class EnumCaseDecl : public Decl +{ + SLANG_CLASS(EnumCaseDecl) + + // type of the parent `enum` + TypeExp type; + + Type* getType() { return (Type*)type.type.Ptr(); } + + // Tag value + RefPtr tagExpr; +}; + +// An interface which other types can conform to +class InterfaceDecl : public AggTypeDecl +{ + SLANG_CLASS(InterfaceDecl) +}; + + +class TypeConstraintDecl : public Decl +{ + SLANG_ABSTRACT_CLASS(TypeConstraintDecl) + + virtual TypeExp& getSup() = 0; +}; + +// A kind of pseudo-member that represents an explicit +// or implicit inheritance relationship. +// +class InheritanceDecl : public TypeConstraintDecl +{ + SLANG_CLASS(InheritanceDecl) + +// The type expression as written + TypeExp base; + + // After checking, this dictionary will map members + // required by the base type to their concrete + // implementations in the type that contains + // this inheritance declaration. + RefPtr witnessTable; + virtual TypeExp& getSup() override + { + return base; + } +}; + +// 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 +class SimpleTypeDecl : public Decl +{ + SLANG_ABSTRACT_CLASS(SimpleTypeDecl) +}; + +// A `typedef` declaration +class TypeDefDecl : public SimpleTypeDecl +{ + SLANG_CLASS(TypeDefDecl) + + TypeExp type; +}; + +class TypeAliasDecl : public TypeDefDecl +{ + SLANG_CLASS(TypeAliasDecl) +}; + +// An 'assoctype' declaration, it is a container of inheritance clauses +class AssocTypeDecl : public AggTypeDecl +{ + SLANG_CLASS(AssocTypeDecl) +}; + +// A 'type_param' declaration, which defines a generic +// entry-point parameter. Is a container of GenericTypeConstraintDecl +class GlobalGenericParamDecl : public AggTypeDecl +{ + SLANG_CLASS(GlobalGenericParamDecl) +}; + +// A `__generic_value_param` declaration, which defines an existential +// value parameter (not a type parameter. +class GlobalGenericValueParamDecl : public VarDeclBase +{ + SLANG_CLASS(GlobalGenericValueParamDecl) +}; + +// A scope for local declarations (e.g., as part of a statement) +class ScopeDecl : public ContainerDecl +{ + SLANG_CLASS(ScopeDecl) +}; + +// A function/initializer/subscript parameter (potentially mutable) +class ParamDecl : public VarDeclBase +{ + SLANG_CLASS(ParamDecl) +}; + +// A parameter of a function declared in "modern" types (immutable unless explicitly `out` or `inout`) +class ModernParamDecl : public ParamDecl +{ + SLANG_CLASS(ModernParamDecl) +}; + +// Base class for things that have parameter lists and can thus be applied to arguments ("called") +class CallableDecl : public ContainerDecl +{ + SLANG_ABSTRACT_CLASS(CallableDecl) + + FilteredMemberList GetParameters() + { + return getMembersOfType(); + } + + TypeExp ReturnType; + + // Fields related to redeclaration, so that we + // can support multiple specialized variations + // of the "same" logical function. + // + // This should also help us to support redeclaration + // of functions when handling HLSL/GLSL. + + // The "primary" declaration of the function, which will + // be used whenever we need to unique things. + CallableDecl* primaryDecl = nullptr; + + // The next declaration of the "same" function (that is, + // with the same `primaryDecl`). + CallableDecl* nextDecl = nullptr; +}; + +// Base class for callable things that may also have a body that is evaluated to produce their result +class FunctionDeclBase : public CallableDecl +{ + SLANG_ABSTRACT_CLASS(FunctionDeclBase) + + RefPtr Body; +}; + +// A constructor/initializer to create instances of a type +class ConstructorDecl : public FunctionDeclBase +{ + SLANG_CLASS(ConstructorDecl) +}; + +// A subscript operation used to index instances of a type +class SubscriptDecl : public CallableDecl +{ + SLANG_CLASS(SubscriptDecl) +}; + +// An "accessor" for a subscript or property +class AccessorDecl : public FunctionDeclBase +{ + SLANG_CLASS(AccessorDecl) +}; + +class GetterDecl : public AccessorDecl +{ + SLANG_CLASS(GetterDecl) +}; +class SetterDecl : public AccessorDecl +{ + SLANG_CLASS(SetterDecl) +}; +class RefAccessorDecl : public AccessorDecl +{ + SLANG_CLASS(RefAccessorDecl) +}; + +class FuncDecl : public FunctionDeclBase +{ + SLANG_CLASS(FuncDecl) +}; + +class NamespaceDeclBase : public ContainerDecl +{ + SLANG_CLASS(NamespaceDeclBase) +}; + + // A `namespace` declaration inside some module, that provides + // a named scope for declarations inside it. + // + // Note: Multiple `namespace` declarations with the same name + // in a given module/file will be collapsed into a single + // `NamespaceDecl` during parsing, so this declaration does + // not directly represent what is present in the input syntax. + // +class NamespaceDecl : public NamespaceDeclBase +{ + SLANG_CLASS(NamespaceDecl) +}; + + // A "module" of code (essentially, a single translation unit) + // that provides a scope for some number of declarations. +class ModuleDecl : public NamespaceDeclBase +{ + SLANG_CLASS(ModuleDecl) + // The API-level module that this declaration belong to. + // + // This field allows lookup of the `Module` based on a + // declaration nested under a `ModuleDecl` by following + // its chain of parents. + // + Module* module = nullptr; +}; + +class ImportDecl : public Decl +{ + SLANG_CLASS(ImportDecl) + + // The name of the module we are trying to import + NameLoc moduleNameAndLoc; + + // The scope that we want to import into + RefPtr scope; + + // The module that actually got imported + RefPtr importedModuleDecl; +}; + +// A generic declaration, parameterized on types/values +class GenericDecl : public ContainerDecl +{ + SLANG_CLASS(GenericDecl) + // The decl that is genericized... + RefPtr inner; +}; + +class GenericTypeParamDecl : public SimpleTypeDecl +{ + SLANG_CLASS(GenericTypeParamDecl) + // 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; +}; + +// A constraint placed as part of a generic declaration +class GenericTypeConstraintDecl : public TypeConstraintDecl +{ + SLANG_CLASS(GenericTypeConstraintDecl) + + // 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 super-type, respectively. + TypeExp sub; + TypeExp sup; + + virtual TypeExp& getSup() override + { + return sup; + } +}; + +class GenericValueParamDecl : public VarDeclBase +{ + SLANG_CLASS(GenericValueParamDecl) +}; + +// 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 +{ + SLANG_CLASS(EmptyDecl) +}; + +// A declaration used by the implementation to put syntax keywords +// into the current scope. +// +class SyntaxDecl : public Decl +{ + SLANG_CLASS(SyntaxDecl) + + // What type of syntax node will be produced when parsing with this keyword? + SyntaxClass syntaxClass; + + // Callback to invoke in order to parse syntax with this keyword. + SyntaxParseCallback parseCallback; + void* parseUserData; +}; + +// A declaration of an attribute to be used with `[name(...)]` syntax. +// +class AttributeDecl : public ContainerDecl +{ + SLANG_CLASS(AttributeDecl) + // What type of syntax node will be produced to represent this attribute. + SyntaxClass syntaxClass; +}; + +#undef SLANG_ABSTRACT_CLASS +#undef SLANG_CLASS + +} // namespace Slang diff --git a/source/slang/slang-ast-expr.h b/source/slang/slang-ast-expr.h new file mode 100644 index 000000000..31e3869d3 --- /dev/null +++ b/source/slang/slang-ast-expr.h @@ -0,0 +1,311 @@ +// slang-ast-expr.h + +#pragma once + +#include "slang-ast-base.h" + +namespace Slang { + +#define SLANG_ABSTRACT_CLASS(x) SLANG_ABSTRACT_CLASS_REFLECT(x) +#define SLANG_CLASS(x) SLANG_CLASS_REFLECT_WITH_ACCEPT(x) + +// Syntax class definitions for expressions. + +// Base class for expressions that will reference declarations +class DeclRefExpr: public Expr +{ + SLANG_ABSTRACT_CLASS(DeclRefExpr) + + // The scope in which to perform lookup + RefPtr scope; + + // The declaration of the symbol being referenced + DeclRef declRef; + + // The name of the symbol being referenced + Name* name; +}; + +class VarExpr : public DeclRefExpr +{ + SLANG_CLASS(VarExpr) +}; + +// An expression that references an overloaded set of declarations +// having the same name. +class OverloadedExpr : public Expr +{ + SLANG_CLASS(OverloadedExpr) + + // The name that was looked up and found to be overloaded + Name* name; + + // Optional: the base expression is this overloaded result + // arose from a member-reference expression. + RefPtr base; + + // The lookup result that was ambiguous + LookupResult lookupResult2; +}; + +// An expression that references an overloaded set of declarations +// having the same name. +class OverloadedExpr2: public Expr +{ + SLANG_CLASS(OverloadedExpr2) + + // Optional: the base expression is this overloaded result + // arose from a member-reference expression. + RefPtr base; + + // The lookup result that was ambiguous + List> candidiateExprs; +}; + +class LiteralExpr : public Expr +{ + SLANG_ABSTRACT_CLASS(LiteralExpr) + // The token that was used to express the literal. This can be + // used to get the raw text of the literal, including any suffix. + Token token; +}; + +class IntegerLiteralExpr : public LiteralExpr +{ + SLANG_CLASS(IntegerLiteralExpr) + + IntegerLiteralValue value; +}; + +class FloatingPointLiteralExpr: public LiteralExpr +{ + SLANG_CLASS(FloatingPointLiteralExpr) + FloatingPointLiteralValue value; +}; + +class BoolLiteralExpr : public LiteralExpr +{ + SLANG_CLASS(BoolLiteralExpr) + bool value; +}; + +class StringLiteralExpr : public LiteralExpr +{ + SLANG_CLASS(StringLiteralExpr) + + // TODO: consider storing the "segments" of the string + // literal, in the case where multiple literals were + //lined up at the lexer level, e.g.: + // + // "first" "second" "third" + // + String value; +}; + +// An initializer list, e.g. `{ 1, 2, 3 }` +class InitializerListExpr : public Expr +{ + SLANG_CLASS(InitializerListExpr) + List> args; +}; + +// A base class for expressions with arguments +class ExprWithArgsBase : public Expr +{ + SLANG_ABSTRACT_CLASS(ExprWithArgsBase) + + List> Arguments; +}; + +// An aggregate type constructor +class AggTypeCtorExpr : public ExprWithArgsBase +{ + SLANG_CLASS(AggTypeCtorExpr) + + TypeExp base;; +}; + + +// A base expression being applied to arguments: covers +// both ordinary `()` function calls and `<>` generic application +class AppExprBase : public ExprWithArgsBase +{ + SLANG_ABSTRACT_CLASS(AppExprBase) + + RefPtr FunctionExpr; +}; + +class InvokeExpr: public AppExprBase +{ + SLANG_CLASS(InvokeExpr) +}; + +class OperatorExpr: public InvokeExpr +{ + SLANG_CLASS(OperatorExpr) +}; + +class InfixExpr: public OperatorExpr +{ + SLANG_CLASS(InfixExpr) +}; +class PrefixExpr: public OperatorExpr +{ + SLANG_CLASS(PrefixExpr) +}; +class PostfixExpr: public OperatorExpr +{ + SLANG_CLASS(PostfixExpr) +}; + +class IndexExpr: public Expr +{ + SLANG_CLASS(IndexExpr) + + RefPtr BaseExpression; + RefPtr IndexExpression; +}; + +class MemberExpr: public DeclRefExpr +{ + SLANG_CLASS(MemberExpr) + RefPtr BaseExpression; +}; + +// Member looked up on a type, rather than a value +class StaticMemberExpr: public DeclRefExpr +{ + SLANG_CLASS(StaticMemberExpr) + RefPtr BaseExpression; +}; + +class SwizzleExpr: public Expr +{ + SLANG_CLASS(SwizzleExpr) + RefPtr base; + int elementCount; + int elementIndices[4]; +}; + +// A dereference of a pointer or pointer-like type +class DerefExpr: public Expr +{ + SLANG_CLASS(DerefExpr) + RefPtr base; +}; + +// Any operation that performs type-casting +class TypeCastExpr: public InvokeExpr +{ + SLANG_CLASS(TypeCastExpr) +// TypeExp TargetType; +// RefPtr Expression; +}; + +// An explicit type-cast that appear in the user's code with `(type) expr` syntax +class ExplicitCastExpr: public TypeCastExpr +{ + SLANG_CLASS(ExplicitCastExpr) +}; + +// An implicit type-cast inserted during semantic checking +class ImplicitCastExpr : public TypeCastExpr +{ + SLANG_CLASS(ImplicitCastExpr) +}; + + /// A cast from a value to an interface ("existential") type. +class CastToInterfaceExpr: public Expr +{ + SLANG_CLASS(CastToInterfaceExpr) + + /// The value being cast to an interface type + RefPtr valueArg; + + /// A witness showing that `valueArg` conforms to the chosen interface + RefPtr witnessArg; +}; + +class SelectExpr: public OperatorExpr +{ + SLANG_CLASS(SelectExpr) +}; + +class GenericAppExpr: public AppExprBase +{ + SLANG_CLASS(GenericAppExpr) +}; + +// An expression representing re-use of the syntax for a type in more +// than once conceptually-distinct declaration +class SharedTypeExpr: public Expr +{ + SLANG_CLASS(SharedTypeExpr) + // The underlying type expression that we want to share + TypeExp base; +}; + +class AssignExpr: public Expr +{ + SLANG_CLASS(AssignExpr) + RefPtr left;; + RefPtr right;; +}; + +// Just an expression inside parentheses `(exp)` +// +// We keep this around explicitly to be sure we don't lose any structure +// when we do rewriter stuff. +class ParenExpr: public Expr +{ + SLANG_CLASS(ParenExpr) + RefPtr base;; +}; + +// An object-oriented `this` expression, used to +// refer to the current instance of an enclosing type. +class ThisExpr: public Expr +{ + SLANG_CLASS(ThisExpr) + RefPtr scope;; +}; + +// An expression that binds a temporary variable in a local expression context +class LetExpr: public Expr +{ + SLANG_CLASS(LetExpr) + RefPtr decl; + RefPtr body; +}; + +class ExtractExistentialValueExpr: public Expr +{ + SLANG_CLASS(ExtractExistentialValueExpr) + DeclRef declRef; +}; + + /// A type expression of the form `__TaggedUnion(A, ...)`. + /// + /// An expression of this form will resolve to a `TaggedUnionType` + /// when checked. + /// +class TaggedUnionTypeExpr: public Expr +{ + SLANG_CLASS(TaggedUnionTypeExpr) + List caseTypes; +}; + + /// A type expression of the form `This` + /// + /// Refers to the type of `this` in the current context. + /// +class ThisTypeExpr: public Expr +{ + SLANG_CLASS(ThisTypeExpr) + RefPtr scope; +}; + +#undef SLANG_ABSTRACT_CLASS +#undef SLANG_CLASS + +} // namespace Slang diff --git a/source/slang/slang-ast-modifier.h b/source/slang/slang-ast-modifier.h new file mode 100644 index 000000000..440575171 --- /dev/null +++ b/source/slang/slang-ast-modifier.h @@ -0,0 +1,883 @@ +// slang-ast-modifier.h + +#pragma once + +#include "slang-ast-base.h" + +namespace Slang { + +#define SLANG_ABSTRACT_CLASS(x) SLANG_ABSTRACT_CLASS_REFLECT(x) +#define SLANG_CLASS(x) SLANG_CLASS_REFLECT_WITH_ACCEPT(x) + +// Syntax class definitions for modifiers. + +// Simple modifiers have no state beyond their identity + +class InModifier : public Modifier { SLANG_CLASS(InModifier)}; +class OutModifier : public Modifier { SLANG_CLASS(OutModifier)}; +class ConstModifier : public Modifier { SLANG_CLASS(ConstModifier)}; +class InstanceModifier : public Modifier { SLANG_CLASS(InstanceModifier)}; +class BuiltinModifier : public Modifier { SLANG_CLASS(BuiltinModifier)}; +class InlineModifier : public Modifier { SLANG_CLASS(InlineModifier)}; +class PublicModifier : public Modifier { SLANG_CLASS(PublicModifier)}; +class RequireModifier : public Modifier { SLANG_CLASS(RequireModifier)}; +class ParamModifier : public Modifier { SLANG_CLASS(ParamModifier)}; +class ExternModifier : public Modifier { SLANG_CLASS(ExternModifier)}; +class InputModifier : public Modifier { SLANG_CLASS(InputModifier)}; +class TransparentModifier : public Modifier { SLANG_CLASS(TransparentModifier)}; +class FromStdLibModifier : public Modifier { SLANG_CLASS(FromStdLibModifier)}; +class PrefixModifier : public Modifier { SLANG_CLASS(PrefixModifier)}; +class PostfixModifier : public Modifier { SLANG_CLASS(PostfixModifier)}; +class ExportedModifier : public Modifier { SLANG_CLASS(ExportedModifier)}; +class ConstExprModifier : public Modifier { SLANG_CLASS(ConstExprModifier)}; +class GloballyCoherentModifier : public Modifier { SLANG_CLASS(GloballyCoherentModifier)}; + +// A modifier that marks something as an operation that +// has a one-to-one translation to the IR, and thus +// has no direct definition in the high-level language. +// +class IntrinsicOpModifier : public Modifier +{ + SLANG_CLASS(IntrinsicOpModifier) + + // Token that names the intrinsic op. + Token opToken; + + // The IR opcode for the intrinsic operation. + // + uint32_t op = 0; +}; + +// A modifier that marks something as an intrinsic function, +// for some subset of targets. +class TargetIntrinsicModifier : public Modifier +{ + SLANG_CLASS(TargetIntrinsicModifier) + + // Token that names the target that the operation + // is an intrisic for. + Token targetToken; + + // A custom definition for the operation + Token definitionToken; +}; + +// A modifier that marks a declaration as representing a +// specialization that should be preferred on a particular +// target. +class SpecializedForTargetModifier : public Modifier +{ + SLANG_CLASS(SpecializedForTargetModifier) + + // Token that names the target that the operation + // has been specialized for. + Token targetToken; +}; + +// A modifier to tag something as an intrinsic that requires +// a certain GLSL extension to be enabled when used +class RequiredGLSLExtensionModifier : public Modifier +{ + SLANG_CLASS(RequiredGLSLExtensionModifier) + + Token extensionNameToken; +}; + +// A modifier to tag something as an intrinsic that requires +// a certain GLSL version to be enabled when used +class RequiredGLSLVersionModifier : public Modifier +{ + SLANG_CLASS(RequiredGLSLVersionModifier) + + Token versionNumberToken; +}; + + +// A modifier to tag something as an intrinsic that requires +// a certain SPIRV version to be enabled when used. Specified as "major.minor" +class RequiredSPIRVVersionModifier : public Modifier +{ + SLANG_CLASS(RequiredSPIRVVersionModifier) + + SemanticVersion version; +}; + +// A modifier to tag something as an intrinsic that requires +// a certain CUDA SM version to be enabled when used. Specified as "major.minor" +class RequiredCUDASMVersionModifier : public Modifier +{ + SLANG_CLASS(RequiredCUDASMVersionModifier) + + SemanticVersion version; +}; + +class InOutModifier : public OutModifier +{ + SLANG_CLASS(InOutModifier) +}; + + +// `__ref` modifier for by-reference parameter passing +class RefModifier : public Modifier +{ + SLANG_CLASS(RefModifier) +}; + + +// 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 +{ + SLANG_CLASS(SharedModifiers) +}; + + +// 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 +{ + SLANG_ABSTRACT_CLASS(GLSLLayoutModifier) + + + // The token used to introduce the modifier is stored + // as the `nameToken` field. + + // TODO: may want to accept a full expression here + Token valToken; +}; + +// AST nodes to represent the begin/end of a `layout` modifier group +class GLSLLayoutModifierGroupMarker : public Modifier +{ + SLANG_ABSTRACT_CLASS(GLSLLayoutModifierGroupMarker) +}; + +class GLSLLayoutModifierGroupBegin : public GLSLLayoutModifierGroupMarker +{ + SLANG_CLASS(GLSLLayoutModifierGroupBegin) +}; + +class GLSLLayoutModifierGroupEnd : public GLSLLayoutModifierGroupMarker +{ + SLANG_CLASS(GLSLLayoutModifierGroupEnd) +}; + + +// 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 +{ + SLANG_ABSTRACT_CLASS(GLSLParsedLayoutModifier) +}; + +class GLSLUnparsedLayoutModifier : public GLSLLayoutModifier +{ + SLANG_CLASS(GLSLUnparsedLayoutModifier) +}; + + +// Specific cases for known GLSL `layout` modifiers that we need to work with +class GLSLConstantIDLayoutModifier : public GLSLParsedLayoutModifier +{ + SLANG_CLASS(GLSLConstantIDLayoutModifier) +}; + +class GLSLLocationLayoutModifier : public GLSLParsedLayoutModifier +{ + SLANG_CLASS(GLSLLocationLayoutModifier) +}; + + +// A catch-all for single-keyword modifiers +class SimpleModifier : public Modifier +{ + SLANG_CLASS(SimpleModifier) +}; + + +// Some GLSL-specific modifiers +class GLSLBufferModifier : public SimpleModifier +{ + SLANG_CLASS(GLSLBufferModifier) +}; + +class GLSLWriteOnlyModifier : public SimpleModifier +{ + SLANG_CLASS(GLSLWriteOnlyModifier) +}; + +class GLSLReadOnlyModifier : public SimpleModifier +{ + SLANG_CLASS(GLSLReadOnlyModifier) +}; + +class GLSLPatchModifier : public SimpleModifier +{ + SLANG_CLASS(GLSLPatchModifier) +}; + + +// Indicates that this is a variable declaration that corresponds to +// a parameter block declaration in the source program. +class ImplicitParameterGroupVariableModifier : public Modifier +{ + SLANG_CLASS(ImplicitParameterGroupVariableModifier) +}; + + +// Indicates that this is a type that corresponds to the element +// type of a parameter block declaration in the source program. +class ImplicitParameterGroupElementTypeModifier : public Modifier +{ + SLANG_CLASS(ImplicitParameterGroupElementTypeModifier) +}; + + +// An HLSL semantic +class HLSLSemantic : public Modifier +{ + SLANG_ABSTRACT_CLASS(HLSLSemantic) + + Token name; +}; + +// An HLSL semantic that affects layout +class HLSLLayoutSemantic : public HLSLSemantic +{ + SLANG_CLASS(HLSLLayoutSemantic) + + Token registerName; + Token componentMask; +}; + +// An HLSL `register` semantic +class HLSLRegisterSemantic : public HLSLLayoutSemantic +{ + SLANG_CLASS(HLSLRegisterSemantic) + + Token spaceName; +}; + +// TODO(tfoley): `packoffset` +class HLSLPackOffsetSemantic : public HLSLLayoutSemantic +{ + SLANG_CLASS(HLSLPackOffsetSemantic) +}; + + +// An HLSL semantic that just associated a declaration with a semantic name +class HLSLSimpleSemantic : public HLSLSemantic +{ + SLANG_CLASS(HLSLSimpleSemantic) +}; + + +// GLSL + +// Directives that came in via the preprocessor, but +// that we need to keep around for later steps +class GLSLPreprocessorDirective : public Modifier +{ + SLANG_CLASS(GLSLPreprocessorDirective) +}; + + +// A GLSL `#version` directive +class GLSLVersionDirective : public GLSLPreprocessorDirective +{ + SLANG_CLASS(GLSLVersionDirective) + + + // 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 +{ + SLANG_CLASS(GLSLExtensionDirective) + + + // Token giving the version number to use + Token extensionNameToken; + + // Optional token giving the sub-profile to be used + Token dispositionToken; +}; + +class ParameterGroupReflectionName : public Modifier +{ + SLANG_CLASS(ParameterGroupReflectionName) + + NameLoc nameAndLoc; +}; + +// A modifier that indicates a built-in base type (e.g., `float`) +class BuiltinTypeModifier : public Modifier +{ + SLANG_CLASS(BuiltinTypeModifier) + + 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 +{ + SLANG_CLASS(MagicTypeModifier) + + String name; + uint32_t tag; +}; + +// A modifier applied to declarations of builtin types to indicate how they +// should be lowered to the IR. +// +// TODO: This should really subsume `BuiltinTypeModifier` and +// `MagicTypeModifier` so that we don't have to apply all of them. +class IntrinsicTypeModifier : public Modifier +{ + SLANG_CLASS(IntrinsicTypeModifier) + + // The IR opcode to use when constructing a type + uint32_t irOp; + + // Additional literal opreands to provide when creating instances. + // (e.g., for a texture type this passes in shape/mutability info) + List irOperands; +}; + +// Modifiers that affect the storage layout for matrices +class MatrixLayoutModifier : public Modifier +{ + SLANG_CLASS(MatrixLayoutModifier) +}; + + +// Modifiers that specify row- and column-major layout, respectively +class RowMajorLayoutModifier : public MatrixLayoutModifier +{ + SLANG_CLASS(RowMajorLayoutModifier) +}; + +class ColumnMajorLayoutModifier : public MatrixLayoutModifier +{ + SLANG_CLASS(ColumnMajorLayoutModifier) +}; + + +// The HLSL flavor of those modifiers +class HLSLRowMajorLayoutModifier : public RowMajorLayoutModifier +{ + SLANG_CLASS(HLSLRowMajorLayoutModifier) +}; + +class HLSLColumnMajorLayoutModifier : public ColumnMajorLayoutModifier +{ + SLANG_CLASS(HLSLColumnMajorLayoutModifier) +}; + + +// 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 +{ + SLANG_CLASS(GLSLRowMajorLayoutModifier) +}; + +class GLSLColumnMajorLayoutModifier : public RowMajorLayoutModifier +{ + SLANG_CLASS(GLSLColumnMajorLayoutModifier) +}; + + +// More HLSL Keyword + +class InterpolationModeModifier : public Modifier +{ + SLANG_ABSTRACT_CLASS(InterpolationModeModifier) + +}; + +// HLSL `nointerpolation` modifier +class HLSLNoInterpolationModifier : public InterpolationModeModifier +{ + SLANG_CLASS(HLSLNoInterpolationModifier) +}; + + +// HLSL `noperspective` modifier +class HLSLNoPerspectiveModifier : public InterpolationModeModifier +{ + SLANG_CLASS(HLSLNoPerspectiveModifier) +}; + + +// HLSL `linear` modifier +class HLSLLinearModifier : public InterpolationModeModifier +{ + SLANG_CLASS(HLSLLinearModifier) +}; + + +// HLSL `sample` modifier +class HLSLSampleModifier : public InterpolationModeModifier +{ + SLANG_CLASS(HLSLSampleModifier) +}; + + +// HLSL `centroid` modifier +class HLSLCentroidModifier : public InterpolationModeModifier +{ + SLANG_CLASS(HLSLCentroidModifier) +}; + + +// HLSL `precise` modifier +class PreciseModifier : public Modifier +{ + SLANG_CLASS(PreciseModifier) +}; + + +// HLSL `shared` modifier (which is used by the effect system, +// and shouldn't be confused with `groupshared`) +class HLSLEffectSharedModifier : public Modifier +{ + SLANG_CLASS(HLSLEffectSharedModifier) +}; + + +// HLSL `groupshared` modifier +class HLSLGroupSharedModifier : public Modifier +{ + SLANG_CLASS(HLSLGroupSharedModifier) +}; + + +// HLSL `static` modifier (probably doesn't need to be +// treated as HLSL-specific) +class HLSLStaticModifier : public Modifier +{ + SLANG_CLASS(HLSLStaticModifier) +}; + + +// HLSL `uniform` modifier (distinct meaning from GLSL +// use of the keyword) +class HLSLUniformModifier : public Modifier +{ + SLANG_CLASS(HLSLUniformModifier) +}; + + +// HLSL `volatile` modifier (ignored) +class HLSLVolatileModifier : public Modifier +{ + SLANG_CLASS(HLSLVolatileModifier) +}; + + +class AttributeTargetModifier : public Modifier +{ + SLANG_CLASS(AttributeTargetModifier) + + // A class to which the declared attribute type is applicable + SyntaxClass syntaxClass; +}; + +// Base class for checked and unchecked `[name(arg0, ...)]` style attribute. +class AttributeBase : public Modifier +{ + SLANG_CLASS(AttributeBase) + + List> args; +}; + +// A `[name(...)]` attribute that hasn't undergone any semantic analysis. +// After analysis, this will be transformed into a more specific case. +class UncheckedAttribute : public AttributeBase +{ + SLANG_CLASS(UncheckedAttribute) + + RefPtr scope; +}; + +// A `[name(arg0, ...)]` style attribute that has been validated. +class Attribute : public AttributeBase +{ + SLANG_CLASS(Attribute) + + AttributeArgumentValueDict intArgVals; +}; + +class UserDefinedAttribute : public Attribute +{ + SLANG_CLASS(UserDefinedAttribute) + +}; + +class AttributeUsageAttribute : public Attribute +{ + SLANG_CLASS(AttributeUsageAttribute) + + SyntaxClass targetSyntaxClass; +}; + +// An `[unroll]` or `[unroll(count)]` attribute +class UnrollAttribute : public Attribute +{ + SLANG_CLASS(UnrollAttribute) + + IntegerLiteralValue getCount(); +}; + +class LoopAttribute : public Attribute +{ + SLANG_CLASS(LoopAttribute) +}; + // `[loop]` +class FastOptAttribute : public Attribute +{ + SLANG_CLASS(FastOptAttribute) +}; + // `[fastopt]` +class AllowUAVConditionAttribute : public Attribute +{ + SLANG_CLASS(AllowUAVConditionAttribute) +}; + // `[allow_uav_condition]` +class BranchAttribute : public Attribute +{ + SLANG_CLASS(BranchAttribute) +}; + // `[branch]` +class FlattenAttribute : public Attribute +{ + SLANG_CLASS(FlattenAttribute) +}; + // `[flatten]` +class ForceCaseAttribute : public Attribute +{ + SLANG_CLASS(ForceCaseAttribute) +}; + // `[forcecase]` +class CallAttribute : public Attribute +{ + SLANG_CLASS(CallAttribute) +}; + // `[call]` + + +// [[vk_push_constant]] [[push_constant]] +class PushConstantAttribute : public Attribute +{ + SLANG_CLASS(PushConstantAttribute) +}; + + +// [[vk_shader_record]] [[shader_record]] +class ShaderRecordAttribute : public Attribute +{ + SLANG_CLASS(ShaderRecordAttribute) +}; + + +// [[vk_binding]] +class GLSLBindingAttribute : public Attribute +{ + SLANG_CLASS(GLSLBindingAttribute) + + int32_t binding = 0; + int32_t set = 0; +}; + +class GLSLSimpleIntegerLayoutAttribute : public Attribute +{ + SLANG_CLASS(GLSLSimpleIntegerLayoutAttribute) + + int32_t value = 0; +}; + +// [[vk_location]] +class GLSLLocationAttribute : public GLSLSimpleIntegerLayoutAttribute +{ + SLANG_CLASS(GLSLLocationAttribute) +}; + + +// [[vk_index]] +class GLSLIndexAttribute : public GLSLSimpleIntegerLayoutAttribute +{ + SLANG_CLASS(GLSLIndexAttribute) +}; + + +// TODO: for attributes that take arguments, the syntax node +// classes should provide accessors for the values of those arguments. + +class MaxTessFactorAttribute : public Attribute +{ + SLANG_CLASS(MaxTessFactorAttribute) +}; + +class OutputControlPointsAttribute : public Attribute +{ + SLANG_CLASS(OutputControlPointsAttribute) +}; + +class OutputTopologyAttribute : public Attribute +{ + SLANG_CLASS(OutputTopologyAttribute) +}; + +class PartitioningAttribute : public Attribute +{ + SLANG_CLASS(PartitioningAttribute) +}; + +class PatchConstantFuncAttribute : public Attribute +{ + SLANG_CLASS(PatchConstantFuncAttribute) + + RefPtr patchConstantFuncDecl; +}; +class DomainAttribute : public Attribute +{ + SLANG_CLASS(DomainAttribute) +}; + + +class EarlyDepthStencilAttribute : public Attribute +{ + SLANG_CLASS(EarlyDepthStencilAttribute) +}; + // `[earlydepthstencil]` + +// An HLSL `[numthreads(x,y,z)]` attribute +class NumThreadsAttribute : public Attribute +{ + SLANG_CLASS(NumThreadsAttribute) + + // The number of threads to use along each axis + // + // TODO: These should be accessors that use the + // ordinary `args` list, rather than side data. + int32_t x; + int32_t y; + int32_t z; +}; + +class MaxVertexCountAttribute : public Attribute +{ + SLANG_CLASS(MaxVertexCountAttribute) + + // The number of max vertex count for geometry shader + // + // TODO: This should be an accessor that uses the + // ordinary `args` list, rather than side data. + int32_t value; +}; + +class InstanceAttribute : public Attribute +{ + SLANG_CLASS(InstanceAttribute) + + // The number of instances to run for geometry shader + // + // TODO: This should be an accessor that uses the + // ordinary `args` list, rather than side data. + int32_t value; +}; + +// A `[shader("stageName")]` attribute, which marks an entry point +// to be compiled, and specifies the stage for that entry point +class EntryPointAttribute : public Attribute +{ + SLANG_CLASS(EntryPointAttribute) + + // The resolved stage that the entry point is targetting. + // + // TODO: This should be an accessor that uses the + // ordinary `args` list, rather than side data. + Stage stage;; +}; + +// A `[__vulkanRayPayload]` attribute, which is used in the +// standard library implementation to indicate that a variable +// actually represents the input/output interface for a Vulkan +// ray tracing shader to pass per-ray payload information. +class VulkanRayPayloadAttribute : public Attribute +{ + SLANG_CLASS(VulkanRayPayloadAttribute) +}; + + +// A `[__vulkanCallablePayload]` attribute, which is used in the +// standard library implementation to indicate that a variable +// actually represents the input/output interface for a Vulkan +// ray tracing shader to pass payload information to/from a callee. +class VulkanCallablePayloadAttribute : public Attribute +{ + SLANG_CLASS(VulkanCallablePayloadAttribute) +}; + + +// A `[__vulkanHitAttributes]` attribute, which is used in the +// standard library implementation to indicate that a variable +// actually represents the output interface for a Vulkan +// intersection shader to pass hit attribute information. +class VulkanHitAttributesAttribute : public Attribute +{ + SLANG_CLASS(VulkanHitAttributesAttribute) +}; + + +// A `[mutating]` attribute, which indicates that a member +// function is allowed to modify things through its `this` +// argument. +// +class MutatingAttribute : public Attribute +{ + SLANG_CLASS(MutatingAttribute) +}; + + +// A `[__readNone]` attribute, which indicates that a function +// computes its results strictly based on argument values, without +// reading or writing through any pointer arguments, or any other +// state that could be observed by a caller. +// +class ReadNoneAttribute : public Attribute +{ + SLANG_CLASS(ReadNoneAttribute) +}; + + + +// HLSL modifiers for geometry shader input topology +class HLSLGeometryShaderInputPrimitiveTypeModifier : public Modifier +{ + SLANG_CLASS(HLSLGeometryShaderInputPrimitiveTypeModifier) +}; + +class HLSLPointModifier : public HLSLGeometryShaderInputPrimitiveTypeModifier +{ + SLANG_CLASS(HLSLPointModifier) +}; + +class HLSLLineModifier : public HLSLGeometryShaderInputPrimitiveTypeModifier +{ + SLANG_CLASS(HLSLLineModifier) +}; + +class HLSLTriangleModifier : public HLSLGeometryShaderInputPrimitiveTypeModifier +{ + SLANG_CLASS(HLSLTriangleModifier) +}; + +class HLSLLineAdjModifier : public HLSLGeometryShaderInputPrimitiveTypeModifier +{ + SLANG_CLASS(HLSLLineAdjModifier) +}; + +class HLSLTriangleAdjModifier : public HLSLGeometryShaderInputPrimitiveTypeModifier +{ + SLANG_CLASS(HLSLTriangleAdjModifier) +}; + + +// A modifier to be attached to syntax after we've computed layout +class ComputedLayoutModifier : public Modifier +{ + SLANG_CLASS(ComputedLayoutModifier) + + RefPtr layout; +}; + + +class TupleVarModifier : public Modifier +{ + SLANG_CLASS(TupleVarModifier) + +// TupleFieldModifier* tupleField = nullptr; +}; + +// A modifier to indicate that a constructor/initializer can be used +// to perform implicit type conversion, and to specify the cost of +// the conversion, if applied. +class ImplicitConversionModifier : public Modifier +{ + SLANG_CLASS(ImplicitConversionModifier) + + // The conversion cost, used to rank conversions + ConversionCost cost; +}; + +class FormatAttribute : public Attribute +{ + SLANG_CLASS(FormatAttribute) + + ImageFormat format; +}; + +class AllowAttribute : public Attribute +{ + SLANG_CLASS(AllowAttribute) + + DiagnosticInfo const* diagnostic = nullptr; +}; + + +// A `[__extern]` attribute, which indicates that a function/type is defined externally +// +class ExternAttribute : public Attribute +{ + SLANG_CLASS(ExternAttribute) +}; + + +// An `[__unsafeForceInlineExternal]` attribute indicates that the callee should be inlined +// into call sites after initial IR generation (that is, as early as possible). +// +class UnsafeForceInlineEarlyAttribute : public Attribute +{ + SLANG_CLASS(UnsafeForceInlineEarlyAttribute) +}; + + +#undef SLANG_ABSTRACT_CLASS +#undef SLANG_CLASS + +} // namespace Slang diff --git a/source/slang/slang-ast-reflect.cpp b/source/slang/slang-ast-reflect.cpp new file mode 100644 index 000000000..471daf92b --- /dev/null +++ b/source/slang/slang-ast-reflect.cpp @@ -0,0 +1,70 @@ +#include "../../slang.h" + +#include "slang-ast-reflect.h" + +#include "../core/slang-smart-pointer.h" + +#include "slang-ast-all.h" + +#include +#include + +#include "slang-ast-generated-macro.h" + +namespace Slang +{ + +#define SLANG_REFLECT_GET_REFLECT_CLASS_INFO(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) infos.infos[int(ASTNodeType::NAME)] = &NAME::kReflectClassInfo; + +static ReflectClassInfo::Infos _calcInfos() +{ + ReflectClassInfo::Infos infos; + memset(&infos, 0, sizeof(infos)); + SLANG_ALL_ASTNode_NodeBase(SLANG_REFLECT_GET_REFLECT_CLASS_INFO, _) + SLANG_ALL_ASTNode_Substitutions(SLANG_REFLECT_GET_REFLECT_CLASS_INFO, _) + return infos; +} + +/* static */const ReflectClassInfo::Infos ReflectClassInfo::kInfos = _calcInfos(); + +bool ReflectClassInfo::isSubClassOfSlow(const ThisType& super) const +{ + ReflectClassInfo const* info = this; + while (info) + { + if (info == &super) + return true; + info = info->m_superClass; + } + return false; +} + +// Now try and implement all of the classes +// Macro generated is of the format + + +template +struct CreateImpl +{ + static void* create() { return new T; } +}; + +#define SLANG_GET_SUPER_BASE(SUPER) nullptr +#define SLANG_GET_SUPER_INNER(SUPER) &SUPER::kReflectClassInfo +#define SLANG_GET_SUPER_LEAF(SUPER) &SUPER::kReflectClassInfo + +#define SLANG_GET_CREATE_FUNC_ABSTRACT(NAME) nullptr +#define SLANG_GET_CREATE_FUNC_NONE(NAME) &CreateImpl::create + +#define SLANG_GET_CREATE_FUNC_NON_VISITOR_ABSTRACT(NAME) nullptr +#define SLANG_GET_CREATE_FUNC_NON_VISITOR(NAME) &CreateImpl::create + + +#define SLANG_REFLECT_CLASS_INFO(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \ + /* static */const ReflectClassInfo NAME::kReflectClassInfo = { uint32_t(ASTNodeType::NAME), uint32_t(ASTNodeType::LAST), SLANG_GET_SUPER_##TYPE(SUPER), #NAME, SLANG_GET_CREATE_FUNC_##MARKER(NAME) }; + +SLANG_ALL_ASTNode_NodeBase(SLANG_REFLECT_CLASS_INFO, _) +SLANG_ALL_ASTNode_Substitutions(SLANG_REFLECT_CLASS_INFO, _) + + +} // namespace Slang diff --git a/source/slang/slang-ast-reflect.h b/source/slang/slang-ast-reflect.h new file mode 100644 index 000000000..953c1eaf1 --- /dev/null +++ b/source/slang/slang-ast-reflect.h @@ -0,0 +1,37 @@ +// slang-ast-reflect.h + +#ifndef SLANG_AST_REFLECT_H +#define SLANG_AST_REFLECT_H + +#include "slang-ast-generated.h" + +#define SLANG_AST_OVERRIDE_BASE +#define SLANG_AST_OVERRIDE_INNER override +#define SLANG_AST_OVERRIDE_LEAF override + +// Implement the part that uses the class definition +#define SLANG_CLASS_REFLECT_DEFAULT_IMPL(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \ + typedef SUPER Super; \ + SLANG_FORCE_INLINE static bool isDerivedFrom(ASTNodeType type) { return int(type) >= int(kType) && int(type) <= int(ASTNodeType::LAST); } \ + virtual const ReflectClassInfo& getClassInfo() const SLANG_AST_OVERRIDE_##TYPE { return kReflectClassInfo; } \ + + +#define SLANG_CLASS_REFLECT_DEFAULT(NAME) \ + public: \ + static const ASTNodeType kType = ASTNodeType::NAME; \ + static const ReflectClassInfo kReflectClassInfo; \ + SLANG_ASTNode_##NAME(SLANG_CLASS_REFLECT_DEFAULT_IMPL, _) + +#define SLANG_CLASS_REFLECT_WITH_ACCEPT(NAME) \ + SLANG_CLASS_REFLECT_DEFAULT(NAME) \ + virtual void accept(NAME::Visitor* visitor, void* extra) override; + +#define SLANG_ABSTRACT_CLASS_REFLECT(NAME) SLANG_CLASS_REFLECT_DEFAULT(NAME) +#define SLANG_CLASS_REFLECT(NAME) SLANG_CLASS_REFLECT_DEFAULT(NAME) + +// Used for C++ extractor, does nothing here +#define SLANG_REFLECT_BASE_CLASS(x) /* ... */ + + + +#endif // SLANG_AST_REFLECT_H diff --git a/source/slang/slang-ast-stmt.h b/source/slang/slang-ast-stmt.h new file mode 100644 index 000000000..28b8162a2 --- /dev/null +++ b/source/slang/slang-ast-stmt.h @@ -0,0 +1,213 @@ +// slang-ast-stmt.h + +#pragma once + +#include "slang-ast-base.h" + +namespace Slang { + +#define SLANG_ABSTRACT_CLASS(x) SLANG_ABSTRACT_CLASS_REFLECT(x) +#define SLANG_CLASS(x) SLANG_CLASS_REFLECT_WITH_ACCEPT(x) + +// Syntax class definitions for statements. + +class ScopeStmt : public Stmt +{ + SLANG_ABSTRACT_CLASS(ScopeStmt) + + RefPtr scopeDecl; +}; + +// A sequence of statements, treated as a single statement +class SeqStmt : public Stmt +{ + SLANG_CLASS(SeqStmt) + + List> stmts; +}; + +// The simplest kind of scope statement: just a `{...}` block +class BlockStmt : public ScopeStmt +{ + SLANG_CLASS(BlockStmt) + + RefPtr body;; +}; + +// A statement that we aren't going to parse or check, because +// we want to let a downstream compiler handle any issues +class UnparsedStmt : public Stmt +{ + SLANG_CLASS(UnparsedStmt) + + // The tokens that were contained between `{` and `}` + List tokens; +}; + +class EmptyStmt : public Stmt +{ + SLANG_CLASS(EmptyStmt) +}; + +class DiscardStmt : public Stmt +{ + SLANG_CLASS(DiscardStmt) +}; + +class DeclStmt : public Stmt +{ + SLANG_CLASS(DeclStmt) + + RefPtr decl; +}; + +class IfStmt : public Stmt +{ + SLANG_CLASS(IfStmt) + + RefPtr Predicate; + RefPtr PositiveStatement; + RefPtr NegativeStatement; +}; + +// A statement that can be escaped with a `break` +class BreakableStmt : public ScopeStmt +{ + SLANG_ABSTRACT_CLASS(BreakableStmt) + +}; + +class SwitchStmt : public BreakableStmt +{ + SLANG_CLASS(SwitchStmt) + + RefPtr condition; + RefPtr body; +}; + +// 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 Stmt +{ + SLANG_ABSTRACT_CLASS(ChildStmt) + + Stmt* 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 +{ + SLANG_ABSTRACT_CLASS(CaseStmtBase) + +}; + +// a `case` statement inside a `switch` +class CaseStmt : public CaseStmtBase +{ + SLANG_CLASS(CaseStmt) + + RefPtr expr; +}; + +// a `default` statement inside a `switch` +class DefaultStmt : public CaseStmtBase +{ + SLANG_CLASS(DefaultStmt) +}; + +// A statement that represents a loop, and can thus be escaped with a `continue` +class LoopStmt : public BreakableStmt +{ + SLANG_ABSTRACT_CLASS(LoopStmt) + +}; + +// A `for` statement +class ForStmt : public LoopStmt +{ + SLANG_CLASS(ForStmt) + + RefPtr InitialStatement; + RefPtr SideEffectExpression; + RefPtr PredicateExpression; + RefPtr Statement; +}; + +// A `for` statement in a language that doesn't restrict the scope +// of the loop variable to the body. +class UnscopedForStmt : public ForStmt +{ + SLANG_CLASS(UnscopedForStmt) +; +}; + +class WhileStmt : public LoopStmt +{ + SLANG_CLASS(WhileStmt) + + RefPtr Predicate; + RefPtr Statement; +}; + +class DoWhileStmt : public LoopStmt +{ + SLANG_CLASS(DoWhileStmt) + + RefPtr Statement; + RefPtr Predicate; +}; + +// A compile-time, range-based `for` loop, which will not appear in the output code +class CompileTimeForStmt : public ScopeStmt +{ + SLANG_CLASS(CompileTimeForStmt) + + RefPtr varDecl; + RefPtr rangeBeginExpr; + RefPtr rangeEndExpr; + RefPtr body; + RefPtr rangeBeginVal; + RefPtr rangeEndVal; +}; + +// The case of child statements that do control flow relative +// to their parent statement. +class JumpStmt : public ChildStmt +{ + SLANG_ABSTRACT_CLASS(JumpStmt) + +}; + +class BreakStmt : public JumpStmt +{ + SLANG_CLASS(BreakStmt) +}; + +class ContinueStmt : public JumpStmt +{ + SLANG_CLASS(ContinueStmt) +}; + +class ReturnStmt : public Stmt +{ + SLANG_CLASS(ReturnStmt) + + RefPtr Expression; +}; + +class ExpressionStmt : public Stmt +{ + SLANG_CLASS(ExpressionStmt) + + RefPtr Expression; +}; + +#undef SLANG_ABSTRACT_CLASS +#undef SLANG_CLASS + +} // namespace Slang diff --git a/source/slang/slang-ast-support-types.h b/source/slang/slang-ast-support-types.h new file mode 100644 index 000000000..c1072c923 --- /dev/null +++ b/source/slang/slang-ast-support-types.h @@ -0,0 +1,1330 @@ +#ifndef SLANG_AST_SUPPORT_TYPES_H +#define SLANG_AST_SUPPORT_TYPES_H + +#include "../core/slang-basic.h" +#include "slang-lexer.h" +#include "slang-profile.h" +#include "slang-type-system-shared.h" +#include "../../slang.h" + +#include "../core/slang-semantic-version.h" + +#include "slang-ast-generated.h" + +#include "slang-ast-reflect.h" + + + +#include "slang-name.h" + +#include + +namespace Slang +{ + class Module; + class Name; + class Session; + class Substitutions; + class SyntaxVisitor; + class FuncDecl; + class Layout; + + struct IExprVisitor; + struct IDeclVisitor; + struct IModifierVisitor; + struct IStmtVisitor; + struct ITypeVisitor; + struct IValVisitor; + + class Parser; + class SyntaxNode; + + class Decl; + struct QualType; + class Type; + struct TypeExp; + class Val; + + void printDiagnosticArg(StringBuilder& sb, Decl* decl); + void printDiagnosticArg(StringBuilder& sb, Type* type); + void printDiagnosticArg(StringBuilder& sb, TypeExp const& type); + void printDiagnosticArg(StringBuilder& sb, QualType const& type); + void printDiagnosticArg(StringBuilder& sb, Val* val); + + class SyntaxNode; + SourceLoc const& getDiagnosticPos(SyntaxNode const* syntax); + SourceLoc const& getDiagnosticPos(TypeExp const& typeExp); + + typedef RefPtr (*SyntaxParseCallback)(Parser* parser, void* userData); + + typedef unsigned int ConversionCost; + enum : ConversionCost + { + // No conversion at all + kConversionCost_None = 0, + + // Conversion from a buffer to the type it carries needs to add a minimal + // extra cost, just so we can distinguish an overload on `ConstantBuffer` + // from one on `Foo` + kConversionCost_ImplicitDereference = 10, + + // Conversions based on explicit sub-typing relationships are the cheapest + // + // TODO(tfoley): We will eventually need a discipline for ranking + // when two up-casts are comparable. + kConversionCost_CastToInterface = 50, + + // Conversion that is lossless and keeps the "kind" of the value the same + kConversionCost_RankPromotion = 150, + + // Conversions that are lossless, but change "kind" + kConversionCost_UnsignedToSignedPromotion = 200, + + // Conversion from signed->unsigned integer of same or greater size + kConversionCost_SignedToUnsignedConversion = 300, + + // Cost of converting an integer to a floating-point type + kConversionCost_IntegerToFloatConversion = 400, + + // Default case (usable for user-defined conversions) + kConversionCost_Default = 500, + + // Catch-all for conversions that should be discouraged + // (i.e., that really shouldn't be made implicitly) + // + // TODO: make these conversions not be allowed implicitly in "Slang mode" + kConversionCost_GeneralConversion = 900, + + // This is the cost of an explicit conversion, which should + // not actually be performed. + kConversionCost_Explicit = 90000, + + // Additional conversion cost to add when promoting from a scalar to + // a vector (this will be added to the cost, if any, of converting + // the element type of the vector) + kConversionCost_ScalarToVector = 1, + + // Conversion is impossible + kConversionCost_Impossible = 0xFFFFFFFF, + }; + + enum class ImageFormat + { +#define FORMAT(NAME) NAME, +#include "slang-image-format-defs.h" + }; + + bool findImageFormatByName(char const* name, ImageFormat* outFormat); + char const* getGLSLNameForImageFormat(ImageFormat format); + + // TODO(tfoley): We should ditch this enumeration + // and just use the IR opcodes that represent these + // types directly. The one major complication there + // is that the order of the enum values currently + // matters, since it determines promotion rank. + // We either need to keep that restriction, or + // look up promotion rank by some other means. + // + + class Decl; + class Val; + +#if 0 + // Forward-declare all syntax classes +#define SYNTAX_CLASS(NAME, BASE, ...) class NAME; +#include "slang-object-meta-begin.h" +#include "slang-syntax-defs.h" +#include "slang-object-meta-end.h" +#endif + + // Helper type for pairing up a name and the location where it appeared + struct NameLoc + { + Name* name; + SourceLoc loc; + + NameLoc() + : name(nullptr) + {} + + explicit NameLoc(Name* inName) + : name(inName) + {} + + + NameLoc(Name* inName, SourceLoc inLoc) + : name(inName) + , loc(inLoc) + {} + + NameLoc(Token const& token) + : name(token.getNameOrNull()) + , loc(token.getLoc()) + {} + }; + + struct StringSliceLoc + { + UnownedStringSlice name; + SourceLoc loc; + + StringSliceLoc() + : name(nullptr) + {} + explicit StringSliceLoc(const UnownedStringSlice& inName) + : name(inName) + {} + StringSliceLoc(const UnownedStringSlice& inName, SourceLoc inLoc) + : name(inName) + , loc(inLoc) + {} + StringSliceLoc(Token const& token) + : loc(token.getLoc()) + { + Name* tokenName = token.getNameOrNull(); + if (tokenName) + { + name = tokenName->text.getUnownedSlice(); + } + } + }; + + // Helper class for iterating over a list of heap-allocated modifiers + struct ModifierList + { + struct Iterator + { + Modifier* current; + + Modifier* operator*() + { + return current; + } + + void operator++(); +#if 0 + { + current = current->next.Ptr(); + } +#endif + + bool operator!=(Iterator other) + { + return current != other.current; + }; + + Iterator() + : current(nullptr) + {} + + Iterator(Modifier* modifier) + : current(modifier) + {} + }; + + ModifierList() + : modifiers(nullptr) + {} + + ModifierList(Modifier* modifiers) + : modifiers(modifiers) + {} + + Iterator begin() { return Iterator(modifiers); } + Iterator end() { return Iterator(nullptr); } + + Modifier* modifiers; + }; + + // Helper class for iterating over heap-allocated modifiers + // of a specific type. + template + struct FilteredModifierList + { + struct Iterator + { + Modifier* current; + + T* operator*() + { + return (T*)current; + } + + void operator++(); + #if 0 + { + current = Adjust(current->next.Ptr()); + } + #endif + + bool operator!=(Iterator other) + { + return current != other.current; + }; + + Iterator() + : current(nullptr) + {} + + Iterator(Modifier* modifier) + : current(modifier) + {} + }; + + FilteredModifierList() + : modifiers(nullptr) + {} + + FilteredModifierList(Modifier* modifiers) + : modifiers(Adjust(modifiers)) + {} + + Iterator begin() { return Iterator(modifiers); } + Iterator end() { return Iterator(nullptr); } + + static Modifier* Adjust(Modifier* modifier); + #if 0 + { + Modifier* m = modifier; + for (;;) + { + if (!m) return m; + if (dynamicCast(m)) return m; + m = m->next.Ptr(); + } + } + #endif + + Modifier* modifiers; + }; + + // A set of modifiers attached to a syntax node + struct Modifiers + { + // The first modifier in the linked list of heap-allocated modifiers + RefPtr first; + + template + FilteredModifierList getModifiersOfType() { return FilteredModifierList(first.Ptr()); } + + // Find the first modifier of a given type, or return `nullptr` if none is found. + template + T* findModifier() + { + return *getModifiersOfType().begin(); + } + + template + bool hasModifier() { return findModifier() != nullptr; } + + FilteredModifierList::Iterator begin() { return FilteredModifierList::Iterator(first.Ptr()); } + FilteredModifierList::Iterator end() { return FilteredModifierList::Iterator(nullptr); } + }; + + class NamedExpressionType; + class GenericDecl; + 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 val); + + /// Represents how much checking has been applied to a declaration. + enum class DeclCheckState : uint8_t + { + /// The declaration has been parsed, but + /// is otherwise completely unchecked. + /// + Unchecked, + + /// Basic checks on the modifiers of the declaration have been applied. + /// + /// For example, when a declaration has attributes, the transformation + /// of an attribute from the parsed-but-unchecked form into a checked + /// form (in which it has the appropriate C++ subclass) happens here. + /// + ModifiersChecked, + + /// The type/signature of the declaration has been checked. + /// + /// For a value declaration like a variable or function, this means that + /// the type of the declaration can be queried. + /// + /// For a type declaration like a `struct` or `typedef` this means + /// that a `Type` referring to that declaration can be formed. + /// + SignatureChecked, + + /// The declaration's basic signature has been checked to the point that + /// it is ready to be referenced in other places. + /// + /// For a function, this means that it has been organized into a + /// "redeclration group" if there are multiple functions with the + /// same name in a scope. + /// + ReadyForReference, + + /// The declaration is ready for lookup operations to be performed. + /// + /// For type declarations (e.g., aggregate types, generic type parameters) + /// this means that any base type or constraint clauses have been + /// sufficiently checked so that we can enumerate the inheritance + /// hierarchy of the type and discover all its members. + /// + ReadyForLookup, + + /// Any conformance declared on the declaration have been validated. + /// + /// In particular, this step means that a "witness table" has been + /// created to show how a type satisfies the requirements of any + /// interfaces it conforms to. + /// + ReadyForConformances, + + /// The declaration is fully checked. + /// + /// This step includes any validation of the declaration that is + /// immaterial to clients code using the declaration, but that is + /// nonetheless relevant to checking correctness. + /// + /// The canonical example here is checking the body of functions. + /// Client code cannot depend on *how* a function is implemented, + /// but we still need to (eventually) check the bodies of all + /// functions, so it belongs in the last phase of checking. + /// + Checked, + + // For convenience at sites that call `ensureDecl()`, we define + // some aliases for the above states that are expressed in terms + // of what client code needs to be able to do with a declaration. + // + // These aliases can be changed over time if we decide to add + // more phases to semantic checking. + + CanEnumerateBases = ReadyForLookup, + CanUseBaseOfInheritanceDecl = ReadyForLookup, + CanUseTypeOfValueDecl = ReadyForReference, + CanUseExtensionTargetType = ReadyForLookup, + CanUseAsType = ReadyForReference, + CanUseFuncSignature = ReadyForReference, + CanSpecializeGeneric = ReadyForReference, + CanReadInterfaceRequirements = ReadyForLookup, + }; + + /// A `DeclCheckState` plus a bit to track whether a declaration is currently being checked. + struct DeclCheckStateExt + { + public: + DeclCheckStateExt() {} + DeclCheckStateExt(DeclCheckState state) + : m_raw(uint8_t(state)) + {} + + enum : uint8_t + { + /// A flag to indicate that a declaration is being checked. + /// + /// The value of this flag is chosen so that it can be + /// represented in the bits of a `DeclCheckState` without + /// colliding with the bits that represent actual states. + /// + kBeingCheckedBit = 0x80, + }; + + DeclCheckState getState() const { return DeclCheckState(m_raw & ~kBeingCheckedBit); } + void setState(DeclCheckState state) + { + m_raw = (m_raw & kBeingCheckedBit) | uint8_t(state); + } + + bool isBeingChecked() const { return (m_raw & kBeingCheckedBit) != 0; } + + void setIsBeingChecked(bool isBeingChecked) + { + m_raw = (m_raw & ~kBeingCheckedBit) + | (isBeingChecked ? kBeingCheckedBit : 0); + } + + bool operator>=(DeclCheckState state) const + { + return getState() >= state; + } + + private: + uint8_t m_raw = 0; + }; + + void addModifier( + RefPtr syntax, + RefPtr modifier); + + struct QualType + { + RefPtr type; + bool IsLeftValue; + + QualType() + : IsLeftValue(false) + {} + + QualType(Type* type) + : type(type) + , IsLeftValue(false) + {} + + Type* Ptr() { return type.Ptr(); } + + operator Type*() { return type; } + operator RefPtr() { return type; } + RefPtr operator->() { return type; } + }; + + struct ReflectClassInfo + { + typedef ReflectClassInfo ThisType; + + typedef void* (*CreateFunc)(); + + /// A constant time implementation of isSubClassOf + SLANG_FORCE_INLINE bool isSubClassOf(const ThisType& super) const + { + // We include super.m_classId, because it's a subclass of itself. + return m_classId >= super.m_classId && m_classId <= super.m_lastClassId; + } + /// Will produce the same result as isSubClassOf, but more slowly by traversing the m_superClass + /// Works without initRange being called. + bool isSubClassOfSlow(const ThisType& super) const; + + uint32_t m_classId; + uint32_t m_lastClassId; + + const ReflectClassInfo* m_superClass; ///< The super class of this class, or nullptr if has no super class. + const char* m_name; ///< Textual class name, for debugging + CreateFunc m_createFunc; ///< Callback to use when creating instances + + struct Infos + { + const ReflectClassInfo* infos[int(ASTNodeType::CountOf)]; + }; + + SLANG_FORCE_INLINE static const ReflectClassInfo* getInfo(ASTNodeType type) { return kInfos.infos[int(type)]; } + + static const Infos kInfos; + }; + + // A reference to a class of syntax node, that can be + // used to create instances on the fly + struct SyntaxClassBase + { + typedef void* (*CreateFunc)(); + + SyntaxClassBase() + {} + + SyntaxClassBase(ReflectClassInfo const* inClassInfo) + : classInfo(inClassInfo) + {} + + void* createInstanceImpl() const + { + auto ci = classInfo; + if (!ci) return nullptr; + + auto cf = ci->m_createFunc; + if (!cf) return nullptr; + + return cf(); + } + + SLANG_FORCE_INLINE bool isSubClassOfImpl(SyntaxClassBase const& super) const { return classInfo->isSubClassOf(*super.classInfo); } + + ReflectClassInfo const* classInfo = nullptr; + }; + + template + struct SyntaxClass : SyntaxClassBase + { + SyntaxClass() + {} + + template + SyntaxClass(SyntaxClass const& other, + typename EnableIf::Value, void>::type* = 0) + : SyntaxClassBase(other.classInfo) + { + } + + T* createInstance() const + { + return (T*)createInstanceImpl(); + } + + SyntaxClass(const ReflectClassInfo* inClassInfo): + SyntaxClassBase(inClassInfo) + {} + + static SyntaxClass getClass() + { + return SyntaxClass(&T::kReflectClassInfo); + } + + template + bool isSubClassOf(SyntaxClass super) + { + return isSubClassOfImpl(super); + } + + template + bool isSubClassOf() + { + return isSubClassOf(SyntaxClass::getClass()); + } + }; + + template + SyntaxClass getClass() + { + return SyntaxClass::getClass(); + } + + struct SubstitutionSet + { + RefPtr substitutions; + operator Substitutions*() const + { + return substitutions; + } + + SubstitutionSet() {} + SubstitutionSet(RefPtr subst) + : substitutions(subst) + { + } + bool Equals(const SubstitutionSet& substSet) const; + int GetHashCode() const; + }; + + template + struct DeclRef; + + // A reference to a declaration, which may include + // substitutions for generic parameters. + struct DeclRefBase + { + typedef Decl DeclType; + + // The underlying declaration + Decl* decl = nullptr; + Decl* getDecl() const { return decl; } + + // Optionally, a chain of substitutions to perform + SubstitutionSet substitutions; + + DeclRefBase() + {} + + DeclRefBase(Decl* decl) + :decl(decl) + {} + + DeclRefBase(Decl* decl, SubstitutionSet subst) + :decl(decl), + substitutions(subst) + {} + + DeclRefBase(Decl* decl, RefPtr subst) + : decl(decl) + , substitutions(subst) + {} + + // Apply substitutions to a type or declaration + RefPtr Substitute(RefPtr type) const; + + DeclRefBase Substitute(DeclRefBase declRef) const; + + // Apply substitutions to an expression + RefPtr Substitute(RefPtr expr) const; + + // Apply substitutions to this declaration reference + DeclRefBase SubstituteImpl(SubstitutionSet subst, int* ioDiff); + + // Returns true if 'as' will return a valid cast + template + bool is() const { return Slang::as(decl) != nullptr; } + + // "dynamic cast" to a more specific declaration reference type + template + DeclRef as() const; + + // Check if this is an equivalent declaration reference to another + bool Equals(DeclRefBase const& declRef) const; + bool operator == (const DeclRefBase& other) const + { + return Equals(other); + } + + // Convenience accessors for common properties of declarations + Name* GetName() const; + SourceLoc getLoc() const; + DeclRefBase GetParent() const; + + int GetHashCode() const; + + // Debugging: + String toString() const; + }; + + template + struct DeclRef : DeclRefBase + { + typedef T DeclType; + + DeclRef() + {} + + DeclRef(T* decl, SubstitutionSet subst) + : DeclRefBase(decl, subst) + {} + + DeclRef(T* decl, RefPtr subst) + : DeclRefBase(decl, SubstitutionSet(subst)) + {} + + template + DeclRef(DeclRef const& other, + typename EnableIf::Value, void>::type* = 0) + : DeclRefBase(other.decl, other.substitutions) + { + } + + T* getDecl() const + { + return (T*)decl; + } + + operator T*() const + { + return getDecl(); + } + + // + static DeclRef unsafeInit(DeclRefBase const& declRef) + { + return DeclRef((T*) declRef.decl, declRef.substitutions); + } + + RefPtr Substitute(RefPtr type) const + { + return DeclRefBase::Substitute(type); + } + RefPtr Substitute(RefPtr expr) const + { + return DeclRefBase::Substitute(expr); + } + + // Apply substitutions to a type or declaration + template + DeclRef Substitute(DeclRef declRef) const + { + return DeclRef::unsafeInit(DeclRefBase::Substitute(declRef)); + } + + // Apply substitutions to this declaration reference + DeclRef SubstituteImpl(SubstitutionSet subst, int* ioDiff) + { + return DeclRef::unsafeInit(DeclRefBase::SubstituteImpl(subst, ioDiff)); + } + + DeclRef GetParent() const + { + return DeclRef::unsafeInit(DeclRefBase::GetParent()); + } + }; + + template + DeclRef DeclRefBase::as() const + { + DeclRef result; + result.decl = Slang::as(decl); + result.substitutions = substitutions; + return result; + } + + template + inline DeclRef makeDeclRef(T* decl) + { + return DeclRef(decl, nullptr); + } + + enum class MemberFilterStyle + { + All, ///< All members + Instance, ///< Only instance members + Static, ///< Only static (ie non instance) members + }; + + const RefPtr* adjustFilterCursorImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filterStyle, const RefPtr* ptr, const RefPtr* end); + const RefPtr* getFilterCursorByIndexImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filterStyle, const RefPtr* ptr, const RefPtr* end, Index index); + Index getFilterCountImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filterStyle, const RefPtr* ptr, const RefPtr* end); + + + template + const RefPtr* adjustFilterCursor(MemberFilterStyle filterStyle, const RefPtr* ptr, const RefPtr* end) + { + return adjustFilterCursorImpl(T::kReflectClassInfo, filterStyle, ptr, end); + } + + /// Finds the element at index. If there is no element at the index (for example has too few elements), returns nullptr. + template + const RefPtr* getFilterCursorByIndex(MemberFilterStyle filterStyle, const RefPtr* ptr, const RefPtr* end, Index index) + { + return getFilterCursorByIndexImpl(T::kReflectClassInfo, filterStyle, ptr, end, index); + } + + template + Index getFilterCount(MemberFilterStyle filterStyle, const RefPtr* ptr, const RefPtr* end) + { + return getFilterCountImpl(T::kReflectClassInfo, filterStyle, ptr, end); + } + + template + bool isFilterNonEmpty(MemberFilterStyle filterStyle, const RefPtr* ptr, const RefPtr* end) + { + return adjustFilterCursorImpl(T::kReflectClassInfo, filterStyle, ptr, end) != end; + } + + template + struct FilteredMemberList + { + typedef RefPtr Element; + + FilteredMemberList() + : m_begin(nullptr) + , m_end(nullptr) + {} + + explicit FilteredMemberList( + List const& list, + MemberFilterStyle filterStyle = MemberFilterStyle::All) + : m_begin(adjustFilterCursor(filterStyle, list.begin(), list.end())) + , m_end(list.end()) + , m_filterStyle(filterStyle) + {} + + struct Iterator + { + const Element* m_cursor; + const Element* m_end; + MemberFilterStyle m_filterStyle; + + bool operator!=(Iterator const& other) const { return m_cursor != other.m_cursor; } + + void operator++() { m_cursor = adjustFilterCursor(m_filterStyle, m_cursor + 1, m_end); } + + const RefPtr& operator*() { return *(RefPtr*)(m_cursor); } + }; + + Iterator begin() + { + Iterator iter = { m_begin, m_end, m_filterStyle }; + return iter; + } + + Iterator end() + { + Iterator iter = { m_end, m_end, m_filterStyle }; + return iter; + } + + // TODO(tfoley): It is ugly to have these. + // We should probably fix the call sites instead. + const RefPtr& getFirst() { return *begin(); } + Index getCount() { return getFilterCount(m_filterStyle, m_begin, m_end); } + + RefPtr operator[](Index index) const + { + const RefPtr* ptr = getFilterCursorByIndex(m_filterStyle, m_begin, m_end, index); + SLANG_ASSERT(ptr); + return *(RefPtr*)(ptr); + } + + /// Returns true if empty (equivalent to getCount() == 0) + bool isEmpty() const + { + /// Note we don't have to scan, because m_begin has already been adjusted, when the FilteredMemberList is constructed + return m_begin == m_end; + } + /// Returns true if non empty (equivalent to getCount() != 0 but faster) + bool isNonEmpty() const { return !isEmpty(); } + + List> toArray() + { + List> result; + for (auto element : (*this)) + { + result.add(element); + } + return result; + } + + const Element* m_begin; ///< Is either equal to m_end, or points to first *valid* filtered member + const Element* m_end; + MemberFilterStyle m_filterStyle; + }; + + struct TransparentMemberInfo + { + // The declaration of the transparent member + Decl* decl; + }; + + template + struct FilteredMemberRefList + { + List> const& m_decls; + SubstitutionSet m_substitutions; + MemberFilterStyle m_filterStyle; + + FilteredMemberRefList( + List> const& decls, + SubstitutionSet substitutions, + MemberFilterStyle filterStyle = MemberFilterStyle::All) + : m_decls(decls) + , m_substitutions(substitutions) + , m_filterStyle(filterStyle) + {} + + Index getCount() const { return getFilterCount(m_filterStyle, m_decls.begin(), m_decls.end()); } + + /// True if empty (equivalent to getCount == 0, but faster) + bool isEmpty() const { return !isNonEmpty(); } + /// True if non empty (equivalent to getCount() != 0 but faster) + bool isNonEmpty() const { return isFilterNonEmpty(m_filterStyle, m_decls.begin(), m_decls.end()); } + + DeclRef operator[](Index index) const + { + const RefPtr* decl = getFilterCursorByIndex(m_filterStyle, m_decls.begin(), m_decls.end(), index); + SLANG_ASSERT(decl); + return DeclRef((T*) decl->Ptr(), m_substitutions); + } + + List> toArray() const + { + List> result; + for (auto d : *this) + result.add(d); + return result; + } + + struct Iterator + { + FilteredMemberRefList const* m_list; + const RefPtr* m_ptr; + const RefPtr* m_end; + MemberFilterStyle m_filterStyle; + + Iterator() : m_list(nullptr), m_ptr(nullptr), m_filterStyle(MemberFilterStyle::All) {} + Iterator( + FilteredMemberRefList const* list, + const RefPtr* ptr, + const RefPtr* end, + MemberFilterStyle filterStyle + ) + : m_list(list) + , m_ptr(ptr) + , m_end(end) + , m_filterStyle(filterStyle) + {} + + bool operator!=(const Iterator& other) const { return m_ptr != other.m_ptr; } + + void operator++() { m_ptr = adjustFilterCursor(m_filterStyle, m_ptr + 1, m_end); } + + DeclRef operator*() { return DeclRef((T*) m_ptr->Ptr(), m_list->m_substitutions); } + }; + + Iterator begin() const { return Iterator(this, adjustFilterCursor(m_filterStyle, m_decls.begin(), m_decls.end()), m_decls.end(), m_filterStyle); } + Iterator end() const { return Iterator(this, m_decls.end(), m_decls.end(), m_filterStyle); } + }; + + // + // type Expressions + // + + // A "type expression" is a term that we expect to resolve to a type during checking. + // We store both the original syntax and the resolved type here. + struct TypeExp + { + TypeExp() {} + TypeExp(TypeExp const& other) + : exp(other.exp) + , type(other.type) + {} + explicit TypeExp(RefPtr exp) + : exp(exp) + {} + explicit TypeExp(RefPtr type) + : type(type) + {} + TypeExp(RefPtr exp, RefPtr type) + : exp(exp) + , type(type) + {} + + RefPtr exp; + RefPtr type; + + bool Equals(Type* other); +#if 0 + { + return type->Equals(other); + } +#endif + bool Equals(RefPtr other); +#if 0 + { + return type->Equals(other.Ptr()); + } +#endif + Type* Ptr() { return type.Ptr(); } + operator Type*() + { + return type; + } + Type* operator->() { return Ptr(); } + + TypeExp Accept(SyntaxVisitor* visitor); + }; + + + + struct Scope : public RefObject + { + // The parent of this scope (where lookup should go if nothing is found locally) + RefPtr parent; + + // The next sibling of this scope (a peer for lookup) + RefPtr nextSibling; + + // The container to use for lookup + // + // Note(tfoley): This is kept as an unowned pointer + // so that a scope can't keep parts of the AST alive, + // but the opposite it allowed. + ContainerDecl* containerDecl; + }; + + // Masks to be applied when lookup up declarations + enum class LookupMask : uint8_t + { + type = 0x1, + Function = 0x2, + Value = 0x4, + Attribute = 0x8, + + Default = type | Function | Value, + }; + + // Represents one item found during lookup + struct LookupResultItem + { + // Sometimes lookup finds an item, but there were additional + // "hops" taken to reach it. We need to remember these steps + // so that if/when we consturct a full expression we generate + // appropriate AST nodes for all the steps. + // + // We build up a list of these "breadcrumbs" while doing + // lookup, and store them alongside each item found. + // + // As an example, suppose we have an HLSL `cbuffer` declaration: + // + // cbuffer C { float4 f; } + // + // This is syntax sugar for a global-scope variable of + // type `ConstantBuffer` where `T` is a `struct` containing + // all the members: + // + // struct Anon0 { float4 f; }; + // __transparent ConstantBuffer anon1; + // + // The `__transparent` modifier there captures the fact that + // when somebody writes `f` in their code, they expect it to + // "see through" the `cbuffer` declaration (or the global variable, + // in this case) and find the member inside. + // + // But when the user writes `f` we can't just create a simple + // `VarExpr` that refers directly to that field, because that + // doesn't actually reflect the required steps in a way that + // code generation can use. + // + // Instead we need to construct an expression like `(*anon1).f`, + // where there is are two additional steps in the process: + // + // 1. We needed to dereference the pointer-like type `ConstantBuffer` + // to get at a value of type `Anon0` + // 2. We needed to access a sub-field of the aggregate type `Anon0` + // + // We *could* just create these full-formed expressions during + // lookup, but this might mean creating a large number of + // AST nodes in cases where the user calls an overloaded function. + // At the very least we'd rather not heap-allocate in the common + // case where no "extra" steps need to be performed to get to + // the declarations. + // + // This is where "breadcrumbs" come in. A breadcrumb represents + // an extra "step" that must be performed to turn a declaration + // found by lookup into a valid expression to splice into the + // AST. Most of the time lookup result items don't have any + // breadcrumbs, so that no extra heap allocation takes place. + // When an item does have breadcrumbs, and it is chosen as + // the unique result (perhaps by overload resolution), then + // we can walk the list of breadcrumbs to create a full + // expression. + class Breadcrumb : public RefObject + { + public: + enum class Kind : uint8_t + { + // The lookup process looked "through" an in-scope + // declaration to the fields inside of it, so that + // even if lookup started with a simple name `f`, + // it needs to result in a member expression `obj.f`. + Member, + + // The lookup process took a pointer(-like) value, and then + // proceeded to derefence it and look at the thing(s) + // it points to instead, so that the final expression + // needs to have `(*obj)` + Deref, + + // The lookup process saw a value `obj` of type `T` and + // took into account an in-scope constraint that says + // `T` is a subtype of some other type `U`, so that + // lookup was able to find a member through type `U` + // instead. + Constraint, + + // The lookup process considered a member of an + // enclosing type as being in scope, so that any + // reference to that member needs to use a `this` + // expression as appropriate. + This, + }; + + // The kind of lookup step that was performed + Kind kind; + + // For the `Kind::This` case, what does the implicit + // `this` or `This` parameter refer to? + // + enum class ThisParameterMode : uint8_t + { + ImmutableValue, // An immutable `this` value + MutableValue, // A mutable `this` value + Type, // A `This` type + + Default = ImmutableValue, + }; + ThisParameterMode thisParameterMode = ThisParameterMode::Default; + + // As needed, a reference to the declaration that faciliated + // the lookup step. + // + // For a `Member` lookup step, this is the declaration whose + // members were implicitly pulled into scope. + // + // For a `Constraint` lookup step, this is the `ConstraintDecl` + // that serves to witness the subtype relationship. + // + DeclRef declRef; + + // The next implicit step that the lookup process took to + // arrive at a final value. + RefPtr next; + + Breadcrumb( + Kind kind, + DeclRef declRef, + RefPtr next, + ThisParameterMode thisParameterMode = ThisParameterMode::Default) + : kind(kind) + , thisParameterMode(thisParameterMode) + , declRef(declRef) + , next(next) + {} + }; + + // A properly-specialized reference to the declaration that was found. + DeclRef declRef; + + // Any breadcrumbs needed in order to turn that declaration + // reference into a well-formed expression. + // + // This is unused in the simple case where a declaration + // is being referenced directly (rather than through + // transparent members). + RefPtr breadcrumbs; + + LookupResultItem() = default; + explicit LookupResultItem(DeclRef declRef) + : declRef(declRef) + {} + LookupResultItem(DeclRef declRef, RefPtr breadcrumbs) + : declRef(declRef) + , breadcrumbs(breadcrumbs) + {} + }; + + + // Result of looking up a name in some lexical/semantic environment. + // Can be used to enumerate all the declarations matching that name, + // in the case where the result is overloaded. + struct LookupResult + { + // The one item that was found, in the smple case + LookupResultItem item; + + // All of the items that were found, in the complex case. + // Note: if there was no overloading, then this list isn't + // used at all, to avoid allocation. + List items; + + // Was at least one result found? + bool isValid() const { return item.declRef.getDecl() != nullptr; } + + bool isOverloaded() const { return items.getCount() > 1; } + + Name* getName() const + { + return items.getCount() > 1 ? items[0].declRef.GetName() : item.declRef.GetName(); + } + LookupResultItem* begin() + { + if (isValid()) + { + if (isOverloaded()) + return items.begin(); + else + return &item; + } + else + return nullptr; + } + LookupResultItem* end() + { + if (isValid()) + { + if (isOverloaded()) + return items.end(); + else + return &item + 1; + } + else + return nullptr; + } + }; + + struct SemanticsVisitor; + + struct LookupRequest + { + SemanticsVisitor* semantics = nullptr; + RefPtr scope = nullptr; + RefPtr endScope = nullptr; + + LookupMask mask = LookupMask::Default; + }; + + struct WitnessTable; + + // A value that witnesses the satisfaction of an interface + // requirement by a particular declaration or value. + struct RequirementWitness + { + RequirementWitness() + : m_flavor(Flavor::none) + {} + + RequirementWitness(DeclRef declRef) + : m_flavor(Flavor::declRef) + , m_declRef(declRef) + {} + + RequirementWitness(RefPtr val); + + RequirementWitness(RefPtr witnessTable); + + enum class Flavor + { + none, + declRef, + val, + witnessTable, + }; + + Flavor getFlavor() + { + return m_flavor; + } + + DeclRef getDeclRef() + { + SLANG_ASSERT(getFlavor() == Flavor::declRef); + return m_declRef; + } + + RefPtr getVal() + { + SLANG_ASSERT(getFlavor() == Flavor::val); + return m_obj.as(); + } + + RefPtr getWitnessTable(); + + RequirementWitness specialize(SubstitutionSet const& subst); + + Flavor m_flavor; + DeclRef m_declRef; + RefPtr m_obj; + + }; + + typedef Dictionary RequirementDictionary; + + struct WitnessTable : RefObject + { + RequirementDictionary requirementDictionary; + }; + + typedef Dictionary> AttributeArgumentValueDict; + + struct SpecializationParam + { + enum class Flavor + { + GenericType, + GenericValue, + ExistentialType, + ExistentialValue, + }; + Flavor flavor; + SourceLoc loc; + RefPtr object; + }; + typedef List SpecializationParams; + + struct SpecializationArg + { + RefPtr val; + }; + typedef List SpecializationArgs; + + struct ExpandedSpecializationArg : SpecializationArg + { + RefPtr witness; + }; + typedef List ExpandedSpecializationArgs; + +} // namespace Slang + +#endif diff --git a/source/slang/slang-ast-type.h b/source/slang/slang-ast-type.h new file mode 100644 index 000000000..454b7228e --- /dev/null +++ b/source/slang/slang-ast-type.h @@ -0,0 +1,690 @@ +// slang-ast-type.h + +#pragma once + +#include "slang-ast-base.h" + +namespace Slang { + +#define SLANG_ABSTRACT_CLASS(x) SLANG_ABSTRACT_CLASS_REFLECT(x) +#define SLANG_CLASS(x) SLANG_CLASS_REFLECT_WITH_ACCEPT(x) + +// Syntax class definitions for types. + +// The type of a reference to an overloaded name +class OverloadGroupType : public Type +{ + SLANG_CLASS(OverloadGroupType) + +public: + virtual String ToString() override; + +protected: + virtual bool EqualsImpl(Type * type) override; + virtual RefPtr 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 Type +{ + SLANG_CLASS(InitializerListType) + + virtual String ToString() override; + +protected: + virtual bool EqualsImpl(Type * type) override; + virtual RefPtr CreateCanonicalType() override; + virtual int GetHashCode() override; +}; + +// The type of an expression that was erroneous +class ErrorType : public Type +{ + SLANG_CLASS(ErrorType) + +public: + virtual String ToString() override; + +protected: + virtual bool EqualsImpl(Type * type) override; + virtual RefPtr SubstituteImpl(SubstitutionSet subst, int* ioDiff) override; + virtual RefPtr CreateCanonicalType() override; + virtual int GetHashCode() override; +}; + +// A type that takes the form of a reference to some declaration +class DeclRefType : public Type +{ + SLANG_CLASS(DeclRefType) + + DeclRef declRef; + + virtual String ToString() override; + virtual RefPtr SubstituteImpl(SubstitutionSet subst, int* ioDiff) override; + + static RefPtr Create( + Session* session, + DeclRef declRef); + + DeclRefType() + {} + DeclRefType( + DeclRef declRef) + : declRef(declRef) + {} +protected: + virtual int GetHashCode() override; + virtual bool EqualsImpl(Type * type) override; + virtual RefPtr CreateCanonicalType() override; +}; + +// Base class for types that can be used in arithmetic expressions +class ArithmeticExpressionType : public DeclRefType +{ + SLANG_ABSTRACT_CLASS(ArithmeticExpressionType) + +public: + virtual BasicExpressionType* GetScalarType() = 0; +}; + +class BasicExpressionType : public ArithmeticExpressionType +{ + SLANG_CLASS(BasicExpressionType) + + + BaseType baseType; + + BasicExpressionType() {} + BasicExpressionType( + Slang::BaseType baseType) + : baseType(baseType) + {} +protected: + virtual BasicExpressionType* GetScalarType() override; + virtual bool EqualsImpl(Type * type) override; + virtual RefPtr CreateCanonicalType() override; + +}; + +// Base type for things that are built in to the compiler, +// and will usually have special behavior or a custom +// mapping to the IR level. +class BuiltinType : public DeclRefType +{ + SLANG_ABSTRACT_CLASS(BuiltinType) + +}; + +// Resources that contain "elements" that can be fetched +class ResourceType : public BuiltinType +{ + SLANG_ABSTRACT_CLASS(ResourceType) + + // The type that results from fetching an element from this resource + RefPtr elementType; + + // Shape and access level information for this resource type + TextureFlavor flavor; + + TextureFlavor::Shape GetBaseShape() + { + return flavor.GetBaseShape(); + } + bool isMultisample() { return flavor.isMultisample(); } + bool isArray() { return flavor.isArray(); } + SlangResourceShape getShape() const { return flavor.getShape(); } + SlangResourceAccess getAccess() { return flavor.getAccess(); } +}; + +class TextureTypeBase : public ResourceType +{ + SLANG_ABSTRACT_CLASS(TextureTypeBase) + + TextureTypeBase() + {} + TextureTypeBase( + TextureFlavor flavor, + RefPtr elementType) + { + this->elementType = elementType; + this->flavor = flavor; + } +}; + +class TextureType : public TextureTypeBase +{ + SLANG_CLASS(TextureType) + + TextureType() + {} + TextureType( + TextureFlavor flavor, + RefPtr elementType) + : TextureTypeBase(flavor, elementType) + {} +}; + +// This is a base type for texture/sampler pairs, +// as they exist in, e.g., GLSL +class TextureSamplerType : public TextureTypeBase +{ + SLANG_CLASS(TextureSamplerType) + + TextureSamplerType() + {} + TextureSamplerType( + TextureFlavor flavor, + RefPtr elementType) + : TextureTypeBase(flavor, elementType) + {} +}; + +// This is a base type for `image*` types, as they exist in GLSL +class GLSLImageType : public TextureTypeBase +{ + SLANG_CLASS(GLSLImageType) + + GLSLImageType() + {} + GLSLImageType( + TextureFlavor flavor, + RefPtr elementType) + : TextureTypeBase(flavor, elementType) + {} +}; + +class SamplerStateType : public BuiltinType +{ + SLANG_CLASS(SamplerStateType) + + // What flavor of sampler state is this + SamplerStateFlavor flavor; +}; + +// Other cases of generic types known to the compiler +class BuiltinGenericType : public BuiltinType +{ + SLANG_CLASS(BuiltinGenericType) + + RefPtr elementType; + + Type* getElementType() { return 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 +{ + SLANG_CLASS(PointerLikeType) +}; + + +// HLSL buffer-type resources + +class HLSLStructuredBufferTypeBase : public BuiltinGenericType +{ + SLANG_CLASS(HLSLStructuredBufferTypeBase) +}; + +class HLSLStructuredBufferType : public HLSLStructuredBufferTypeBase +{ + SLANG_CLASS(HLSLStructuredBufferType) +}; + +class HLSLRWStructuredBufferType : public HLSLStructuredBufferTypeBase +{ + SLANG_CLASS(HLSLRWStructuredBufferType) +}; + +class HLSLRasterizerOrderedStructuredBufferType : public HLSLStructuredBufferTypeBase +{ + SLANG_CLASS(HLSLRasterizerOrderedStructuredBufferType) +}; + + +class UntypedBufferResourceType : public BuiltinType +{ + SLANG_CLASS(UntypedBufferResourceType) +}; + +class HLSLByteAddressBufferType : public UntypedBufferResourceType +{ + SLANG_CLASS(HLSLByteAddressBufferType) +}; + +class HLSLRWByteAddressBufferType : public UntypedBufferResourceType +{ + SLANG_CLASS(HLSLRWByteAddressBufferType) +}; + +class HLSLRasterizerOrderedByteAddressBufferType : public UntypedBufferResourceType +{ + SLANG_CLASS(HLSLRasterizerOrderedByteAddressBufferType) +}; + +class RaytracingAccelerationStructureType : public UntypedBufferResourceType +{ + SLANG_CLASS(RaytracingAccelerationStructureType) +}; + + +class HLSLAppendStructuredBufferType : public HLSLStructuredBufferTypeBase +{ + SLANG_CLASS(HLSLAppendStructuredBufferType) +}; + +class HLSLConsumeStructuredBufferType : public HLSLStructuredBufferTypeBase +{ + SLANG_CLASS(HLSLConsumeStructuredBufferType) +}; + + +class HLSLPatchType : public BuiltinType +{ + SLANG_CLASS(HLSLPatchType) + + Type* getElementType(); + IntVal* getElementCount(); +}; + +class HLSLInputPatchType : public HLSLPatchType +{ + SLANG_CLASS(HLSLInputPatchType) +}; + +class HLSLOutputPatchType : public HLSLPatchType +{ + SLANG_CLASS(HLSLOutputPatchType) +}; + + +// HLSL geometry shader output stream types + +class HLSLStreamOutputType : public BuiltinGenericType +{ + SLANG_CLASS(HLSLStreamOutputType) +}; + +class HLSLPointStreamType : public HLSLStreamOutputType +{ + SLANG_CLASS(HLSLPointStreamType) +}; + +class HLSLLineStreamType : public HLSLStreamOutputType +{ + SLANG_CLASS(HLSLLineStreamType) +}; + +class HLSLTriangleStreamType : public HLSLStreamOutputType +{ + SLANG_CLASS(HLSLTriangleStreamType) +}; + + +// +class GLSLInputAttachmentType : public BuiltinType +{ + SLANG_CLASS(GLSLInputAttachmentType) +}; + + +// Base class for types used when desugaring parameter block +// declarations, includeing HLSL `cbuffer` or GLSL `uniform` blocks. +class ParameterGroupType : public PointerLikeType +{ + SLANG_CLASS(ParameterGroupType) +}; + +class UniformParameterGroupType : public ParameterGroupType +{ + SLANG_CLASS(UniformParameterGroupType) +}; + +class VaryingParameterGroupType : public ParameterGroupType +{ + SLANG_CLASS(VaryingParameterGroupType) +}; + + +// type for HLSL `cbuffer` declarations, and `ConstantBuffer` +// ALso used for GLSL `uniform` blocks. +class ConstantBufferType : public UniformParameterGroupType +{ + SLANG_CLASS(ConstantBufferType) +}; + + +// type for HLSL `tbuffer` declarations, and `TextureBuffer` +class TextureBufferType : public UniformParameterGroupType +{ + SLANG_CLASS(TextureBufferType) +}; + + +// type for GLSL `in` and `out` blocks +class GLSLInputParameterGroupType : public VaryingParameterGroupType +{ + SLANG_CLASS(GLSLInputParameterGroupType) +}; + +class GLSLOutputParameterGroupType : public VaryingParameterGroupType +{ + SLANG_CLASS(GLSLOutputParameterGroupType) +}; + + +// type for GLLSL `buffer` blocks +class GLSLShaderStorageBufferType : public UniformParameterGroupType +{ + SLANG_CLASS(GLSLShaderStorageBufferType) +}; + + +// type for Slang `ParameterBlock` type +class ParameterBlockType : public UniformParameterGroupType +{ + SLANG_CLASS(ParameterBlockType) +}; + +class ArrayExpressionType : public Type +{ + SLANG_CLASS(ArrayExpressionType) + + RefPtr baseType; + RefPtr ArrayLength; + + virtual Slang::String ToString() override; + +protected: + virtual bool EqualsImpl(Type * type) override; + virtual RefPtr CreateCanonicalType() override; + virtual RefPtr SubstituteImpl(SubstitutionSet subst, int* ioDiff) 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 Type +{ + SLANG_CLASS(TypeType) + + // The type that this is the type of... + RefPtr type; + +public: + TypeType() + {} + TypeType(RefPtr type) + : type(type) + {} + + virtual String ToString() override; + +protected: + virtual bool EqualsImpl(Type * type) override; + virtual RefPtr CreateCanonicalType() override; + virtual int GetHashCode() override; +}; + +// A vector type, e.g., `vector` +class VectorExpressionType : public ArithmeticExpressionType +{ + SLANG_CLASS(VectorExpressionType) + + // The type of vector elements. + // As an invariant, this should be a basic type or an alias. + RefPtr elementType; + + // The number of elements + RefPtr elementCount; + + virtual String ToString() override; + +protected: + virtual BasicExpressionType* GetScalarType() override; +}; + +// A matrix type, e.g., `matrix` +class MatrixExpressionType : public ArithmeticExpressionType +{ + SLANG_CLASS(MatrixExpressionType) + + Type* getElementType(); + IntVal* getRowCount(); + IntVal* getColumnCount(); + + RefPtr getRowType(); + + virtual String ToString() override; + +protected: + virtual BasicExpressionType* GetScalarType() override; + +private: + RefPtr mRowType; +}; + +// The built-in `String` type +class StringType : public BuiltinType +{ + SLANG_CLASS(StringType) +}; + + +// Type built-in `__EnumType` type +class EnumTypeType : public BuiltinType +{ + SLANG_CLASS(EnumTypeType) + // TODO: provide accessors for the declaration, the "tag" type, etc. +}; + +// Base class for types that map down to +// simple pointers as part of code generation. +class PtrTypeBase : public BuiltinType +{ + SLANG_CLASS(PtrTypeBase) + + // Get the type of the pointed-to value. + Type* getValueType(); +}; + +// A true (user-visible) pointer type, e.g., `T*` +class PtrType : public PtrTypeBase +{ + SLANG_CLASS(PtrType) +}; + +// A type that represents the behind-the-scenes +// logical pointer that is passed for an `out` +// or `in out` parameter +class OutTypeBase : public PtrTypeBase +{ + SLANG_CLASS(OutTypeBase) +}; + +// The type for an `out` parameter, e.g., `out T` +class OutType : public OutTypeBase +{ + SLANG_CLASS(OutType) +}; + +// The type for an `in out` parameter, e.g., `in out T` +class InOutType : public OutTypeBase +{ + SLANG_CLASS(InOutType) +}; + +// The type for an `ref` parameter, e.g., `ref T` +class RefType : public PtrTypeBase +{ + SLANG_CLASS(RefType) +}; + +// A type alias of some kind (e.g., via `typedef`) +class NamedExpressionType : public Type +{ + SLANG_CLASS(NamedExpressionType) + + DeclRef declRef; + + RefPtr innerType; + NamedExpressionType() + {} + NamedExpressionType( + DeclRef declRef) + : declRef(declRef) + {} + + virtual String ToString() override; + +protected: + virtual bool EqualsImpl(Type * type) override; + virtual RefPtr CreateCanonicalType() override; + virtual int GetHashCode() override; +}; + +// A function type is defined by its parameter types +// and its result type. +class FuncType : public Type +{ + SLANG_CLASS(FuncType) + + // TODO: We may want to preserve parameter names + // in the list here, just so that we can print + // out friendly names when printing a function + // type, even if they don't affect the actual + // semantic type underneath. + + List> paramTypes; + RefPtr resultType; + + FuncType() + {} + + UInt getParamCount() { return paramTypes.getCount(); } + Type* getParamType(UInt index) { return paramTypes[index]; } + Type* getResultType() { return resultType; } + + virtual String ToString() override; +protected: + virtual RefPtr SubstituteImpl(SubstitutionSet subst, int* ioDiff) override; + virtual bool EqualsImpl(Type * type) override; + virtual RefPtr CreateCanonicalType() override; + virtual int GetHashCode() override; +}; + +// The "type" of an expression that names a generic declaration. +class GenericDeclRefType : public Type +{ + SLANG_CLASS(GenericDeclRefType) + + DeclRef declRef; + + GenericDeclRefType() + {} + GenericDeclRefType( + DeclRef declRef) + : declRef(declRef) + {} + + DeclRef const& GetDeclRef() const { return declRef; } + + virtual String ToString() override; + +protected: + virtual bool EqualsImpl(Type * type) override; + virtual int GetHashCode() override; + virtual RefPtr CreateCanonicalType() override; +}; + +// The "type" of a reference to a module or namespace +class NamespaceType : public Type +{ + SLANG_CLASS(NamespaceType) + + DeclRef m_declRef; + + NamespaceType() + {} + + DeclRef const& getDeclRef() const { return m_declRef; } + + virtual String ToString() override; + +protected: + virtual bool EqualsImpl(Type * type) override; + virtual int GetHashCode() override; + virtual RefPtr CreateCanonicalType() override; +}; + +// The concrete type for a value wrapped in an existential, accessible +// when the existential is "opened" in some context. +class ExtractExistentialType : public Type +{ + SLANG_CLASS(ExtractExistentialType) + + DeclRef declRef; + + virtual String ToString() override; + virtual bool EqualsImpl(Type * type) override; + virtual int GetHashCode() override; + virtual RefPtr CreateCanonicalType() override; + virtual RefPtr SubstituteImpl(SubstitutionSet subst, int* ioDiff) override; +}; + + /// A tagged union of zero or more other types. +class TaggedUnionType : public Type +{ + SLANG_CLASS(TaggedUnionType) + + /// The distinct "cases" the tagged union can store. + /// + /// For each type in this array, the array index is the + /// tag value for that case. + /// + List> caseTypes; + + virtual String ToString() override; + virtual bool EqualsImpl(Type * type) override; + virtual int GetHashCode() override; + virtual RefPtr CreateCanonicalType() override; + virtual RefPtr SubstituteImpl(SubstitutionSet subst, int* ioDiff) override; +}; + +class ExistentialSpecializedType : public Type +{ + SLANG_CLASS(ExistentialSpecializedType) + + RefPtr baseType; + ExpandedSpecializationArgs args; + + virtual String ToString() override; + virtual bool EqualsImpl(Type * type) override; + virtual int GetHashCode() override; + virtual RefPtr CreateCanonicalType() override; + virtual RefPtr SubstituteImpl(SubstitutionSet subst, int* ioDiff) override; +}; + + /// The type of `this` within a polymorphic declaration +class ThisType : public Type +{ + SLANG_CLASS(ThisType) + + DeclRef interfaceDeclRef; + + virtual String ToString() override; + virtual bool EqualsImpl(Type * type) override; + virtual int GetHashCode() override; + virtual RefPtr CreateCanonicalType() override; + virtual RefPtr SubstituteImpl(SubstitutionSet subst, int* ioDiff) override; + +}; + +#undef SLANG_ABSTRACT_CLASS +#undef SLANG_CLASS + +} // namespace Slang diff --git a/source/slang/slang-ast-val.h b/source/slang/slang-ast-val.h new file mode 100644 index 000000000..a47acc92d --- /dev/null +++ b/source/slang/slang-ast-val.h @@ -0,0 +1,206 @@ +// slang-ast-val.h + +#pragma once + +#include "slang-ast-base.h" + +namespace Slang { + +#define SLANG_ABSTRACT_CLASS(x) SLANG_ABSTRACT_CLASS_REFLECT(x) +#define SLANG_CLASS(x) SLANG_CLASS_REFLECT_WITH_ACCEPT(x) + +// Syntax class definitions for compile-time values. + +// A compile-time integer (may not have a specific concrete value) +class IntVal : public Val +{ + SLANG_ABSTRACT_CLASS(IntVal) +}; + +// Trivial case of a value that is just a constant integer +class ConstantIntVal : public IntVal +{ + SLANG_CLASS(ConstantIntVal) + + IntegerLiteralValue value; + + ConstantIntVal() + {} + ConstantIntVal(IntegerLiteralValue value) + : value(value) + {} + + virtual bool EqualsVal(Val* val) override; + virtual String ToString() override; + virtual int GetHashCode() override; +}; + +// The logical "value" of a rererence to a generic value parameter +class GenericParamIntVal : public IntVal +{ + SLANG_CLASS(GenericParamIntVal) + + DeclRef declRef; + + GenericParamIntVal() + {} + GenericParamIntVal(DeclRef declRef) + : declRef(declRef) + {} + + virtual bool EqualsVal(Val* val) override; + virtual String ToString() override; + virtual int GetHashCode() override; + virtual RefPtr SubstituteImpl(SubstitutionSet subst, int* ioDiff) override; +}; + + /// An unknown integer value indicating an erroneous sub-expression +class ErrorIntVal : public IntVal +{ + SLANG_CLASS(ErrorIntVal) + + // TODO: We should probably eventually just have an `ErrorVal` here + // and have all `Val`s that represent ordinary values hold their + // `Type` so that we can have an `ErrorVal` of any type. + + ErrorIntVal() + {} + + virtual bool EqualsVal(Val* val) override; + virtual String ToString() override; + virtual int GetHashCode() override; + virtual RefPtr SubstituteImpl(SubstitutionSet subst, int* ioDiff) override; +}; + +// A witness to the fact that some proposition is true, encoded +// at the level of the type system. +// +// Given a generic like: +// +// void example(L light) +// where L : ILight +// { ... } +// +// a call to `example()` needs two things for us to be sure +// it is valid: +// +// 1. We need a type `X` to use as the argument for the +// parameter `L`. We might supply this explicitly, or +// via inference. +// +// 2. We need a *proof* that whatever `X` we chose conforms +// to the `ILight` interface. +// +// The easiest way to make such a proof is by construction, +// and a `Witness` represents such a constructive proof. +// Conceptually a proposition like `X : ILight` can be +// seen as a type, and witness prooving that proposition +// is a value of that type. +// +// We construct and store witnesses explicitly during +// semantic checking because they can help us with +// generating downstream code. By following the structure +// of a witness (the structure of a proof) we can, e.g., +// navigate from the knowledge that `X : ILight` to +// the concrete declarations that provide the implementation +// of `ILight` for `X`. +// +class Witness : public Val +{ + SLANG_ABSTRACT_CLASS(Witness) +}; + +// A witness that one type is a subtype of another +// (where by "subtype" we include both inheritance +// relationships and type-conforms-to-interface relationships) +// +// TODO: we may need to tease those apart. +class SubtypeWitness : public Witness +{ + SLANG_ABSTRACT_CLASS(SubtypeWitness) + + RefPtr sub; + RefPtr sup; +}; + +class TypeEqualityWitness : public SubtypeWitness +{ + SLANG_CLASS(TypeEqualityWitness) + + + virtual bool EqualsVal(Val* val) override; + virtual String ToString() override; + virtual int GetHashCode() override; + virtual RefPtr SubstituteImpl(SubstitutionSet subst, int * ioDiff) override; +}; + +// A witness that one type is a subtype of another +// because some in-scope declaration says so +class DeclaredSubtypeWitness : public SubtypeWitness +{ + SLANG_CLASS(DeclaredSubtypeWitness) + + DeclRef declRef; + + virtual bool EqualsVal(Val* val) override; + virtual String ToString() override; + virtual int GetHashCode() override; + virtual RefPtr SubstituteImpl(SubstitutionSet subst, int * ioDiff) override; +}; + +// A witness that `sub : sup` because `sub : mid` and `mid : sup` +class TransitiveSubtypeWitness : public SubtypeWitness +{ + SLANG_CLASS(TransitiveSubtypeWitness) + + // Witness that `sub : mid` + RefPtr subToMid; + + // Witness that `mid : sup` + DeclRef midToSup; + + virtual bool EqualsVal(Val* val) override; + virtual String ToString() override; + virtual int GetHashCode() override; + virtual RefPtr SubstituteImpl(SubstitutionSet subst, int * ioDiff) override; +}; + +// A witness taht `sub : sup` because `sub` was wrapped into +// an existential of type `sup`. +class ExtractExistentialSubtypeWitness : public SubtypeWitness +{ + SLANG_CLASS(ExtractExistentialSubtypeWitness) + + // The declaration of the existential value that has been opened + DeclRef declRef; + + virtual bool EqualsVal(Val* val) override; + virtual String ToString() override; + virtual int GetHashCode() override; + virtual RefPtr SubstituteImpl(SubstitutionSet subst, int * ioDiff) override; +}; + +// A witness that `sub : sup`, because `sub` is a tagged union +// of the form `A | B | C | ...` and each of `A : sup`, +// `B : sup`, `C : sup`, etc. +// +class TaggedUnionSubtypeWitness : public SubtypeWitness +{ + SLANG_CLASS(TaggedUnionSubtypeWitness) + + // Witnesses that each of the "case" types in the union + // is a subtype of `sup`. + // + List> caseWitnesses; + + virtual bool EqualsVal(Val* val) override; + virtual String ToString() override; + virtual int GetHashCode() override; + virtual RefPtr SubstituteImpl(SubstitutionSet subst, int * ioDiff) override; +}; + + +#undef SLANG_ABSTRACT_CLASS +#undef SLANG_CLASS + +} // namespace Slang diff --git a/source/slang/slang-decl-defs.h b/source/slang/slang-decl-defs.h deleted file mode 100644 index 7dc58539c..000000000 --- a/source/slang/slang-decl-defs.h +++ /dev/null @@ -1,345 +0,0 @@ -// slang-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>, decls) -END_SYNTAX_CLASS() - -// A "container" decl is a parent to other declarations -ABSTRACT_SYNTAX_CLASS(ContainerDecl, Decl) - SYNTAX_FIELD(List>, Members) - - RAW( - template - FilteredMemberList getMembersOfType() - { - return FilteredMemberList(Members); - } - - bool isMemberDictionaryValid() const { return dictionaryLastCount == Members.getCount(); } - - void invalidateMemberDictionary() { dictionaryLastCount = -1; } - - // Denotes how much of Members has been placed into the dictionary/transparentMembers. - // If this value equals the Members.getCount(), the dictionary is completely full and valid. - // If it's >= 0, then the Members after dictionaryLastCount are all that need to be added. - // If it < 0 it means that the dictionary/transparentMembers is invalid and needs to be recreated. - Index dictionaryLastCount = 0; - - // Dictionary for looking up members by name. - // This is built on demand before performing lookup. - Dictionary memberDictionary; - - // A list of transparent members, to be used in lookup - // Note: this is only valid if `memberDictionaryIsValid` is true - List transparentMembers; - ) -END_SYNTAX_CLASS() - -// Base class for all variable declarations -ABSTRACT_SYNTAX_CLASS(VarDeclBase, Decl) - - // type of the variable - SYNTAX_FIELD(TypeExp, type) - - RAW( - Type* getType() { return type.type.Ptr(); } - ) - - // Initializer expression (optional) - SYNTAX_FIELD(RefPtr, initExpr) -END_SYNTAX_CLASS() - -// Ordinary potentially-mutable variables (locals, globals, and member variables) -SYNTAX_CLASS(VarDecl, VarDeclBase) -END_SYNTAX_CLASS() - -// A variable declaration that is always immutable (whether local, global, or member variable) -SYNTAX_CLASS(LetDecl, VarDecl) -END_SYNTAX_CLASS() - -// 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 GetFields() - { - return getMembersOfType(); - } - ) -END_SYNTAX_CLASS() - -SIMPLE_SYNTAX_CLASS(StructDecl, AggTypeDecl) - -SIMPLE_SYNTAX_CLASS(ClassDecl, AggTypeDecl) - -// TODO: Is it appropriate to treat an `enum` as an aggregate type? -// Most code that looks for, e.g., conformances assumes user-defined -// types are all `AggTypeDecl`, so this is the right choice for now -// if we want `enum` types to be able to implement interfaces, etc. -// -SYNTAX_CLASS(EnumDecl, AggTypeDecl) -RAW( - RefPtr tagType; -) -END_SYNTAX_CLASS() - -// A single case in an enum. -// -// E.g., in a declaration like: -// -// enum Color { Red = 0, Green, Blue }; -// -// The `Red = 0` is the declaration of the `Red` -// case, with `0` as an explicit expression for its -// _tag value_. -// -SYNTAX_CLASS(EnumCaseDecl, Decl) - - // type of the parent `enum` - SYNTAX_FIELD(TypeExp, type) - - RAW( - Type* getType() { return type.type.Ptr(); } - ) - - // Tag value - SYNTAX_FIELD(RefPtr, tagExpr) -END_SYNTAX_CLASS() - -// An interface which other types can conform to -SIMPLE_SYNTAX_CLASS(InterfaceDecl, AggTypeDecl) - -ABSTRACT_SYNTAX_CLASS(TypeConstraintDecl, Decl) - RAW( - virtual TypeExp& getSup() = 0; - ) -END_SYNTAX_CLASS() - -// A kind of pseudo-member that represents an explicit -// or implicit inheritance relationship. -// -SYNTAX_CLASS(InheritanceDecl, TypeConstraintDecl) -// The type expression as written - SYNTAX_FIELD(TypeExp, base) - - RAW( - // After checking, this dictionary will map members - // required by the base type to their concrete - // implementations in the type that contains - // this inheritance declaration. - RefPtr witnessTable; - virtual TypeExp& getSup() override - { - return 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() - -SIMPLE_SYNTAX_CLASS(TypeAliasDecl, TypeDefDecl) - -// An 'assoctype' declaration, it is a container of inheritance clauses -SYNTAX_CLASS(AssocTypeDecl, AggTypeDecl) -END_SYNTAX_CLASS() - -// A 'type_param' declaration, which defines a generic -// entry-point parameter. Is a container of GenericTypeConstraintDecl -SYNTAX_CLASS(GlobalGenericParamDecl, AggTypeDecl) -END_SYNTAX_CLASS() - -// A `__generic_value_param` declaration, which defines an existential -// value parameter (not a type parameter. -SYNTAX_CLASS(GlobalGenericValueParamDecl, VarDeclBase) -END_SYNTAX_CLASS() - -// A scope for local declarations (e.g., as part of a statement) -SIMPLE_SYNTAX_CLASS(ScopeDecl, ContainerDecl) - -// A function/initializer/subscript parameter (potentially mutable) -SIMPLE_SYNTAX_CLASS(ParamDecl, VarDeclBase) - -// A parameter of a function declared in "modern" types (immutable unless explicitly `out` or `inout`) -SIMPLE_SYNTAX_CLASS(ModernParamDecl, ParamDecl) - -// Base class for things that have parameter lists and can thus be applied to arguments ("called") -ABSTRACT_SYNTAX_CLASS(CallableDecl, ContainerDecl) - RAW( - FilteredMemberList GetParameters() - { - return getMembersOfType(); - }) - - SYNTAX_FIELD(TypeExp, ReturnType) - - // Fields related to redeclaration, so that we - // can support multiple specialized varaitions - // of the "same" logical function. - // - // This should also help us to support redeclaration - // of functions when handling HLSL/GLSL. - - // The "primary" declaration of the function, which will - // be used whenever we need to unique things. - FIELD_INIT(CallableDecl*, primaryDecl, nullptr) - - // The next declaration of the "same" function (that is, - // with the same `primaryDecl`). - FIELD_INIT(CallableDecl*, nextDecl, nullptr); - -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, 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(RefAccessorDecl, AccessorDecl) - -SIMPLE_SYNTAX_CLASS(FuncDecl, FunctionDeclBase) - -SIMPLE_SYNTAX_CLASS(NamespaceDeclBase, ContainerDecl) - - // A `namespace` declaration inside some module, that provides - // a named scope for declarations inside it. - // - // Note: Multiple `namespace` declarations with the same name - // in a given module/file will be collapsed into a single - // `NamespaceDecl` during parsing, so this declaration does - // not directly represent what is present in the input syntax. - // -SIMPLE_SYNTAX_CLASS(NamespaceDecl, NamespaceDeclBase) - - // A "module" of code (essentiately, a single translation unit) - // that provides a scope for some number of declarations. -SYNTAX_CLASS(ModuleDecl, NamespaceDeclBase) - // The API-level module that this declaration belong to. - // - // This field allows lookup of the `Module` based on a - // declaration nested under a `ModuleDecl` by following - // its chain of parents. - // - RAW(Module* module = nullptr;) -END_SYNTAX_CLASS() - -SYNTAX_CLASS(ImportDecl, Decl) - // The name of the module we are trying to import - FIELD(NameLoc, moduleNameAndLoc) - - // The scope that we want to import into - FIELD(RefPtr, scope) - - // The module that actually got imported - DECL_FIELD(RefPtr, importedModuleDecl) -END_SYNTAX_CLASS() - -// A generic declaration, parameterized on types/values -SYNTAX_CLASS(GenericDecl, ContainerDecl) - // The decl that is genericized... - SYNTAX_FIELD(RefPtr, 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, TypeConstraintDecl) - // 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) - RAW( - virtual TypeExp& getSup() override - { - return sup; - } - ) -END_SYNTAX_CLASS() - -SIMPLE_SYNTAX_CLASS(GenericValueParamDecl, VarDeclBase) - -// 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) - -// 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, syntaxClass) - - // Callback to invoke in order to parse syntax with this keyword. - FIELD(SyntaxParseCallback, parseCallback) - FIELD(void*, parseUserData) -END_SYNTAX_CLASS() - -// A declaration of an attribute to be used with `[name(...)]` syntax. -// -SYNTAX_CLASS(AttributeDecl, ContainerDecl) - // What type of syntax node will be produced to represent this attribute. - FIELD(SyntaxClass, syntaxClass) -END_SYNTAX_CLASS() diff --git a/source/slang/slang-expr-defs.h b/source/slang/slang-expr-defs.h deleted file mode 100644 index 725bbb62d..000000000 --- a/source/slang/slang-expr-defs.h +++ /dev/null @@ -1,216 +0,0 @@ -// slang-expr-defs.h - -// Syntax class definitions for expressions. - - -// Base class for expressions that will reference declarations -ABSTRACT_SYNTAX_CLASS(DeclRefExpr, Expr) - -// The scope in which to perform lookup - FIELD(RefPtr, scope) - - // The declaration of the symbol being referenced - DECL_FIELD(DeclRef, declRef) - - // The name of the symbol being referenced - FIELD(Name*, name) -END_SYNTAX_CLASS() - -SIMPLE_SYNTAX_CLASS(VarExpr, DeclRefExpr) - -// An expression that references an overloaded set of declarations -// having the same name. -SYNTAX_CLASS(OverloadedExpr, Expr) - // The name that was looked up and found to be overloaded - FIELD(Name*, name) - - // Optional: the base expression is this overloaded result - // arose from a member-reference expression. - SYNTAX_FIELD(RefPtr, base) - - // The lookup result that was ambiguous - FIELD(LookupResult, lookupResult2) -END_SYNTAX_CLASS() - -// An expression that references an overloaded set of declarations -// having the same name. -SYNTAX_CLASS(OverloadedExpr2, Expr) - - // Optional: the base expression is this overloaded result - // arose from a member-reference expression. - SYNTAX_FIELD(RefPtr, base) - - // The lookup result that was ambiguous - FIELD(List>, candidiateExprs) -END_SYNTAX_CLASS() - -ABSTRACT_SYNTAX_CLASS(LiteralExpr, Expr) - // The token that was used to express the literal. This can be - // used to get the raw text of the literal, including any suffix. - FIELD(Token, token) -END_SYNTAX_CLASS() - -SYNTAX_CLASS(IntegerLiteralExpr, LiteralExpr) - FIELD(IntegerLiteralValue, value) -END_SYNTAX_CLASS() - -SYNTAX_CLASS(FloatingPointLiteralExpr, LiteralExpr) - FIELD(FloatingPointLiteralValue, value) -END_SYNTAX_CLASS() - -SYNTAX_CLASS(BoolLiteralExpr, LiteralExpr) - FIELD(bool, value) -END_SYNTAX_CLASS() - -SYNTAX_CLASS(StringLiteralExpr, LiteralExpr) - // TODO: consider storing the "segments" of the string - // literal, in the case where multiple literals were - //lined up at the lexer level, e.g.: - // - // "first" "second" "third" - // - FIELD(String, value) -END_SYNTAX_CLASS() - -// An initializer list, e.g. `{ 1, 2, 3 }` -SYNTAX_CLASS(InitializerListExpr, Expr) - SYNTAX_FIELD(List>, args) -END_SYNTAX_CLASS() - -// A base class for expressions with arguments -ABSTRACT_SYNTAX_CLASS(ExprWithArgsBase, Expr) - SYNTAX_FIELD(List>, Arguments) -END_SYNTAX_CLASS() - -// An aggregate type constructor -SYNTAX_CLASS(AggTypeCtorExpr, ExprWithArgsBase) - SYNTAX_FIELD(TypeExp, base); -END_SYNTAX_CLASS() - - -// A base expression being applied to arguments: covers -// both ordinary `()` function calls and `<>` generic application -ABSTRACT_SYNTAX_CLASS(AppExprBase, ExprWithArgsBase) - SYNTAX_FIELD(RefPtr, FunctionExpr) -END_SYNTAX_CLASS() - -SIMPLE_SYNTAX_CLASS(InvokeExpr, AppExprBase) - -SIMPLE_SYNTAX_CLASS(OperatorExpr, InvokeExpr) - -SIMPLE_SYNTAX_CLASS(InfixExpr , OperatorExpr) -SIMPLE_SYNTAX_CLASS(PrefixExpr , OperatorExpr) -SIMPLE_SYNTAX_CLASS(PostfixExpr, OperatorExpr) - -SYNTAX_CLASS(IndexExpr, Expr) - SYNTAX_FIELD(RefPtr, BaseExpression) - SYNTAX_FIELD(RefPtr, IndexExpression) -END_SYNTAX_CLASS() - -SYNTAX_CLASS(MemberExpr, DeclRefExpr) - SYNTAX_FIELD(RefPtr, BaseExpression) -END_SYNTAX_CLASS() - -// Member looked up on a type, rather than a value -SYNTAX_CLASS(StaticMemberExpr, DeclRefExpr) - SYNTAX_FIELD(RefPtr, BaseExpression) -END_SYNTAX_CLASS() - -SYNTAX_CLASS(SwizzleExpr, Expr) - SYNTAX_FIELD(RefPtr, base) - FIELD(int, elementCount) - FIELD(int, elementIndices[4]) -END_SYNTAX_CLASS() - -// A dereference of a pointer or pointer-like type -SYNTAX_CLASS(DerefExpr, Expr) - SYNTAX_FIELD(RefPtr, base) -END_SYNTAX_CLASS() - -// Any operation that performs type-casting -SYNTAX_CLASS(TypeCastExpr, InvokeExpr) -// SYNTAX_FIELD(TypeExp, TargetType) -// SYNTAX_FIELD(RefPtr, Expression) -END_SYNTAX_CLASS() - -// An explicit type-cast that appear in the user's code with `(type) expr` syntax -SYNTAX_CLASS(ExplicitCastExpr, TypeCastExpr) -END_SYNTAX_CLASS() - -// An implicit type-cast inserted during semantic checking -SYNTAX_CLASS(ImplicitCastExpr, TypeCastExpr) -END_SYNTAX_CLASS() - - /// A cast from a value to an interface ("existential") type. -SYNTAX_CLASS(CastToInterfaceExpr, Expr) -RAW( - /// The value being cast to an interface type - RefPtr valueArg; - - /// A witness showing that `valueArg` conforms to the chosen interface - RefPtr witnessArg; -) -END_SYNTAX_CLASS() - -SIMPLE_SYNTAX_CLASS(SelectExpr, OperatorExpr) - -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, Expr) - // The underlying type expression that we want to share - SYNTAX_FIELD(TypeExp, base) -END_SYNTAX_CLASS() - -SYNTAX_CLASS(AssignExpr, Expr) - SYNTAX_FIELD(RefPtr, left); - SYNTAX_FIELD(RefPtr, right); -END_SYNTAX_CLASS() - -// Just an expression inside parentheses `(exp)` -// -// We keep this around explicitly to be sure we don't lose any structure -// when we do rewriter stuff. -SYNTAX_CLASS(ParenExpr, Expr) - SYNTAX_FIELD(RefPtr, base); -END_SYNTAX_CLASS() - -// An object-oriented `this` expression, used to -// refer to the current instance of an enclosing type. -SYNTAX_CLASS(ThisExpr, Expr) - FIELD(RefPtr, scope); -END_SYNTAX_CLASS() - -// An expression that binds a temporary variable in a local expression context -SYNTAX_CLASS(LetExpr, Expr) -RAW( - RefPtr decl; - RefPtr body; -) -END_SYNTAX_CLASS() - -SYNTAX_CLASS(ExtractExistentialValueExpr, Expr) -RAW( - DeclRef declRef; -) -END_SYNTAX_CLASS() - - /// A type expression of the form `__TaggedUnion(A, ...)`. - /// - /// An expression of this form will resolve to a `TaggedUnionType` - /// when checked. - /// -SYNTAX_CLASS(TaggedUnionTypeExpr, Expr) -RAW( - List caseTypes; -) -END_SYNTAX_CLASS() - - /// A type expression of the form `This` - /// - /// Refers to the type of `this` in the current context. - /// -SYNTAX_CLASS(ThisTypeExpr, Expr) - FIELD(RefPtr, scope); -END_SYNTAX_CLASS() diff --git a/source/slang/slang-modifier-defs.h b/source/slang/slang-modifier-defs.h deleted file mode 100644 index 0c7156c72..000000000 --- a/source/slang/slang-modifier-defs.h +++ /dev/null @@ -1,495 +0,0 @@ -// slang-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(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); -SIMPLE_MODIFIER(ConstExpr); -SIMPLE_MODIFIER(GloballyCoherent) - -#undef SIMPLE_MODIFIER - -// A modifier that marks something as an operation that -// has a one-to-one translation to the IR, and thus -// has no direct definition in the high-level language. -// -SYNTAX_CLASS(IntrinsicOpModifier, Modifier) - - // Token that names the intrinsic op. - FIELD(Token, opToken) - - // The IR opcode for the intrinsic operation. - // - FIELD_INIT(uint32_t, op, 0) -END_SYNTAX_CLASS() - -// A modifier that marks something as an intrinsic function, -// for some subset of targets. -SYNTAX_CLASS(TargetIntrinsicModifier, Modifier) - // 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() - -// A modifier that marks a declaration as representing a -// specialization that should be preferred on a particular -// target. -SYNTAX_CLASS(SpecializedForTargetModifier, Modifier) - // Token that names the target that the operation - // has been specialized for. - FIELD(Token, targetToken) -END_SYNTAX_CLASS() - -// A modifier to tag something as an intrinsic that requires -// a certain GLSL extension to be enabled when used -SYNTAX_CLASS(RequiredGLSLExtensionModifier, Modifier) -FIELD(Token, extensionNameToken) -END_SYNTAX_CLASS() - -// A modifier to tag something as an intrinsic that requires -// a certain GLSL version to be enabled when used -SYNTAX_CLASS(RequiredGLSLVersionModifier, Modifier) -FIELD(Token, versionNumberToken) -END_SYNTAX_CLASS() - - -// A modifier to tag something as an intrinsic that requires -// a certain SPIRV version to be enabled when used. Specified as "major.minor" -SYNTAX_CLASS(RequiredSPIRVVersionModifier, Modifier) -FIELD(SemanticVersion, version) -END_SYNTAX_CLASS() - -// A modifier to tag something as an intrinsic that requires -// a certain CUDA SM version to be enabled when used. Specified as "major.minor" -SYNTAX_CLASS(RequiredCUDASMVersionModifier, Modifier) -FIELD(SemanticVersion, version) -END_SYNTAX_CLASS() - -SIMPLE_SYNTAX_CLASS(InOutModifier, OutModifier) - -// `__ref` modifier for by-reference parameter passing -SIMPLE_SYNTAX_CLASS(RefModifier, Modifier) - -// 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() - -// AST nodes to represent the begin/end of a `layout` modifier group -ABSTRACT_SYNTAX_CLASS(GLSLLayoutModifierGroupMarker, Modifier) -END_SYNTAX_CLASS() -SIMPLE_SYNTAX_CLASS(GLSLLayoutModifierGroupBegin, GLSLLayoutModifierGroupMarker) -SIMPLE_SYNTAX_CLASS(GLSLLayoutModifierGroupEnd, GLSLLayoutModifierGroupMarker) - -// 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(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(ImplicitParameterGroupVariableModifier , 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(ImplicitParameterGroupElementTypeModifier, 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 -SYNTAX_CLASS(HLSLRegisterSemantic, HLSLLayoutSemantic) - FIELD(Token, spaceName) -END_SYNTAX_CLASS() - -// 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(ParameterGroupReflectionName, Modifier) - FIELD(NameLoc, nameAndLoc) -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() - -// A modifier applied to declarations of builtin types to indicate how they -// should be lowered to the IR. -// -// TODO: This should really subsume `BuiltinTypeModifier` and -// `MagicTypeModifier` so that we don't have to apply all of them. -SYNTAX_CLASS(IntrinsicTypeModifier, Modifier) - // The IR opcode to use when constructing a type - FIELD(uint32_t, irOp) - - // Additional literal opreands to provide when creating instances. - // (e.g., for a texture type this passes in shape/mutability info) - FIELD(List, irOperands) -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 - -ABSTRACT_SYNTAX_CLASS(InterpolationModeModifier, Modifier) -END_SYNTAX_CLASS() - -// HLSL `nointerpolation` modifier -SIMPLE_SYNTAX_CLASS(HLSLNoInterpolationModifier, InterpolationModeModifier) - -// HLSL `noperspective` modifier -SIMPLE_SYNTAX_CLASS(HLSLNoPerspectiveModifier, InterpolationModeModifier) - -// HLSL `linear` modifier -SIMPLE_SYNTAX_CLASS(HLSLLinearModifier, InterpolationModeModifier) - -// HLSL `sample` modifier -SIMPLE_SYNTAX_CLASS(HLSLSampleModifier, InterpolationModeModifier) - -// HLSL `centroid` modifier -SIMPLE_SYNTAX_CLASS(HLSLCentroidModifier, InterpolationModeModifier) - -// HLSL `precise` modifier -SIMPLE_SYNTAX_CLASS(PreciseModifier, 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) - -SYNTAX_CLASS(AttributeTargetModifier, Modifier) - // A class to which the declared attribute type is applicable - FIELD(SyntaxClass, syntaxClass) -END_SYNTAX_CLASS() - -// Base class for checked and unchecked `[name(arg0, ...)]` style attribute. -SYNTAX_CLASS(AttributeBase, Modifier) - SYNTAX_FIELD(List>, args) -END_SYNTAX_CLASS() - -// A `[name(...)]` attribute that hasn't undergone any semantic analysis. -// After analysis, this will be transformed into a more specific case. -SYNTAX_CLASS(UncheckedAttribute, AttributeBase) - FIELD(RefPtr, scope) -END_SYNTAX_CLASS() - -// A `[name(arg0, ...)]` style attribute that has been validated. -SYNTAX_CLASS(Attribute, AttributeBase) - FIELD(AttributeArgumentValueDict, intArgVals) -END_SYNTAX_CLASS() - -SYNTAX_CLASS(UserDefinedAttribute, Attribute) -END_SYNTAX_CLASS() - -SYNTAX_CLASS(AttributeUsageAttribute, Attribute) - FIELD(SyntaxClass, targetSyntaxClass) -END_SYNTAX_CLASS() - -// An `[unroll]` or `[unroll(count)]` attribute -SYNTAX_CLASS(UnrollAttribute, Attribute) - RAW(IntegerLiteralValue getCount();) -END_SYNTAX_CLASS() - -SIMPLE_SYNTAX_CLASS(LoopAttribute, Attribute) // `[loop]` -SIMPLE_SYNTAX_CLASS(FastOptAttribute, Attribute) // `[fastopt]` -SIMPLE_SYNTAX_CLASS(AllowUAVConditionAttribute, Attribute) // `[allow_uav_condition]` -SIMPLE_SYNTAX_CLASS(BranchAttribute, Attribute) // `[branch]` -SIMPLE_SYNTAX_CLASS(FlattenAttribute, Attribute) // `[flatten]` -SIMPLE_SYNTAX_CLASS(ForceCaseAttribute, Attribute) // `[forcecase]` -SIMPLE_SYNTAX_CLASS(CallAttribute, Attribute) // `[call]` - - -// [[vk_push_constant]] [[push_constant]] -SIMPLE_SYNTAX_CLASS(PushConstantAttribute, Attribute) - -// [[vk_shader_record]] [[shader_record]] -SIMPLE_SYNTAX_CLASS(ShaderRecordAttribute, Attribute) - -// [[vk_binding]] -SYNTAX_CLASS(GLSLBindingAttribute, Attribute) - FIELD(int32_t, binding = 0) - FIELD(int32_t, set = 0) -END_SYNTAX_CLASS() - -SYNTAX_CLASS(GLSLSimpleIntegerLayoutAttribute, Attribute) - FIELD(int32_t, value = 0) -END_SYNTAX_CLASS() - -// [[vk_location]] -SIMPLE_SYNTAX_CLASS(GLSLLocationAttribute, GLSLSimpleIntegerLayoutAttribute) - -// [[vk_index]] -SIMPLE_SYNTAX_CLASS(GLSLIndexAttribute, GLSLSimpleIntegerLayoutAttribute) - -// TODO: for attributes that take arguments, the syntax node -// classes should provide accessors for the values of those arguments. - -SIMPLE_SYNTAX_CLASS(MaxTessFactorAttribute, Attribute) -SIMPLE_SYNTAX_CLASS(OutputControlPointsAttribute, Attribute) -SIMPLE_SYNTAX_CLASS(OutputTopologyAttribute, Attribute) -SIMPLE_SYNTAX_CLASS(PartitioningAttribute, Attribute) -SYNTAX_CLASS(PatchConstantFuncAttribute, Attribute) - FIELD(RefPtr, patchConstantFuncDecl) -END_SYNTAX_CLASS() -SIMPLE_SYNTAX_CLASS(DomainAttribute, Attribute) - -SIMPLE_SYNTAX_CLASS(EarlyDepthStencilAttribute, Attribute) // `[earlydepthstencil]` - -// An HLSL `[numthreads(x,y,z)]` attribute -SYNTAX_CLASS(NumThreadsAttribute, Attribute) - // The number of threads to use along each axis - // - // TODO: These should be accessors that use the - // ordinary `args` list, rather than side data. - FIELD(int32_t, x) - FIELD(int32_t, y) - FIELD(int32_t, z) -END_SYNTAX_CLASS() - -SYNTAX_CLASS(MaxVertexCountAttribute, Attribute) - // The number of max vertex count for geometry shader - // - // TODO: This should be an accessor that uses the - // ordinary `args` list, rather than side data. - FIELD(int32_t, value) -END_SYNTAX_CLASS() - -SYNTAX_CLASS(InstanceAttribute, Attribute) - // The number of instances to run for geometry shader - // - // TODO: This should be an accessor that uses the - // ordinary `args` list, rather than side data. - FIELD(int32_t, value) -END_SYNTAX_CLASS() - -// A `[shader("stageName")]` attribute, which marks an entry point -// to be compiled, and specifies the stage for that entry point -SYNTAX_CLASS(EntryPointAttribute, Attribute) - // The resolved stage that the entry point is targetting. - // - // TODO: This should be an accessor that uses the - // ordinary `args` list, rather than side data. - FIELD(Stage, stage); -END_SYNTAX_CLASS() - -// A `[__vulkanRayPayload]` attribute, which is used in the -// standard library implementation to indicate that a variable -// actually represents the input/output interface for a Vulkan -// ray tracing shader to pass per-ray payload information. -SIMPLE_SYNTAX_CLASS(VulkanRayPayloadAttribute, Attribute) - -// A `[__vulkanCallablePayload]` attribute, which is used in the -// standard library implementation to indicate that a variable -// actually represents the input/output interface for a Vulkan -// ray tracing shader to pass payload information to/from a callee. -SIMPLE_SYNTAX_CLASS(VulkanCallablePayloadAttribute, Attribute) - -// A `[__vulkanHitAttributes]` attribute, which is used in the -// standard library implementation to indicate that a variable -// actually represents the output interface for a Vulkan -// intersection shader to pass hit attribute information. -SIMPLE_SYNTAX_CLASS(VulkanHitAttributesAttribute, Attribute) - -// A `[mutating]` attribute, which indicates that a member -// function is allowed to modify things through its `this` -// argument. -// -SIMPLE_SYNTAX_CLASS(MutatingAttribute, Attribute) - -// A `[__readNone]` attribute, which indicates that a function -// computes its results strictly based on argument values, without -// reading or writing through any pointer arguments, or any other -// state that could be observed by a caller. -// -SIMPLE_SYNTAX_CLASS(ReadNoneAttribute, Attribute) - - -// 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) - -// A modifier to be attached to syntax after we've computed layout -SYNTAX_CLASS(ComputedLayoutModifier, Modifier) - FIELD(RefPtr, layout) -END_SYNTAX_CLASS() - - -SYNTAX_CLASS(TupleVarModifier, Modifier) -// FIELD_INIT(TupleFieldModifier*, tupleField, nullptr) -END_SYNTAX_CLASS() - -// A modifier to indicate that a constructor/initializer can be used -// to perform implicit type conversion, and to specify the cost of -// the conversion, if applied. -SYNTAX_CLASS(ImplicitConversionModifier, Modifier) - // The conversion cost, used to rank conversions - FIELD(ConversionCost, cost) -END_SYNTAX_CLASS() - -SYNTAX_CLASS(FormatAttribute, Attribute) - FIELD(ImageFormat, format) -END_SYNTAX_CLASS() - -SYNTAX_CLASS(AllowAttribute, Attribute) - FIELD_INIT(DiagnosticInfo const*, diagnostic, nullptr) -END_SYNTAX_CLASS() - - -// A `[__extern]` attribute, which indicates that a function/type is defined externally -// -SIMPLE_SYNTAX_CLASS(ExternAttribute, Attribute) - -// An `[__unsafeForceInlineExternal]` attribute indicates that the callee should be inlined -// into call sites after initial IR generation (that is, as early as possible). -// -SIMPLE_SYNTAX_CLASS(UnsafeForceInlineEarlyAttribute, Attribute) diff --git a/source/slang/slang-object-meta-begin.h b/source/slang/slang-object-meta-begin.h deleted file mode 100644 index 9c09e845d..000000000 --- a/source/slang/slang-object-meta-begin.h +++ /dev/null @@ -1,43 +0,0 @@ -// slang-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() - -// Hack to remove 'warning C4702: unreachable code' on VS2017, blocking compilation -// Note! This is matched in object-meta-end.h -#if _MSC_VER >= 1910 -#pragma warning(push) -#pragma warning(disable: 4702) -#endif - diff --git a/source/slang/slang-object-meta-end.h b/source/slang/slang-object-meta-end.h deleted file mode 100644 index 5018b5ede..000000000 --- a/source/slang/slang-object-meta-end.h +++ /dev/null @@ -1,17 +0,0 @@ -// slang-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 - -// Hack to remove 'warning C4702: unreachable code' on VS2017, blocking compilation -// Note! This is matched in object-meta-begin.h -#if _MSC_VER >= 1910 -#pragma warning(pop) -#endif diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp index d8b0d9463..cdd573a97 100644 --- a/source/slang/slang-parser.cpp +++ b/source/slang/slang-parser.cpp @@ -2833,7 +2833,7 @@ namespace Slang // the class of AST node to construct. static RefPtr parseSimpleSyntax(Parser* /*parser*/, void* userData) { - SyntaxClassBase syntaxClass((SyntaxClassBase::ClassInfo*) userData); + SyntaxClassBase syntaxClass((ReflectClassInfo*) userData); return (RefObject*) syntaxClass.createInstanceImpl(); } diff --git a/source/slang/slang-stmt-defs.h b/source/slang/slang-stmt-defs.h deleted file mode 100644 index bf25f1706..000000000 --- a/source/slang/slang-stmt-defs.h +++ /dev/null @@ -1,124 +0,0 @@ -// slang-stmt-defs.h - -// Syntax class definitions for statements. - -ABSTRACT_SYNTAX_CLASS(ScopeStmt, Stmt) - SYNTAX_FIELD(RefPtr, scopeDecl) -END_SYNTAX_CLASS() - -// A sequence of statements, treated as a single statement -SYNTAX_CLASS(SeqStmt, Stmt) - SYNTAX_FIELD(List>, stmts) -END_SYNTAX_CLASS() - -// The simplest kind of scope statement: just a `{...}` block -SYNTAX_CLASS(BlockStmt, ScopeStmt) - SYNTAX_FIELD(RefPtr, body); -END_SYNTAX_CLASS() - -// A statement that we aren't going to parse or check, because -// we want to let a downstream compiler handle any issues -SYNTAX_CLASS(UnparsedStmt, Stmt) - // The tokens that were contained between `{` and `}` - FIELD(List, tokens) -END_SYNTAX_CLASS() - -SIMPLE_SYNTAX_CLASS(EmptyStmt, Stmt) - -SIMPLE_SYNTAX_CLASS(DiscardStmt, Stmt) - -SYNTAX_CLASS(DeclStmt, Stmt) - SYNTAX_FIELD(RefPtr, decl) -END_SYNTAX_CLASS() - -SYNTAX_CLASS(IfStmt, Stmt) - SYNTAX_FIELD(RefPtr, Predicate) - SYNTAX_FIELD(RefPtr, PositiveStatement) - SYNTAX_FIELD(RefPtr, 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, condition) - SYNTAX_FIELD(RefPtr, 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, Stmt) - DECL_FIELD(Stmt*, 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, 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() - -// A `for` statement -SYNTAX_CLASS(ForStmt, LoopStmt) - SYNTAX_FIELD(RefPtr, InitialStatement) - SYNTAX_FIELD(RefPtr, SideEffectExpression) - SYNTAX_FIELD(RefPtr, PredicateExpression) - SYNTAX_FIELD(RefPtr, Statement) -END_SYNTAX_CLASS() - -// A `for` statement in a language that doesn't restrict the scope -// of the loop variable to the body. -SYNTAX_CLASS(UnscopedForStmt, ForStmt); -END_SYNTAX_CLASS() - -SYNTAX_CLASS(WhileStmt, LoopStmt) - SYNTAX_FIELD(RefPtr, Predicate) - SYNTAX_FIELD(RefPtr, Statement) -END_SYNTAX_CLASS() - -SYNTAX_CLASS(DoWhileStmt, LoopStmt) - SYNTAX_FIELD(RefPtr, Statement) - SYNTAX_FIELD(RefPtr, Predicate) -END_SYNTAX_CLASS() - -// A compile-time, range-based `for` loop, which will not appear in the output code -SYNTAX_CLASS(CompileTimeForStmt, ScopeStmt) - SYNTAX_FIELD(RefPtr, varDecl) - SYNTAX_FIELD(RefPtr, rangeBeginExpr) - SYNTAX_FIELD(RefPtr, rangeEndExpr) - SYNTAX_FIELD(RefPtr, body) - SYNTAX_FIELD(RefPtr, rangeBeginVal) - SYNTAX_FIELD(RefPtr, rangeEndVal) -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(BreakStmt, JumpStmt) - -SIMPLE_SYNTAX_CLASS(ContinueStmt, JumpStmt) - -SYNTAX_CLASS(ReturnStmt, Stmt) - SYNTAX_FIELD(RefPtr, Expression) -END_SYNTAX_CLASS() - -SYNTAX_CLASS(ExpressionStmt, Stmt) - SYNTAX_FIELD(RefPtr, Expression) -END_SYNTAX_CLASS() diff --git a/source/slang/slang-syntax-base-defs.h b/source/slang/slang-syntax-base-defs.h deleted file mode 100644 index 60e888b56..000000000 --- a/source/slang/slang-syntax-base-defs.h +++ /dev/null @@ -1,306 +0,0 @@ -// slang-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. - -ABSTRACT_SYNTAX_CLASS(NodeBase, RefObject) - // A helper to access the corresponding class on a concrete instance - RAW(virtual const SyntaxClassBase::ClassInfo& getClassInfo() const = 0;) - RAW(SyntaxClass getClass() { return SyntaxClass(&getClassInfo()); } ) -END_SYNTAX_CLASS() - -// Base class for all nodes representing actual syntax -// (thus having a location in the source code) -ABSTRACT_SYNTAX_CLASS(SyntaxNodeBase, NodeBase) - // The primary source location associated with this AST node - FIELD(SourceLoc, loc) -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, NodeBase) - 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 Substitute(SubstitutionSet subst); - - // Lower-level interface for substitution. 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 SubstituteImpl(SubstitutionSet 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(&v)); - } - ) -END_SYNTAX_CLASS() - -RAW( - class Type; - - template - SLANG_FORCE_INLINE T* as(Type* obj); - template - SLANG_FORCE_INLINE const T* as(const Type* obj); - ) - -// 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 representation caches a pointer to -// a canonical type on every type, so we can easily -// operate on the raw representation when needed. -ABSTRACT_SYNTAX_CLASS(Type, 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: - Session* getSession() { return this->session; } - void setSession(Session* s) { this->session = s; } - - bool Equals(Type* type); - - Type* GetCanonicalType(); - - virtual RefPtr SubstituteImpl(SubstitutionSet subst, int* ioDiff) override; - - virtual bool EqualsVal(Val* val) override; - - ~Type(); - -protected: - virtual bool EqualsImpl(Type* type) = 0; - - virtual RefPtr CreateCanonicalType() = 0; - Type* canonicalType = nullptr; - - Session* session = nullptr; - ) -END_SYNTAX_CLASS() -RAW( - template - SLANG_FORCE_INLINE T* as(Type* obj) { return obj ? dynamicCast(obj->GetCanonicalType()) : nullptr; } - template - SLANG_FORCE_INLINE const T* as(const Type* obj) { return obj ? dynamicCast(const_cast(obj)->GetCanonicalType()) : nullptr; } -) - -// A substitution represents a binding of certain -// type-level variables to concrete argument values -ABSTRACT_SYNTAX_CLASS(Substitutions, RefObject) - // The next outer that this one refines. - FIELD(RefPtr, outer) - - RAW( - // Apply a set of substitutions to the bindings in this substitution - virtual RefPtr applySubstitutionsShallow(SubstitutionSet substSet, RefPtr substOuter, int* ioDiff) = 0; - - // Check if these are equivalent substitutiosn to another set - virtual bool Equals(Substitutions* subst) = 0; - virtual int GetHashCode() const = 0; - ) -END_SYNTAX_CLASS() - -SYNTAX_CLASS(GenericSubstitution, Substitutions) - // The generic declaration that defines the - // parameters we are binding to arguments - DECL_FIELD(GenericDecl*, genericDecl) - - // The actual values of the arguments - SYNTAX_FIELD(List>, args) - - RAW( - // Apply a set of substitutions to the bindings in this substitution - virtual RefPtr applySubstitutionsShallow(SubstitutionSet substSet, RefPtr substOuter, int* ioDiff) override; - - // Check if these are equivalent substitutiosn to another set - virtual bool Equals(Substitutions* subst) override; - - virtual int GetHashCode() const override - { - int rs = 0; - for (auto && v : args) - { - rs ^= v->GetHashCode(); - rs *= 16777619; - } - return rs; - } - ) -END_SYNTAX_CLASS() - -SYNTAX_CLASS(ThisTypeSubstitution, Substitutions) - // The declaration of the interface that we are specializing - FIELD_INIT(InterfaceDecl*, interfaceDecl, nullptr) - - // A witness that shows that the concrete type used to - // specialize the interface conforms to the interface. - FIELD(RefPtr, witness) - - // The actual type that provides the lookup scope for an associated type - RAW( - // Apply a set of substitutions to the bindings in this substitution - virtual RefPtr applySubstitutionsShallow(SubstitutionSet substSet, RefPtr substOuter, int* ioDiff) override; - - // Check if these are equivalent substitutiosn to another set - virtual bool Equals(Substitutions* subst) override; - - virtual int GetHashCode() const override; - ) -END_SYNTAX_CLASS() - -SYNTAX_CLASS(GlobalGenericParamSubstitution, Substitutions) - // the type_param decl to be substituted - DECL_FIELD(GlobalGenericParamDecl*, paramDecl) - - // the actual type to substitute in - SYNTAX_FIELD(RefPtr, actualType) - - RAW( - struct ConstraintArg - { - RefPtr decl; - RefPtr val; - }; - ) - - // the values that satisfy any constraints on the type parameter - SYNTAX_FIELD(List, constraintArgs) - -RAW( - // Apply a set of substitutions to the bindings in this substitution - virtual RefPtr applySubstitutionsShallow(SubstitutionSet substSet, RefPtr substOuter, int* ioDiff) override; - - // Check if these are equivalent substitutiosn to another set - virtual bool Equals(Substitutions* subst) override; - - virtual int GetHashCode() const override - { - int rs = actualType->GetHashCode(); - for (auto && a : constraintArgs) - { - rs = combineHash(rs, a.val->GetHashCode()); - } - 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, SyntaxNode) - 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, next) - - // The keyword that was used to introduce t that was used to name this modifier. - FIELD(Name*, name) - - RAW( - Name* getName() { return name; } - NameLoc getNameAndLoc() { return NameLoc(name, loc); } - ) -END_SYNTAX_CLASS() - -// A syntax node which can have modifiers applied -ABSTRACT_SYNTAX_CLASS(ModifiableSyntaxNode, SyntaxNode) - - SYNTAX_FIELD(Modifiers, modifiers) - - RAW( - template - FilteredModifierList GetModifiersOfType() { return FilteredModifierList(modifiers.first.Ptr()); } - - // Find the first modifier of a given type, or return `nullptr` if none is found. - template - T* FindModifier() - { - return *GetModifiersOfType().begin(); - } - - template - bool HasModifier() { return FindModifier() != 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(NameLoc, nameAndLoc) - - RAW( - Name* getName() { return nameAndLoc.name; } - SourceLoc getNameLoc() { return nameAndLoc.loc ; } - NameLoc getNameAndLoc() { return nameAndLoc ; } - ) - - - FIELD_INIT(DeclCheckStateExt, 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) - { - SLANG_RELEASE_ASSERT(state >= checkState.getState()); - checkState.setState(state); - } - ) -END_SYNTAX_CLASS() - -ABSTRACT_SYNTAX_CLASS(Expr, SyntaxNode) - RAW(typedef IExprVisitor Visitor;) - - FIELD(QualType, type) - - RAW(virtual void accept(IExprVisitor* visitor, void* extra) = 0;) - -END_SYNTAX_CLASS() - -ABSTRACT_SYNTAX_CLASS(Stmt, ModifiableSyntaxNode) - RAW(typedef IStmtVisitor Visitor;) - - RAW(virtual void accept(IStmtVisitor* visitor, void* extra) = 0;) - -END_SYNTAX_CLASS() diff --git a/source/slang/slang-syntax-defs.h b/source/slang/slang-syntax-defs.h deleted file mode 100644 index 5a16c3709..000000000 --- a/source/slang/slang-syntax-defs.h +++ /dev/null @@ -1,10 +0,0 @@ -// slang-syntax-defs.h - -#include "slang-syntax-base-defs.h" - -#include "slang-expr-defs.h" -#include "slang-decl-defs.h" -#include "slang-modifier-defs.h" -#include "slang-stmt-defs.h" -#include "slang-type-defs.h" -#include "slang-val-defs.h" diff --git a/source/slang/slang-syntax.cpp b/source/slang/slang-syntax.cpp index 2055c2422..cb75622bc 100644 --- a/source/slang/slang-syntax.cpp +++ b/source/slang/slang-syntax.cpp @@ -8,182 +8,11 @@ namespace Slang { - // We want this first, before the kClassInfo variables so it is constructed before anything else. - /* static*/ SyntaxClassBase::ClassInfo* SyntaxClassBase::ClassInfo::s_first = nullptr; - // BasicExpressionType - - bool BasicExpressionType::EqualsImpl(Type * type) - { - auto basicType = as(type); - return basicType && basicType->baseType == this->baseType; - } - - RefPtr BasicExpressionType::CreateCanonicalType() - { - // A basic type is already canonical, in our setup - return this; - } - - // Generate dispatch logic and other definitions for all syntax classes -#define SYNTAX_CLASS(NAME, BASE) /* empty */ -#include "slang-object-meta-begin.h" - -#include "slang-syntax-base-defs.h" -#undef SYNTAX_CLASS -#undef ABSTRACT_SYNTAX_CLASS - -#define ABSTRACT_SYNTAX_CLASS(NAME, BASE) \ - template<> \ - SyntaxClassBase::ClassInfo const SyntaxClassBase::Impl::kClassInfo(#NAME, nullptr, &SyntaxClassBase::Impl::kClassInfo); - -#define SYNTAX_CLASS(NAME, BASE) \ - template<> \ - void* SyntaxClassBase::Impl::createFunc() { return new NAME(); } \ - template<> \ - SyntaxClassBase::ClassInfo const SyntaxClassBase::Impl::kClassInfo( #NAME, &SyntaxClassBase::Impl::createFunc, &SyntaxClassBase::Impl::kClassInfo); \ - void NAME::accept(NAME::Visitor* visitor, void* extra) \ - { visitor->dispatch_##NAME(this, extra); } \ - const SyntaxClassBase::ClassInfo& NAME::getClassInfo() const { return SyntaxClassBase::Impl::kClassInfo; } - -template<> -SyntaxClassBase::ClassInfo const SyntaxClassBase::Impl::kClassInfo("RefObject", nullptr, nullptr); - -ABSTRACT_SYNTAX_CLASS(NodeBase, RefObject); -ABSTRACT_SYNTAX_CLASS(SyntaxNodeBase, NodeBase); -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, NodeBase); -ABSTRACT_SYNTAX_CLASS(Type, Val); -ABSTRACT_SYNTAX_CLASS(Modifier, SyntaxNodeBase); -ABSTRACT_SYNTAX_CLASS(Expr, SyntaxNode); - -ABSTRACT_SYNTAX_CLASS(Substitutions, SyntaxNode); -ABSTRACT_SYNTAX_CLASS(GenericSubstitution, Substitutions); -ABSTRACT_SYNTAX_CLASS(ThisTypeSubstitution, Substitutions); -ABSTRACT_SYNTAX_CLASS(GlobalGenericParamSubstitution, Substitutions); - -#include "slang-expr-defs.h" -#include "slang-decl-defs.h" -#include "slang-modifier-defs.h" -#include "slang-stmt-defs.h" -#include "slang-type-defs.h" -#include "slang-val-defs.h" -#include "slang-object-meta-end.h" - - -SyntaxClassBase::ClassInfo::ClassInfo(const char* name, CreateFunc createFunc, const ClassInfo* superClass): - m_name(name), - m_createFunc(createFunc), - m_superClass(superClass), - m_next(s_first) -{ - m_classId = 0; - m_childrenEndClassId = 0; - - s_first = this; -} - - - -static uint32_t _calcRangeRec(const SyntaxClassBase::ClassInfo* classInfo, const Dictionary >& childMap, uint32_t index) -{ - classInfo->m_classId = index++; - // Do the calc range for all the children - auto list = childMap.TryGetValue(classInfo); +#define SLANG_CLASS_ACCEPT_IMPL(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \ + void NAME::accept(NAME::Visitor* visitor, void* extra) { visitor->dispatch_##NAME(this, extra); } - if (list) - { - for (auto child : *list) - { - index = _calcRangeRec(child, childMap, index); - } - } - - classInfo->m_childrenEndClassId = index; - return index; -} - -bool SyntaxClassBase::ClassInfo::isSubClassOfSlow(const ThisType& super) const -{ - SyntaxClassBase::ClassInfo const* info = this; - while (info) - { - if (info == &super) - return true; - info = info->m_superClass; - } - return false; -} - -static bool _checkSubClassRange() -{ - typedef SyntaxClassBase::ClassInfo ClassInfo; - - List list; - for (const ClassInfo* type = ClassInfo::s_first; type; type = type->m_next) - { - list.add(type); - } - - for (Index i = 0; i < list.getCount(); ++i) - { - for (Index j = 0; j < list.getCount(); ++j) - { - auto a = list[i]; - auto b = list[j]; - if (a->isSubClassOf(*b) != a->isSubClassOfSlow(*b)) - { - return false; - } - } - } - - return true; -} - - -/* static */SlangResult SyntaxClassBase::ClassInfo::initRanges() -{ - // Remove the warning about not referenced - SLANG_UNUSED(&_checkSubClassRange); - - // TODO(JS): - // Note that the calculating of the ranges could be done more efficiently by adding to an array of struct { super, class }, sorting, by super classs - // and using a dictionary to map from class it's first in list of super class use. This works for now though. - - // We want to produce a map from a node that holds all of it's children - Dictionary > childMap; - - const List emptyList; - - { - for (const ThisType* type = s_first; type; type = type->m_next) - { - if (type->m_superClass) - { - // Add to that item - List* list = childMap.TryGetValueOrAdd(type->m_superClass, emptyList); - if (!list) - { - list = childMap.TryGetValue(type->m_superClass); - } - SLANG_ASSERT(list); - list->add(type); - } - } - } - - // We want to recursively work out a range - _calcRangeRec(&SyntaxClassBase::Impl::kClassInfo, childMap, 1); - - SLANG_ASSERT(_checkSubClassRange()); - - return SLANG_OK; -} +SLANG_ALL_ASTNode_NodeBase(SLANG_CLASS_ONLY, SLANG_CLASS_ACCEPT_IMPL) // !!!!!!!!!!!!!!!!!!!!!!!!!!!!! DiagnosticSink impls !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -225,10 +54,23 @@ SourceLoc const& getDiagnosticPos(TypeExp const& typeExp) return typeExp.exp->loc; } +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! BasicExpressionType !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +bool BasicExpressionType::EqualsImpl(Type * type) +{ + auto basicType = as(type); + return basicType && basicType->baseType == this->baseType; +} + +RefPtr BasicExpressionType::CreateCanonicalType() +{ + // A basic type is already canonical, in our setup + return this; +} // !!!!!!!!!!!!!!!!!!!!!!!!!!!!! Free functions !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -const RefPtr* adjustFilterCursorImpl(const SyntaxClassBase::ClassInfo& clsInfo, MemberFilterStyle filterStyle, const RefPtr* ptr, const RefPtr* end) +const RefPtr* adjustFilterCursorImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filterStyle, const RefPtr* ptr, const RefPtr* end) { switch (filterStyle) { @@ -273,7 +115,7 @@ const RefPtr* adjustFilterCursorImpl(const SyntaxClassBase::ClassInfo& cls return end; } -const RefPtr* getFilterCursorByIndexImpl(const SyntaxClassBase::ClassInfo& clsInfo, MemberFilterStyle filterStyle, const RefPtr* ptr, const RefPtr* end, Index index) +const RefPtr* getFilterCursorByIndexImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filterStyle, const RefPtr* ptr, const RefPtr* end, Index index) { switch (filterStyle) { @@ -330,7 +172,7 @@ const RefPtr* getFilterCursorByIndexImpl(const SyntaxClassBase::ClassInfo& return nullptr; } -Index getFilterCountImpl(const SyntaxClassBase::ClassInfo& clsInfo, MemberFilterStyle filterStyle, const RefPtr* ptr, const RefPtr* end) +Index getFilterCountImpl(const ReflectClassInfo& clsInfo, MemberFilterStyle filterStyle, const RefPtr* ptr, const RefPtr* end) { Index count = 0; switch (filterStyle) diff --git a/source/slang/slang-syntax.h b/source/slang/slang-syntax.h index 5e1f057e4..e29a641a1 100644 --- a/source/slang/slang-syntax.h +++ b/source/slang/slang-syntax.h @@ -1,1373 +1,12 @@ #ifndef SLANG_SYNTAX_H #define SLANG_SYNTAX_H -#include "../core/slang-basic.h" -#include "slang-lexer.h" -#include "slang-profile.h" -#include "slang-type-system-shared.h" -#include "../../slang.h" +#include "slang-ast-support-types.h" -#include "../core/slang-semantic-version.h" - -#include "slang-name.h" - -#include +#include "slang-ast-all.h" namespace Slang { - class Module; - class Name; - class Session; - class Substitutions; - class SyntaxVisitor; - class FuncDecl; - class Layout; - - struct IExprVisitor; - struct IDeclVisitor; - struct IModifierVisitor; - struct IStmtVisitor; - struct ITypeVisitor; - struct IValVisitor; - - class Parser; - class SyntaxNode; - - class Decl; - struct QualType; - class Type; - struct TypeExp; - class Val; - - void printDiagnosticArg(StringBuilder& sb, Decl* decl); - void printDiagnosticArg(StringBuilder& sb, Type* type); - void printDiagnosticArg(StringBuilder& sb, TypeExp const& type); - void printDiagnosticArg(StringBuilder& sb, QualType const& type); - void printDiagnosticArg(StringBuilder& sb, Val* val); - - class SyntaxNode; - SourceLoc const& getDiagnosticPos(SyntaxNode const* syntax); - SourceLoc const& getDiagnosticPos(TypeExp const& typeExp); - - typedef RefPtr (*SyntaxParseCallback)(Parser* parser, void* userData); - - typedef unsigned int ConversionCost; - enum : ConversionCost - { - // No conversion at all - kConversionCost_None = 0, - - // Conversion from a buffer to the type it carries needs to add a minimal - // extra cost, just so we can distinguish an overload on `ConstantBuffer` - // from one on `Foo` - kConversionCost_ImplicitDereference = 10, - - // Conversions based on explicit sub-typing relationships are the cheapest - // - // TODO(tfoley): We will eventually need a discipline for ranking - // when two up-casts are comparable. - kConversionCost_CastToInterface = 50, - - // Conversion that is lossless and keeps the "kind" of the value the same - kConversionCost_RankPromotion = 150, - - // Conversions that are lossless, but change "kind" - kConversionCost_UnsignedToSignedPromotion = 200, - - // Conversion from signed->unsigned integer of same or greater size - kConversionCost_SignedToUnsignedConversion = 300, - - // Cost of converting an integer to a floating-point type - kConversionCost_IntegerToFloatConversion = 400, - - // Default case (usable for user-defined conversions) - kConversionCost_Default = 500, - - // Catch-all for conversions that should be discouraged - // (i.e., that really shouldn't be made implicitly) - // - // TODO: make these conversions not be allowed implicitly in "Slang mode" - kConversionCost_GeneralConversion = 900, - - // This is the cost of an explicit conversion, which should - // not actually be performed. - kConversionCost_Explicit = 90000, - - // Additional conversion cost to add when promoting from a scalar to - // a vector (this will be added to the cost, if any, of converting - // the element type of the vector) - kConversionCost_ScalarToVector = 1, - - // Conversion is impossible - kConversionCost_Impossible = 0xFFFFFFFF, - }; - - enum class ImageFormat - { -#define FORMAT(NAME) NAME, -#include "slang-image-format-defs.h" - }; - - bool findImageFormatByName(char const* name, ImageFormat* outFormat); - char const* getGLSLNameForImageFormat(ImageFormat format); - - // TODO(tfoley): We should ditch this enumeration - // and just use the IR opcodes that represent these - // types directly. The one major complication there - // is that the order of the enum values currently - // matters, since it determines promotion rank. - // We either need to keep that restriction, or - // look up promotion rank by some other means. - // - - class Decl; - class Val; - - // Forward-declare all syntax classes -#define SYNTAX_CLASS(NAME, BASE, ...) class NAME; -#include "slang-object-meta-begin.h" -#include "slang-syntax-defs.h" -#include "slang-object-meta-end.h" - - // Helper type for pairing up a name and the location where it appeared - struct NameLoc - { - Name* name; - SourceLoc loc; - - NameLoc() - : name(nullptr) - {} - - explicit NameLoc(Name* inName) - : name(inName) - {} - - - NameLoc(Name* inName, SourceLoc inLoc) - : name(inName) - , loc(inLoc) - {} - - NameLoc(Token const& token) - : name(token.getNameOrNull()) - , loc(token.getLoc()) - {} - }; - - struct StringSliceLoc - { - UnownedStringSlice name; - SourceLoc loc; - - StringSliceLoc() - : name(nullptr) - {} - explicit StringSliceLoc(const UnownedStringSlice& inName) - : name(inName) - {} - StringSliceLoc(const UnownedStringSlice& inName, SourceLoc inLoc) - : name(inName) - , loc(inLoc) - {} - StringSliceLoc(Token const& token) - : loc(token.getLoc()) - { - Name* tokenName = token.getNameOrNull(); - if (tokenName) - { - name = tokenName->text.getUnownedSlice(); - } - } - }; - - // Helper class for iterating over a list of heap-allocated modifiers - struct ModifierList - { - struct Iterator - { - Modifier* current; - - Modifier* operator*() - { - return current; - } - - void operator++(); -#if 0 - { - current = current->next.Ptr(); - } -#endif - - bool operator!=(Iterator other) - { - return current != other.current; - }; - - Iterator() - : current(nullptr) - {} - - Iterator(Modifier* modifier) - : current(modifier) - {} - }; - - ModifierList() - : modifiers(nullptr) - {} - - ModifierList(Modifier* modifiers) - : modifiers(modifiers) - {} - - Iterator begin() { return Iterator(modifiers); } - Iterator end() { return Iterator(nullptr); } - - Modifier* modifiers; - }; - - // Helper class for iterating over heap-allocated modifiers - // of a specific type. - template - struct FilteredModifierList - { - struct Iterator - { - Modifier* current; - - T* operator*() - { - return (T*)current; - } - - void operator++(); - #if 0 - { - current = Adjust(current->next.Ptr()); - } - #endif - - bool operator!=(Iterator other) - { - return current != other.current; - }; - - Iterator() - : current(nullptr) - {} - - Iterator(Modifier* modifier) - : current(modifier) - {} - }; - - FilteredModifierList() - : modifiers(nullptr) - {} - - FilteredModifierList(Modifier* modifiers) - : modifiers(Adjust(modifiers)) - {} - - Iterator begin() { return Iterator(modifiers); } - Iterator end() { return Iterator(nullptr); } - - static Modifier* Adjust(Modifier* modifier); - #if 0 - { - Modifier* m = modifier; - for (;;) - { - if (!m) return m; - if (dynamicCast(m)) return m; - m = m->next.Ptr(); - } - } - #endif - - Modifier* modifiers; - }; - - // A set of modifiers attached to a syntax node - struct Modifiers - { - // The first modifier in the linked list of heap-allocated modifiers - RefPtr first; - - template - FilteredModifierList getModifiersOfType() { return FilteredModifierList(first.Ptr()); } - - // Find the first modifier of a given type, or return `nullptr` if none is found. - template - T* findModifier() - { - return *getModifiersOfType().begin(); - } - - template - bool hasModifier() { return findModifier() != nullptr; } - - FilteredModifierList::Iterator begin() { return FilteredModifierList::Iterator(first.Ptr()); } - FilteredModifierList::Iterator end() { return FilteredModifierList::Iterator(nullptr); } - }; - - class NamedExpressionType; - class GenericDecl; - 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 val); - - /// Represents how much checking has been applied to a declaration. - enum class DeclCheckState : uint8_t - { - /// The declaration has been parsed, but - /// is otherwise completely unchecked. - /// - Unchecked, - - /// Basic checks on the modifiers of the declaration have been applied. - /// - /// For example, when a declaration has attributes, the transformation - /// of an attribute from the parsed-but-unchecked form into a checked - /// form (in which it has the appropriate C++ subclass) happens here. - /// - ModifiersChecked, - - /// The type/signature of the declaration has been checked. - /// - /// For a value declaration like a variable or function, this means that - /// the type of the declaration can be queried. - /// - /// For a type declaration like a `struct` or `typedef` this means - /// that a `Type` referring to that declaration can be formed. - /// - SignatureChecked, - - /// The declaration's basic signature has been checked to the point that - /// it is ready to be referenced in other places. - /// - /// For a function, this means that it has been organized into a - /// "redeclration group" if there are multiple functions with the - /// same name in a scope. - /// - ReadyForReference, - - /// The declaration is ready for lookup operations to be performed. - /// - /// For type declarations (e.g., aggregate types, generic type parameters) - /// this means that any base type or constraint clauses have been - /// sufficiently checked so that we can enumerate the inheritance - /// hierarchy of the type and discover all its members. - /// - ReadyForLookup, - - /// Any conformance declared on the declaration have been validated. - /// - /// In particular, this step means that a "witness table" has been - /// created to show how a type satisfies the requirements of any - /// interfaces it conforms to. - /// - ReadyForConformances, - - /// The declaration is fully checked. - /// - /// This step includes any validation of the declaration that is - /// immaterial to clients code using the declaration, but that is - /// nonetheless relevant to checking correctness. - /// - /// The canonical example here is checking the body of functions. - /// Client code cannot depend on *how* a function is implemented, - /// but we still need to (eventually) check the bodies of all - /// functions, so it belongs in the last phase of checking. - /// - Checked, - - // For convenience at sites that call `ensureDecl()`, we define - // some aliases for the above states that are expressed in terms - // of what client code needs to be able to do with a declaration. - // - // These aliases can be changed over time if we decide to add - // more phases to semantic checking. - - CanEnumerateBases = ReadyForLookup, - CanUseBaseOfInheritanceDecl = ReadyForLookup, - CanUseTypeOfValueDecl = ReadyForReference, - CanUseExtensionTargetType = ReadyForLookup, - CanUseAsType = ReadyForReference, - CanUseFuncSignature = ReadyForReference, - CanSpecializeGeneric = ReadyForReference, - CanReadInterfaceRequirements = ReadyForLookup, - }; - - /// A `DeclCheckState` plus a bit to track whether a declaration is currently being checked. - struct DeclCheckStateExt - { - public: - DeclCheckStateExt() {} - DeclCheckStateExt(DeclCheckState state) - : m_raw(uint8_t(state)) - {} - - enum : uint8_t - { - /// A flag to indicate that a declaration is being checked. - /// - /// The value of this flag is chosen so that it can be - /// represented in the bits of a `DeclCheckState` without - /// colliding with the bits that represent actual states. - /// - kBeingCheckedBit = 0x80, - }; - - DeclCheckState getState() const { return DeclCheckState(m_raw & ~kBeingCheckedBit); } - void setState(DeclCheckState state) - { - m_raw = (m_raw & kBeingCheckedBit) | uint8_t(state); - } - - bool isBeingChecked() const { return (m_raw & kBeingCheckedBit) != 0; } - - void setIsBeingChecked(bool isBeingChecked) - { - m_raw = (m_raw & ~kBeingCheckedBit) - | (isBeingChecked ? kBeingCheckedBit : 0); - } - - bool operator>=(DeclCheckState state) const - { - return getState() >= state; - } - - private: - uint8_t m_raw = 0; - }; - - void addModifier( - RefPtr syntax, - RefPtr modifier); - - struct QualType - { - RefPtr type; - bool IsLeftValue; - - QualType() - : IsLeftValue(false) - {} - - QualType(Type* type) - : type(type) - , IsLeftValue(false) - {} - - Type* Ptr() { return type.Ptr(); } - - operator Type*() { return type; } - operator RefPtr() { return type; } - RefPtr operator->() { return type; } - }; - - // A reference to a class of syntax node, that can be - // used to create instances on the fly - struct SyntaxClassBase - { - typedef void* (*CreateFunc)(); - - // Run-time type representation for syntax nodes - struct ClassInfo - { - typedef ClassInfo ThisType; - - /// A constant time implementation of isSubClassOf - SLANG_FORCE_INLINE bool isSubClassOf(const ThisType& super) const - { - // We include super.m_classId, because it's a subclass of itself. - return m_classId >= super.m_classId && m_classId < super.m_childrenEndClassId; - } - /// Will produce the same result as isSubClassOf, but more slowly by traversing the m_superClass - /// Works without initRange being called. - bool isSubClassOfSlow(const ThisType& super) const; - - /// This function must have been called before any dynamic casting will work (via the m_classId/m_childrenEndClassId. - /// It sets up the m_rangeStart/m_rangeEnd values to make. - /// Is called within the creation of Session - static SlangResult initRanges(); - - /// Ctor - ClassInfo(const char* name, CreateFunc createFunc, const ClassInfo* superClass); - - /// The id for this class. The children of this class are in the range of m_classId + 1 to (but not including) m_childrenEndId. - mutable uint32_t m_classId; - /// Non inclusive end of range of children. - mutable uint32_t m_childrenEndClassId; - - const ClassInfo* m_superClass; ///< The super class of this class, or nullptr if has no super class. - const char* m_name; ///< Textual class name, for debugging - CreateFunc m_createFunc; ///< Callback to use when creating instances - - ClassInfo* m_next; ///< Next in list starting from s_first - static ClassInfo* s_first; - }; - - SyntaxClassBase() - {} - - SyntaxClassBase(ClassInfo const* classInfoIn) - : classInfo(classInfoIn) - {} - - void* createInstanceImpl() const - { - auto ci = classInfo; - if (!ci) return nullptr; - - auto cf = ci->m_createFunc; - if (!cf) return nullptr; - - return cf(); - } - - SLANG_FORCE_INLINE bool isSubClassOfImpl(SyntaxClassBase const& super) const { return classInfo->isSubClassOf(*super.classInfo); } - - ClassInfo const* classInfo = nullptr; - - template - struct Impl - { - static void* createFunc(); - static const ClassInfo kClassInfo; - }; - }; - - template - struct SyntaxClass : SyntaxClassBase - { - SyntaxClass() - {} - - template - SyntaxClass(SyntaxClass const& other, - typename EnableIf::Value, void>::type* = 0) - : SyntaxClassBase(other.classInfo) - { - } - - T* createInstance() const - { - return (T*)createInstanceImpl(); - } - - SyntaxClass(const ClassInfo* classInfoIn): - SyntaxClassBase(classInfoIn) - {} - - static SyntaxClass getClass() - { - return SyntaxClass(&SyntaxClassBase::Impl::kClassInfo); - } - - template - bool isSubClassOf(SyntaxClass super) - { - return isSubClassOfImpl(super); - } - - template - bool isSubClassOf() - { - return isSubClassOf(SyntaxClass::getClass()); - } - }; - - template - SyntaxClass getClass() - { - return SyntaxClass::getClass(); - } - - template - SLANG_FORCE_INLINE T* dynamicCast(NodeBase* node); - - template - SLANG_FORCE_INLINE const T* dynamicCast(const NodeBase* node); - - template - SLANG_FORCE_INLINE T* as(NodeBase* node); - - template - SLANG_FORCE_INLINE const T* as(const NodeBase* node); - - struct SubstitutionSet - { - RefPtr substitutions; - operator Substitutions*() const - { - return substitutions; - } - - SubstitutionSet() {} - SubstitutionSet(RefPtr subst) - : substitutions(subst) - { - } - bool Equals(const SubstitutionSet& substSet) const; - int GetHashCode() const; - }; - - template - struct DeclRef; - - // A reference to a declaration, which may include - // substitutions for generic parameters. - struct DeclRefBase - { - typedef Decl DeclType; - - // The underlying declaration - Decl* decl = nullptr; - Decl* getDecl() const { return decl; } - - // Optionally, a chain of substitutions to perform - SubstitutionSet substitutions; - - DeclRefBase() - {} - - DeclRefBase(Decl* decl) - :decl(decl) - {} - - DeclRefBase(Decl* decl, SubstitutionSet subst) - :decl(decl), - substitutions(subst) - {} - - DeclRefBase(Decl* decl, RefPtr subst) - : decl(decl) - , substitutions(subst) - {} - - // Apply substitutions to a type or declaration - RefPtr Substitute(RefPtr type) const; - - DeclRefBase Substitute(DeclRefBase declRef) const; - - // Apply substitutions to an expression - RefPtr Substitute(RefPtr expr) const; - - // Apply substitutions to this declaration reference - DeclRefBase SubstituteImpl(SubstitutionSet subst, int* ioDiff); - - // Returns true if 'as' will return a valid cast - template - bool is() const { return Slang::as(decl) != nullptr; } - - // "dynamic cast" to a more specific declaration reference type - template - DeclRef as() const; - - // Check if this is an equivalent declaration reference to another - bool Equals(DeclRefBase const& declRef) const; - bool operator == (const DeclRefBase& other) const - { - return Equals(other); - } - - // Convenience accessors for common properties of declarations - Name* GetName() const; - SourceLoc getLoc() const; - DeclRefBase GetParent() const; - - int GetHashCode() const; - - // Debugging: - String toString() const; - }; - - template - struct DeclRef : DeclRefBase - { - typedef T DeclType; - - DeclRef() - {} - - DeclRef(T* decl, SubstitutionSet subst) - : DeclRefBase(decl, subst) - {} - - DeclRef(T* decl, RefPtr subst) - : DeclRefBase(decl, SubstitutionSet(subst)) - {} - - template - DeclRef(DeclRef const& other, - typename EnableIf::Value, void>::type* = 0) - : DeclRefBase(other.decl, other.substitutions) - { - } - - T* getDecl() const - { - return (T*)decl; - } - - operator T*() const - { - return getDecl(); - } - - // - static DeclRef unsafeInit(DeclRefBase const& declRef) - { - return DeclRef((T*) declRef.decl, declRef.substitutions); - } - - RefPtr Substitute(RefPtr type) const - { - return DeclRefBase::Substitute(type); - } - RefPtr Substitute(RefPtr expr) const - { - return DeclRefBase::Substitute(expr); - } - - // Apply substitutions to a type or declaration - template - DeclRef Substitute(DeclRef declRef) const - { - return DeclRef::unsafeInit(DeclRefBase::Substitute(declRef)); - } - - // Apply substitutions to this declaration reference - DeclRef SubstituteImpl(SubstitutionSet subst, int* ioDiff) - { - return DeclRef::unsafeInit(DeclRefBase::SubstituteImpl(subst, ioDiff)); - } - - DeclRef GetParent() const - { - return DeclRef::unsafeInit(DeclRefBase::GetParent()); - } - }; - - template - DeclRef DeclRefBase::as() const - { - DeclRef result; - result.decl = Slang::as(decl); - result.substitutions = substitutions; - return result; - } - - template - inline DeclRef makeDeclRef(T* decl) - { - return DeclRef(decl, nullptr); - } - - enum class MemberFilterStyle - { - All, ///< All members - Instance, ///< Only instance members - Static, ///< Only static (ie non instance) members - }; - - const RefPtr* adjustFilterCursorImpl(const SyntaxClassBase::ClassInfo& clsInfo, MemberFilterStyle filterStyle, const RefPtr* ptr, const RefPtr* end); - const RefPtr* getFilterCursorByIndexImpl(const SyntaxClassBase::ClassInfo& clsInfo, MemberFilterStyle filterStyle, const RefPtr* ptr, const RefPtr* end, Index index); - Index getFilterCountImpl(const SyntaxClassBase::ClassInfo& clsInfo, MemberFilterStyle filterStyle, const RefPtr* ptr, const RefPtr* end); - - - template - const RefPtr* adjustFilterCursor(MemberFilterStyle filterStyle, const RefPtr* ptr, const RefPtr* end) - { - return adjustFilterCursorImpl(SyntaxClassBase::Impl::kClassInfo, filterStyle, ptr, end); - } - - /// Finds the element at index. If there is no element at the index (for example has too few elements), returns nullptr. - template - const RefPtr* getFilterCursorByIndex(MemberFilterStyle filterStyle, const RefPtr* ptr, const RefPtr* end, Index index) - { - return getFilterCursorByIndexImpl(SyntaxClassBase::Impl::kClassInfo, filterStyle, ptr, end, index); - } - - template - Index getFilterCount(MemberFilterStyle filterStyle, const RefPtr* ptr, const RefPtr* end) - { - return getFilterCountImpl(SyntaxClassBase::Impl::kClassInfo, filterStyle, ptr, end); - } - - template - bool isFilterNonEmpty(MemberFilterStyle filterStyle, const RefPtr* ptr, const RefPtr* end) - { - return adjustFilterCursorImpl(SyntaxClassBase::Impl::kClassInfo, filterStyle, ptr, end) != end; - } - - template - struct FilteredMemberList - { - typedef RefPtr Element; - - FilteredMemberList() - : m_begin(nullptr) - , m_end(nullptr) - {} - - explicit FilteredMemberList( - List const& list, - MemberFilterStyle filterStyle = MemberFilterStyle::All) - : m_begin(adjustFilterCursor(filterStyle, list.begin(), list.end())) - , m_end(list.end()) - , m_filterStyle(filterStyle) - {} - - struct Iterator - { - const Element* m_cursor; - const Element* m_end; - MemberFilterStyle m_filterStyle; - - bool operator!=(Iterator const& other) const { return m_cursor != other.m_cursor; } - - void operator++() { m_cursor = adjustFilterCursor(m_filterStyle, m_cursor + 1, m_end); } - - const RefPtr& operator*() { return *(RefPtr*)(m_cursor); } - }; - - Iterator begin() - { - Iterator iter = { m_begin, m_end, m_filterStyle }; - return iter; - } - - Iterator end() - { - Iterator iter = { m_end, m_end, m_filterStyle }; - return iter; - } - - // TODO(tfoley): It is ugly to have these. - // We should probably fix the call sites instead. - const RefPtr& getFirst() { return *begin(); } - Index getCount() { return getFilterCount(m_filterStyle, m_begin, m_end); } - - RefPtr operator[](Index index) const - { - const RefPtr* ptr = getFilterCursorByIndex(m_filterStyle, m_begin, m_end, index); - SLANG_ASSERT(ptr); - return *(RefPtr*)(ptr); - } - - /// Returns true if empty (equivalent to getCount() == 0) - bool isEmpty() const - { - /// Note we don't have to scan, because m_begin has already been adjusted, when the FilteredMemberList is constructed - return m_begin == m_end; - } - /// Returns true if non empty (equivalent to getCount() != 0 but faster) - bool isNonEmpty() const { return !isEmpty(); } - - List> toArray() - { - List> result; - for (auto element : (*this)) - { - result.add(element); - } - return result; - } - - const Element* m_begin; ///< Is either equal to m_end, or points to first *valid* filtered member - const Element* m_end; - MemberFilterStyle m_filterStyle; - }; - - struct TransparentMemberInfo - { - // The declaration of the transparent member - Decl* decl; - }; - - template - struct FilteredMemberRefList - { - List> const& m_decls; - SubstitutionSet m_substitutions; - MemberFilterStyle m_filterStyle; - - FilteredMemberRefList( - List> const& decls, - SubstitutionSet substitutions, - MemberFilterStyle filterStyle = MemberFilterStyle::All) - : m_decls(decls) - , m_substitutions(substitutions) - , m_filterStyle(filterStyle) - {} - - Index getCount() const { return getFilterCount(m_filterStyle, m_decls.begin(), m_decls.end()); } - - /// True if empty (equivalent to getCount == 0, but faster) - bool isEmpty() const { return !isNonEmpty(); } - /// True if non empty (equivalent to getCount() != 0 but faster) - bool isNonEmpty() const { return isFilterNonEmpty(m_filterStyle, m_decls.begin(), m_decls.end()); } - - DeclRef operator[](Index index) const - { - const RefPtr* decl = getFilterCursorByIndex(m_filterStyle, m_decls.begin(), m_decls.end(), index); - SLANG_ASSERT(decl); - return DeclRef((T*) decl->Ptr(), m_substitutions); - } - - List> toArray() const - { - List> result; - for (auto d : *this) - result.add(d); - return result; - } - - struct Iterator - { - FilteredMemberRefList const* m_list; - const RefPtr* m_ptr; - const RefPtr* m_end; - MemberFilterStyle m_filterStyle; - - Iterator() : m_list(nullptr), m_ptr(nullptr), m_filterStyle(MemberFilterStyle::All) {} - Iterator( - FilteredMemberRefList const* list, - const RefPtr* ptr, - const RefPtr* end, - MemberFilterStyle filterStyle - ) - : m_list(list) - , m_ptr(ptr) - , m_end(end) - , m_filterStyle(filterStyle) - {} - - bool operator!=(const Iterator& other) const { return m_ptr != other.m_ptr; } - - void operator++() { m_ptr = adjustFilterCursor(m_filterStyle, m_ptr + 1, m_end); } - - DeclRef operator*() { return DeclRef((T*) m_ptr->Ptr(), m_list->m_substitutions); } - }; - - Iterator begin() const { return Iterator(this, adjustFilterCursor(m_filterStyle, m_decls.begin(), m_decls.end()), m_decls.end(), m_filterStyle); } - Iterator end() const { return Iterator(this, m_decls.end(), m_decls.end(), m_filterStyle); } - }; - - // - // type Expressions - // - - // A "type expression" is a term that we expect to resolve to a type during checking. - // We store both the original syntax and the resolved type here. - struct TypeExp - { - TypeExp() {} - TypeExp(TypeExp const& other) - : exp(other.exp) - , type(other.type) - {} - explicit TypeExp(RefPtr exp) - : exp(exp) - {} - explicit TypeExp(RefPtr type) - : type(type) - {} - TypeExp(RefPtr exp, RefPtr type) - : exp(exp) - , type(type) - {} - - RefPtr exp; - RefPtr type; - - bool Equals(Type* other); -#if 0 - { - return type->Equals(other); - } -#endif - bool Equals(RefPtr other); -#if 0 - { - return type->Equals(other.Ptr()); - } -#endif - Type* Ptr() { return type.Ptr(); } - operator Type*() - { - return type; - } - Type* operator->() { return Ptr(); } - - TypeExp Accept(SyntaxVisitor* visitor); - }; - - - - struct Scope : public RefObject - { - // The parent of this scope (where lookup should go if nothing is found locally) - RefPtr parent; - - // The next sibling of this scope (a peer for lookup) - RefPtr nextSibling; - - // The container to use for lookup - // - // Note(tfoley): This is kept as an unowned pointer - // so that a scope can't keep parts of the AST alive, - // but the opposite it allowed. - ContainerDecl* containerDecl; - }; - - // Masks to be applied when lookup up declarations - enum class LookupMask : uint8_t - { - type = 0x1, - Function = 0x2, - Value = 0x4, - Attribute = 0x8, - - Default = type | Function | Value, - }; - - // Represents one item found during lookup - struct LookupResultItem - { - // Sometimes lookup finds an item, but there were additional - // "hops" taken to reach it. We need to remember these steps - // so that if/when we consturct a full expression we generate - // appropriate AST nodes for all the steps. - // - // We build up a list of these "breadcrumbs" while doing - // lookup, and store them alongside each item found. - // - // As an example, suppose we have an HLSL `cbuffer` declaration: - // - // cbuffer C { float4 f; } - // - // This is syntax sugar for a global-scope variable of - // type `ConstantBuffer` where `T` is a `struct` containing - // all the members: - // - // struct Anon0 { float4 f; }; - // __transparent ConstantBuffer anon1; - // - // The `__transparent` modifier there captures the fact that - // when somebody writes `f` in their code, they expect it to - // "see through" the `cbuffer` declaration (or the global variable, - // in this case) and find the member inside. - // - // But when the user writes `f` we can't just create a simple - // `VarExpr` that refers directly to that field, because that - // doesn't actually reflect the required steps in a way that - // code generation can use. - // - // Instead we need to construct an expression like `(*anon1).f`, - // where there is are two additional steps in the process: - // - // 1. We needed to dereference the pointer-like type `ConstantBuffer` - // to get at a value of type `Anon0` - // 2. We needed to access a sub-field of the aggregate type `Anon0` - // - // We *could* just create these full-formed expressions during - // lookup, but this might mean creating a large number of - // AST nodes in cases where the user calls an overloaded function. - // At the very least we'd rather not heap-allocate in the common - // case where no "extra" steps need to be performed to get to - // the declarations. - // - // This is where "breadcrumbs" come in. A breadcrumb represents - // an extra "step" that must be performed to turn a declaration - // found by lookup into a valid expression to splice into the - // AST. Most of the time lookup result items don't have any - // breadcrumbs, so that no extra heap allocation takes place. - // When an item does have breadcrumbs, and it is chosen as - // the unique result (perhaps by overload resolution), then - // we can walk the list of breadcrumbs to create a full - // expression. - class Breadcrumb : public RefObject - { - public: - enum class Kind : uint8_t - { - // The lookup process looked "through" an in-scope - // declaration to the fields inside of it, so that - // even if lookup started with a simple name `f`, - // it needs to result in a member expression `obj.f`. - Member, - - // The lookup process took a pointer(-like) value, and then - // proceeded to derefence it and look at the thing(s) - // it points to instead, so that the final expression - // needs to have `(*obj)` - Deref, - - // The lookup process saw a value `obj` of type `T` and - // took into account an in-scope constraint that says - // `T` is a subtype of some other type `U`, so that - // lookup was able to find a member through type `U` - // instead. - Constraint, - - // The lookup process considered a member of an - // enclosing type as being in scope, so that any - // reference to that member needs to use a `this` - // expression as appropriate. - This, - }; - - // The kind of lookup step that was performed - Kind kind; - - // For the `Kind::This` case, what does the implicit - // `this` or `This` parameter refer to? - // - enum class ThisParameterMode : uint8_t - { - ImmutableValue, // An immutable `this` value - MutableValue, // A mutable `this` value - Type, // A `This` type - - Default = ImmutableValue, - }; - ThisParameterMode thisParameterMode = ThisParameterMode::Default; - - // As needed, a reference to the declaration that faciliated - // the lookup step. - // - // For a `Member` lookup step, this is the declaration whose - // members were implicitly pulled into scope. - // - // For a `Constraint` lookup step, this is the `ConstraintDecl` - // that serves to witness the subtype relationship. - // - DeclRef declRef; - - // The next implicit step that the lookup process took to - // arrive at a final value. - RefPtr next; - - Breadcrumb( - Kind kind, - DeclRef declRef, - RefPtr next, - ThisParameterMode thisParameterMode = ThisParameterMode::Default) - : kind(kind) - , thisParameterMode(thisParameterMode) - , declRef(declRef) - , next(next) - {} - }; - - // A properly-specialized reference to the declaration that was found. - DeclRef declRef; - - // Any breadcrumbs needed in order to turn that declaration - // reference into a well-formed expression. - // - // This is unused in the simple case where a declaration - // is being referenced directly (rather than through - // transparent members). - RefPtr breadcrumbs; - - LookupResultItem() = default; - explicit LookupResultItem(DeclRef declRef) - : declRef(declRef) - {} - LookupResultItem(DeclRef declRef, RefPtr breadcrumbs) - : declRef(declRef) - , breadcrumbs(breadcrumbs) - {} - }; - - - // Result of looking up a name in some lexical/semantic environment. - // Can be used to enumerate all the declarations matching that name, - // in the case where the result is overloaded. - struct LookupResult - { - // The one item that was found, in the smple case - LookupResultItem item; - - // All of the items that were found, in the complex case. - // Note: if there was no overloading, then this list isn't - // used at all, to avoid allocation. - List items; - - // Was at least one result found? - bool isValid() const { return item.declRef.getDecl() != nullptr; } - - bool isOverloaded() const { return items.getCount() > 1; } - - Name* getName() const - { - return items.getCount() > 1 ? items[0].declRef.GetName() : item.declRef.GetName(); - } - LookupResultItem* begin() - { - if (isValid()) - { - if (isOverloaded()) - return items.begin(); - else - return &item; - } - else - return nullptr; - } - LookupResultItem* end() - { - if (isValid()) - { - if (isOverloaded()) - return items.end(); - else - return &item + 1; - } - else - return nullptr; - } - }; - - struct SemanticsVisitor; - - struct LookupRequest - { - SemanticsVisitor* semantics = nullptr; - RefPtr scope = nullptr; - RefPtr endScope = nullptr; - - LookupMask mask = LookupMask::Default; - }; - - struct WitnessTable; - - // A value that witnesses the satisfaction of an interface - // requirement by a particular declaration or value. - struct RequirementWitness - { - RequirementWitness() - : m_flavor(Flavor::none) - {} - - RequirementWitness(DeclRef declRef) - : m_flavor(Flavor::declRef) - , m_declRef(declRef) - {} - - RequirementWitness(RefPtr val); - - RequirementWitness(RefPtr witnessTable); - - enum class Flavor - { - none, - declRef, - val, - witnessTable, - }; - - Flavor getFlavor() - { - return m_flavor; - } - - DeclRef getDeclRef() - { - SLANG_ASSERT(getFlavor() == Flavor::declRef); - return m_declRef; - } - - RefPtr getVal() - { - SLANG_ASSERT(getFlavor() == Flavor::val); - return m_obj.as(); - } - - RefPtr getWitnessTable(); - - RequirementWitness specialize(SubstitutionSet const& subst); - - Flavor m_flavor; - DeclRef m_declRef; - RefPtr m_obj; - - }; - - typedef Dictionary RequirementDictionary; - - struct WitnessTable : RefObject - { - RequirementDictionary requirementDictionary; - }; - - typedef Dictionary> AttributeArgumentValueDict; - - struct SpecializationParam - { - enum class Flavor - { - GenericType, - GenericValue, - ExistentialType, - ExistentialValue, - }; - Flavor flavor; - SourceLoc loc; - RefPtr object; - }; - typedef List SpecializationParams; - - struct SpecializationArg - { - RefPtr val; - }; - typedef List SpecializationArgs; - - struct ExpandedSpecializationArg : SpecializationArg - { - RefPtr witness; - }; - typedef List ExpandedSpecializationArgs; - - // 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 "slang-object-meta-begin.h" - -#include "slang-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: virtual const SyntaxClassBase::ClassInfo& getClassInfo() const override; \ - public: /* ... */ -#include "slang-expr-defs.h" -#include "slang-decl-defs.h" -#include "slang-modifier-defs.h" -#include "slang-stmt-defs.h" -#include "slang-type-defs.h" -#include "slang-val-defs.h" - -#include "slang-object-meta-end.h" inline RefPtr GetSub(DeclRef const& declRef) { @@ -1629,29 +268,7 @@ namespace Slang /// Get the module that a declaration is associated with, if any. Module* getModule(Decl* decl); - template - SLANG_FORCE_INLINE T* dynamicCast(NodeBase* node) - { - return (node && node->getClassInfo().isSubClassOf(SyntaxClassBase::Impl::kClassInfo)) ? static_cast(node) : nullptr; - } - - template - SLANG_FORCE_INLINE const T* dynamicCast(const NodeBase* node) - { - return (node && node->getClassInfo().isSubClassOf(SyntaxClassBase::Impl::kClassInfo)) ? static_cast(node) : nullptr; - } - - template - SLANG_FORCE_INLINE T* as(NodeBase* node) - { - return (node && node->getClassInfo().isSubClassOf(SyntaxClassBase::Impl::kClassInfo)) ? static_cast(node) : nullptr; - } - - template - SLANG_FORCE_INLINE const T* as(const NodeBase* node) - { - return (node && node->getClassInfo().isSubClassOf(SyntaxClassBase::Impl::kClassInfo)) ? static_cast(node) : nullptr; - } + } // namespace Slang diff --git a/source/slang/slang-type-defs.h b/source/slang/slang-type-defs.h deleted file mode 100644 index 356aa05d2..000000000 --- a/source/slang/slang-type-defs.h +++ /dev/null @@ -1,522 +0,0 @@ -// slang-type-defs.h - -// Syntax class definitions for types. - -// The type of a reference to an overloaded name -SYNTAX_CLASS(OverloadGroupType, Type) -RAW( -public: - virtual String ToString() override; - -protected: - virtual bool EqualsImpl(Type * type) override; - virtual RefPtr 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, Type) -RAW( - virtual String ToString() override; - -protected: - virtual bool EqualsImpl(Type * type) override; - virtual RefPtr CreateCanonicalType() override; - virtual int GetHashCode() override; -) -END_SYNTAX_CLASS() - -// The type of an expression that was erroneous -SYNTAX_CLASS(ErrorType, Type) -RAW( -public: - virtual String ToString() override; - -protected: - virtual bool EqualsImpl(Type * type) override; - virtual RefPtr SubstituteImpl(SubstitutionSet subst, int* ioDiff) override; - virtual RefPtr CreateCanonicalType() override; - virtual int GetHashCode() override; -) -END_SYNTAX_CLASS() - -// A type that takes the form of a reference to some declaration -SYNTAX_CLASS(DeclRefType, Type) - DECL_FIELD(DeclRef, declRef) - -RAW( - virtual String ToString() override; - virtual RefPtr SubstituteImpl(SubstitutionSet subst, int* ioDiff) override; - - static RefPtr Create( - Session* session, - DeclRef declRef); - - DeclRefType() - {} - DeclRefType( - DeclRef declRef) - : declRef(declRef) - {} -protected: - virtual int GetHashCode() override; - virtual bool EqualsImpl(Type * type) override; - virtual RefPtr CreateCanonicalType() override; -) -END_SYNTAX_CLASS() - -// Base class for types that can be used in arithmetic expressions -ABSTRACT_SYNTAX_CLASS(ArithmeticExpressionType, DeclRefType) -RAW( -public: - virtual BasicExpressionType* GetScalarType() = 0; -) -END_SYNTAX_CLASS() - -SYNTAX_CLASS(BasicExpressionType, ArithmeticExpressionType) - - FIELD(BaseType, baseType) - -RAW( - BasicExpressionType() {} - BasicExpressionType( - Slang::BaseType baseType) - : baseType(baseType) - {} -protected: - virtual BasicExpressionType* GetScalarType() override; - virtual bool EqualsImpl(Type * type) override; - virtual RefPtr CreateCanonicalType() override; -) -END_SYNTAX_CLASS() - -// Base type for things that are built in to the compiler, -// and will usually have special behavior or a custom -// mapping to the IR level. -ABSTRACT_SYNTAX_CLASS(BuiltinType, DeclRefType) -END_SYNTAX_CLASS() - -// Resources that contain "elements" that can be fetched -ABSTRACT_SYNTAX_CLASS(ResourceType, BuiltinType) - // The type that results from fetching an element from this resource - SYNTAX_FIELD(RefPtr, elementType) - - // Shape and access level information for this resource type - FIELD(TextureFlavor, flavor) - - RAW( - TextureFlavor::Shape GetBaseShape() - { - return flavor.GetBaseShape(); - } - bool isMultisample() { return flavor.isMultisample(); } - bool isArray() { return flavor.isArray(); } - SlangResourceShape getShape() const { return flavor.getShape(); } - SlangResourceAccess getAccess() { return flavor.getAccess(); } - - ) -END_SYNTAX_CLASS() - -ABSTRACT_SYNTAX_CLASS(TextureTypeBase, ResourceType) -RAW( - TextureTypeBase() - {} - TextureTypeBase( - TextureFlavor flavor, - RefPtr elementType) - { - this->elementType = elementType; - this->flavor = flavor; - } -) -END_SYNTAX_CLASS() - -SYNTAX_CLASS(TextureType, TextureTypeBase) -RAW( - TextureType() - {} - TextureType( - TextureFlavor flavor, - RefPtr 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() - {} - TextureSamplerType( - TextureFlavor flavor, - RefPtr 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() - {} - GLSLImageType( - TextureFlavor flavor, - RefPtr elementType) - : TextureTypeBase(flavor, elementType) - {} -) -END_SYNTAX_CLASS() - -SYNTAX_CLASS(SamplerStateType, BuiltinType) - // What flavor of sampler state is this - FIELD(SamplerStateFlavor, flavor) -END_SYNTAX_CLASS() - -// Other cases of generic types known to the compiler -SYNTAX_CLASS(BuiltinGenericType, BuiltinType) - SYNTAX_FIELD(RefPtr, elementType) - - RAW(Type* getElementType() { return 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) - -// HLSL buffer-type resources - -SIMPLE_SYNTAX_CLASS(HLSLStructuredBufferTypeBase, BuiltinGenericType) -SIMPLE_SYNTAX_CLASS(HLSLStructuredBufferType, HLSLStructuredBufferTypeBase) -SIMPLE_SYNTAX_CLASS(HLSLRWStructuredBufferType, HLSLStructuredBufferTypeBase) -SIMPLE_SYNTAX_CLASS(HLSLRasterizerOrderedStructuredBufferType, HLSLStructuredBufferTypeBase) - -SIMPLE_SYNTAX_CLASS(UntypedBufferResourceType, BuiltinType) -SIMPLE_SYNTAX_CLASS(HLSLByteAddressBufferType, UntypedBufferResourceType) -SIMPLE_SYNTAX_CLASS(HLSLRWByteAddressBufferType, UntypedBufferResourceType) -SIMPLE_SYNTAX_CLASS(HLSLRasterizerOrderedByteAddressBufferType, UntypedBufferResourceType) -SIMPLE_SYNTAX_CLASS(RaytracingAccelerationStructureType, UntypedBufferResourceType) - -SIMPLE_SYNTAX_CLASS(HLSLAppendStructuredBufferType, HLSLStructuredBufferTypeBase) -SIMPLE_SYNTAX_CLASS(HLSLConsumeStructuredBufferType, HLSLStructuredBufferTypeBase) - -SYNTAX_CLASS(HLSLPatchType, BuiltinType) -RAW( - Type* 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, BuiltinType) - -// Base class for types used when desugaring parameter block -// declarations, includeing HLSL `cbuffer` or GLSL `uniform` blocks. -SIMPLE_SYNTAX_CLASS(ParameterGroupType, PointerLikeType) - -SIMPLE_SYNTAX_CLASS(UniformParameterGroupType, ParameterGroupType) -SIMPLE_SYNTAX_CLASS(VaryingParameterGroupType, ParameterGroupType) - -// type for HLSL `cbuffer` declarations, and `ConstantBuffer` -// ALso used for GLSL `uniform` blocks. -SIMPLE_SYNTAX_CLASS(ConstantBufferType, UniformParameterGroupType) - -// type for HLSL `tbuffer` declarations, and `TextureBuffer` -SIMPLE_SYNTAX_CLASS(TextureBufferType, UniformParameterGroupType) - -// type for GLSL `in` and `out` blocks -SIMPLE_SYNTAX_CLASS(GLSLInputParameterGroupType, VaryingParameterGroupType) -SIMPLE_SYNTAX_CLASS(GLSLOutputParameterGroupType, VaryingParameterGroupType) - -// type for GLLSL `buffer` blocks -SIMPLE_SYNTAX_CLASS(GLSLShaderStorageBufferType, UniformParameterGroupType) - -// type for Slang `ParameterBlock` type -SIMPLE_SYNTAX_CLASS(ParameterBlockType, UniformParameterGroupType) - -SYNTAX_CLASS(ArrayExpressionType, Type) - SYNTAX_FIELD(RefPtr, baseType) - SYNTAX_FIELD(RefPtr, ArrayLength) - -RAW( - virtual Slang::String ToString() override; - -protected: - virtual bool EqualsImpl(Type * type) override; - virtual RefPtr CreateCanonicalType() override; - virtual RefPtr SubstituteImpl(SubstitutionSet subst, int* ioDiff) 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, Type) - // The type that this is the type of... - SYNTAX_FIELD(RefPtr, type) - -RAW( -public: - TypeType() - {} - TypeType(RefPtr type) - : type(type) - {} - - virtual String ToString() override; - -protected: - virtual bool EqualsImpl(Type * type) override; - virtual RefPtr CreateCanonicalType() override; - virtual int GetHashCode() override; -) -END_SYNTAX_CLASS() - -// A vector type, e.g., `vector` -SYNTAX_CLASS(VectorExpressionType, ArithmeticExpressionType) - - // The type of vector elements. - // As an invariant, this should be a basic type or an alias. - SYNTAX_FIELD(RefPtr, elementType) - - // The number of elements - SYNTAX_FIELD(RefPtr, elementCount) - -RAW( - virtual String ToString() override; - -protected: - virtual BasicExpressionType* GetScalarType() override; -) -END_SYNTAX_CLASS() - -// A matrix type, e.g., `matrix` -SYNTAX_CLASS(MatrixExpressionType, ArithmeticExpressionType) -RAW( - - Type* getElementType(); - IntVal* getRowCount(); - IntVal* getColumnCount(); - - RefPtr getRowType(); - - virtual String ToString() override; - -protected: - virtual BasicExpressionType* GetScalarType() override; - -private: - RefPtr mRowType; -) -END_SYNTAX_CLASS() - -// The built-in `String` type -SIMPLE_SYNTAX_CLASS(StringType, BuiltinType) - -// Type built-in `__EnumType` type -SYNTAX_CLASS(EnumTypeType, BuiltinType) - -// TODO: provide accessors for the declaration, the "tag" type, etc. - -END_SYNTAX_CLASS() - -// Base class for types that map down to -// simple pointers as part of code generation. -SYNTAX_CLASS(PtrTypeBase, BuiltinType) -RAW( - // Get the type of the pointed-to value. - Type* getValueType(); -) -END_SYNTAX_CLASS() - -// A true (user-visible) pointer type, e.g., `T*` -SYNTAX_CLASS(PtrType, PtrTypeBase) -END_SYNTAX_CLASS() - -// A type that represents the behind-the-scenes -// logical pointer that is passed for an `out` -// or `in out` parameter -SYNTAX_CLASS(OutTypeBase, PtrTypeBase) -END_SYNTAX_CLASS() - -// The type for an `out` parameter, e.g., `out T` -SYNTAX_CLASS(OutType, OutTypeBase) -END_SYNTAX_CLASS() - -// The type for an `in out` parameter, e.g., `in out T` -SYNTAX_CLASS(InOutType, OutTypeBase) -END_SYNTAX_CLASS() - -// The type for an `ref` parameter, e.g., `ref T` -SYNTAX_CLASS(RefType, PtrTypeBase) -END_SYNTAX_CLASS() - -// A type alias of some kind (e.g., via `typedef`) -SYNTAX_CLASS(NamedExpressionType, Type) -DECL_FIELD(DeclRef, declRef) - -RAW( - RefPtr innerType; - NamedExpressionType() - {} - NamedExpressionType( - DeclRef declRef) - : declRef(declRef) - {} - - - virtual String ToString() override; - -protected: - virtual bool EqualsImpl(Type * type) override; - virtual RefPtr CreateCanonicalType() override; - virtual int GetHashCode() override; -) -END_SYNTAX_CLASS() - -// A function type is defined by its parameter types -// and its result type. -SYNTAX_CLASS(FuncType, Type) - - // TODO: We may want to preserve parameter names - // in the list here, just so that we can print - // out friendly names when printing a function - // type, even if they don't affect the actual - // semantic type underneath. - - FIELD(List>, paramTypes) - FIELD(RefPtr, resultType) -RAW( - FuncType() - {} - - UInt getParamCount() { return paramTypes.getCount(); } - Type* getParamType(UInt index) { return paramTypes[index]; } - Type* getResultType() { return resultType; } - - virtual String ToString() override; -protected: - virtual RefPtr SubstituteImpl(SubstitutionSet subst, int* ioDiff) override; - virtual bool EqualsImpl(Type * type) override; - virtual RefPtr CreateCanonicalType() override; - virtual int GetHashCode() override; -) -END_SYNTAX_CLASS() - -// The "type" of an expression that names a generic declaration. -SYNTAX_CLASS(GenericDeclRefType, Type) - - DECL_FIELD(DeclRef, declRef) - - RAW( - GenericDeclRefType() - {} - GenericDeclRefType( - DeclRef declRef) - : declRef(declRef) - {} - - - DeclRef const& GetDeclRef() const { return declRef; } - - virtual String ToString() override; - -protected: - virtual bool EqualsImpl(Type * type) override; - virtual int GetHashCode() override; - virtual RefPtr CreateCanonicalType() override; -) -END_SYNTAX_CLASS() - -// The "type" of a reference to a module or namespace -SYNTAX_CLASS(NamespaceType, Type) - DECL_FIELD(DeclRef, m_declRef) - -RAW( - NamespaceType() - {} - - DeclRef const& getDeclRef() const { return m_declRef; } - - virtual String ToString() override; - -protected: - virtual bool EqualsImpl(Type * type) override; - virtual int GetHashCode() override; - virtual RefPtr CreateCanonicalType() override; -) -END_SYNTAX_CLASS() - -// The concrete type for a value wrapped in an existential, accessible -// when the existential is "opened" in some context. -SYNTAX_CLASS(ExtractExistentialType, Type) -RAW( - DeclRef declRef; - - virtual String ToString() override; - virtual bool EqualsImpl(Type * type) override; - virtual int GetHashCode() override; - virtual RefPtr CreateCanonicalType() override; - virtual RefPtr SubstituteImpl(SubstitutionSet subst, int* ioDiff) override; -) -END_SYNTAX_CLASS() - - /// A tagged union of zero or more other types. -SYNTAX_CLASS(TaggedUnionType, Type) -RAW( - /// The distinct "cases" the tagged union can store. - /// - /// For each type in this array, the array index is the - /// tag value for that case. - /// - List> caseTypes; - - virtual String ToString() override; - virtual bool EqualsImpl(Type * type) override; - virtual int GetHashCode() override; - virtual RefPtr CreateCanonicalType() override; - virtual RefPtr SubstituteImpl(SubstitutionSet subst, int* ioDiff) override; -) -END_SYNTAX_CLASS() - -SYNTAX_CLASS(ExistentialSpecializedType, Type) -RAW( - RefPtr baseType; - ExpandedSpecializationArgs args; - - virtual String ToString() override; - virtual bool EqualsImpl(Type * type) override; - virtual int GetHashCode() override; - virtual RefPtr CreateCanonicalType() override; - virtual RefPtr SubstituteImpl(SubstitutionSet subst, int* ioDiff) override; -) -END_SYNTAX_CLASS() - - /// The type of `this` within a polymorphic declaration -SYNTAX_CLASS(ThisType, Type) -RAW( - DeclRef interfaceDeclRef; - - virtual String ToString() override; - virtual bool EqualsImpl(Type * type) override; - virtual int GetHashCode() override; - virtual RefPtr CreateCanonicalType() override; - virtual RefPtr SubstituteImpl(SubstitutionSet subst, int* ioDiff) override; -) -END_SYNTAX_CLASS() diff --git a/source/slang/slang-val-defs.h b/source/slang/slang-val-defs.h deleted file mode 100644 index 5024554d4..000000000 --- a/source/slang/slang-val-defs.h +++ /dev/null @@ -1,173 +0,0 @@ -// slang-val-defs.h - -// Syntax class definitions for compile-time values. - -// A compile-time integer (may not have a specific concrete value) -ABSTRACT_SYNTAX_CLASS(IntVal, Val) -END_SYNTAX_CLASS() - -// Trivial case of a value that is just a constant integer -SYNTAX_CLASS(ConstantIntVal, IntVal) - FIELD(IntegerLiteralValue, value) - - RAW( - ConstantIntVal() - {} - 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, declRef) - - RAW( - GenericParamIntVal() - {} - GenericParamIntVal(DeclRef declRef) - : declRef(declRef) - {} - - virtual bool EqualsVal(Val* val) override; - virtual String ToString() override; - virtual int GetHashCode() override; - virtual RefPtr SubstituteImpl(SubstitutionSet subst, int* ioDiff) override; -) -END_SYNTAX_CLASS() - - /// An unknown integer value indicating an erroneous sub-expression -SYNTAX_CLASS(ErrorIntVal, IntVal) - - // TODO: We should probably eventually just have an `ErrorVal` here - // and have all `Val`s that represent ordinary values hold their - // `Type` so that we can have an `ErrorVal` of any type. - - RAW( - ErrorIntVal() - {} - - virtual bool EqualsVal(Val* val) override; - virtual String ToString() override; - virtual int GetHashCode() override; - virtual RefPtr SubstituteImpl(SubstitutionSet subst, int* ioDiff) override; -) -END_SYNTAX_CLASS() - -// A witness to the fact that some proposition is true, encoded -// at the level of the type system. -// -// Given a generic like: -// -// void example(L light) -// where L : ILight -// { ... } -// -// a call to `example()` needs two things for us to be sure -// it is valid: -// -// 1. We need a type `X` to use as the argument for the -// parameter `L`. We might supply this explicitly, or -// via inference. -// -// 2. We need a *proof* that whatever `X` we chose conforms -// to the `ILight` interface. -// -// The easiest way to make such a proof is by construction, -// and a `Witness` represents such a constructive proof. -// Conceptually a proposition like `X : ILight` can be -// seen as a type, and witness prooving that proposition -// is a value of that type. -// -// We construct and store witnesses explicitly during -// semantic checking because they can help us with -// generating downstream code. By following the structure -// of a witness (the structure of a proof) we can, e.g., -// navigate from the knowledge that `X : ILight` to -// the concrete declarations that provide the implementation -// of `ILight` for `X`. -// -ABSTRACT_SYNTAX_CLASS(Witness, Val) -END_SYNTAX_CLASS() - -// A witness that one type is a subtype of another -// (where by "subtype" we include both inheritance -// relationships and type-conforms-to-interface relationships) -// -// TODO: we may need to tease those apart. -ABSTRACT_SYNTAX_CLASS(SubtypeWitness, Witness) - FIELD(RefPtr, sub) - FIELD(RefPtr, sup) -END_SYNTAX_CLASS() - -SYNTAX_CLASS(TypeEqualityWitness, SubtypeWitness) -RAW( - virtual bool EqualsVal(Val* val) override; - virtual String ToString() override; - virtual int GetHashCode() override; - virtual RefPtr SubstituteImpl(SubstitutionSet subst, int * ioDiff) override; -) -END_SYNTAX_CLASS() -// A witness that one type is a subtype of another -// because some in-scope declaration says so -SYNTAX_CLASS(DeclaredSubtypeWitness, SubtypeWitness) - FIELD(DeclRef, declRef); -RAW( - virtual bool EqualsVal(Val* val) override; - virtual String ToString() override; - virtual int GetHashCode() override; - virtual RefPtr SubstituteImpl(SubstitutionSet subst, int * ioDiff) override; -) -END_SYNTAX_CLASS() - -// A witness that `sub : sup` because `sub : mid` and `mid : sup` -SYNTAX_CLASS(TransitiveSubtypeWitness, SubtypeWitness) - // Witness that `sub : mid` - FIELD(RefPtr, subToMid); - - // Witness that `mid : sup` - FIELD(DeclRef, midToSup); -RAW( - virtual bool EqualsVal(Val* val) override; - virtual String ToString() override; - virtual int GetHashCode() override; - virtual RefPtr SubstituteImpl(SubstitutionSet subst, int * ioDiff) override; -) -END_SYNTAX_CLASS() - -// A witness taht `sub : sup` because `sub` was wrapped into -// an existential of type `sup`. -SYNTAX_CLASS(ExtractExistentialSubtypeWitness, SubtypeWitness) -RAW( - // The declaration of the existential value that has been opened - DeclRef declRef; - - virtual bool EqualsVal(Val* val) override; - virtual String ToString() override; - virtual int GetHashCode() override; - virtual RefPtr SubstituteImpl(SubstitutionSet subst, int * ioDiff) override; -) -END_SYNTAX_CLASS() - -// A witness that `sub : sup`, because `sub` is a tagged union -// of the form `A | B | C | ...` and each of `A : sup`, -// `B : sup`, `C : sup`, etc. -// -SYNTAX_CLASS(TaggedUnionSubtypeWitness, SubtypeWitness) -RAW( - // Witnesses that each of the "case" types in the union - // is a subtype of `sup`. - // - List> caseWitnesses; - - virtual bool EqualsVal(Val* val) override; - virtual String ToString() override; - virtual int GetHashCode() override; - virtual RefPtr SubstituteImpl(SubstitutionSet subst, int * ioDiff) override; -) -END_SYNTAX_CLASS() diff --git a/source/slang/slang-visitor.h b/source/slang/slang-visitor.h index c6d63cd40..449fda917 100644 --- a/source/slang/slang-visitor.h +++ b/source/slang/slang-visitor.h @@ -7,21 +7,52 @@ #include "slang-syntax.h" +#include "slang-ast-generated-macro.h" + namespace Slang { +// Macros to generate from ast-generated-macro file the vistors + +// Only runs 'param' macro if the marker is NONE (ie not ABSTRACT here) +#define SLANG_CLASS_ONLY_ABSTRACT(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) +#define SLANG_CLASS_ONLY_NONE(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) param(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) + +#define SLANG_CLASS_ONLY(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) SLANG_CLASS_ONLY_##MARKER(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) + +// Dispatch decl +#define SLANG_VISITOR_DISPATCH_DECL(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \ + virtual void dispatch_##NAME(NAME* obj, void* extra) = 0; + +// Dispatch + +#define SLANG_VISITOR_DISPATCH_RESULT_IMPL(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \ + virtual void dispatch_##NAME(NAME* obj, void* extra) override { *(Result*)extra = ((Derived*) this)->visit##NAME(obj); } + +#define SLANG_VISITOR_DISPATCH_VOID_IMPL(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \ + virtual void dispatch_##NAME(NAME* obj, void*) override { ((Derived*) this)->visit##NAME(obj); } + +// Visitor with and without result + +#define SLANG_VISITOR_RESULT_VISIT_IMPL(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \ + Result visit##NAME(NAME* obj) { return ((Derived*) this)->visit##SUPER(obj); } \ + +#define SLANG_VISITOR_VOID_VISIT_IMPL(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \ + void visit##NAME(NAME* obj) { ((Derived*) this)->visit##SUPER(obj); } + +// Args + +#define SLANG_VISITOR_DISPATCH_ARG_IMPL(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \ + virtual void dispatch_##NAME(NAME* obj, void* arg) override { ((Derived*) this)->visit##NAME(obj, *(Arg*)arg); } + +#define SLANG_VISITOR_VOID_VISIT_ARG_IMPL(NAME, SUPER, ORIGIN, LAST, MARKER, TYPE, param) \ + void visit##NAME(NAME* obj, Arg const& arg) { ((Derived*) this)->visit##SUPER(obj, arg); } // // 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 "slang-object-meta-begin.h" -#include "slang-type-defs.h" -#include "slang-object-meta-end.h" + SLANG_CHILDREN_ASTNode_Type(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_DECL) }; template @@ -41,23 +72,8 @@ struct TypeVisitor : Base 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##NAME(obj); } - -#include "slang-object-meta-begin.h" -#include "slang-type-defs.h" -#include "slang-object-meta-end.h" - -#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE) -#define SYNTAX_CLASS(NAME, BASE) \ - Result visit##NAME(NAME* obj) \ - { return ((Derived*) this)->visit##BASE(obj); } - -#include "slang-object-meta-begin.h" -#include "slang-type-defs.h" -#include "slang-object-meta-end.h" + SLANG_CHILDREN_ASTNode_Type(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_RESULT_IMPL) + SLANG_CHILDREN_ASTNode_Type(SLANG_VISITOR_RESULT_VISIT_IMPL, _) }; template @@ -73,23 +89,8 @@ struct TypeVisitor : Base 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##NAME(obj); } - -#include "slang-object-meta-begin.h" -#include "slang-type-defs.h" -#include "slang-object-meta-end.h" - -#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE) -#define SYNTAX_CLASS(NAME, BASE) \ - void visit##NAME(NAME* obj) \ - { ((Derived*) this)->visit##BASE(obj); } - -#include "slang-object-meta-begin.h" -#include "slang-type-defs.h" -#include "slang-object-meta-end.h" + SLANG_CHILDREN_ASTNode_Type(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_VOID_IMPL) + SLANG_CHILDREN_ASTNode_Type(SLANG_VISITOR_VOID_VISIT_IMPL, _) }; template @@ -100,23 +101,8 @@ struct TypeVisitorWithArg : Base type->accept(this, (void*)&arg); } -#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */ -#define SYNTAX_CLASS(NAME, BASE) \ - virtual void dispatch_##NAME(NAME* obj, void* arg) override \ - { ((Derived*) this)->visit##NAME(obj, *(Arg*)arg); } - -#include "slang-object-meta-begin.h" -#include "slang-type-defs.h" -#include "slang-object-meta-end.h" - -#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE) -#define SYNTAX_CLASS(NAME, BASE) \ - void visit##NAME(NAME* obj, Arg const& arg) \ - { ((Derived*) this)->visit##BASE(obj, arg); } - -#include "slang-object-meta-begin.h" -#include "slang-type-defs.h" -#include "slang-object-meta-end.h" + SLANG_CHILDREN_ASTNode_Type(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_ARG_IMPL) + SLANG_CHILDREN_ASTNode_Type(SLANG_VISITOR_VOID_VISIT_ARG_IMPL, _) }; // @@ -125,13 +111,7 @@ struct TypeVisitorWithArg : Base struct IExprVisitor { -#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */ -#define SYNTAX_CLASS(NAME, BASE) \ - virtual void dispatch_##NAME(NAME* obj, void* extra) = 0; - -#include "slang-object-meta-begin.h" -#include "slang-expr-defs.h" -#include "slang-object-meta-end.h" + SLANG_CHILDREN_ASTNode_Expr(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_DECL) }; template @@ -144,23 +124,8 @@ struct ExprVisitor : IExprVisitor 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##NAME(obj); } - -#include "slang-object-meta-begin.h" -#include "slang-expr-defs.h" -#include "slang-object-meta-end.h" - -#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE) -#define SYNTAX_CLASS(NAME, BASE) \ - Result visit##NAME(NAME* obj) \ - { return ((Derived*) this)->visit##BASE(obj); } - -#include "slang-object-meta-begin.h" -#include "slang-expr-defs.h" -#include "slang-object-meta-end.h" + SLANG_CHILDREN_ASTNode_Expr(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_RESULT_IMPL) + SLANG_CHILDREN_ASTNode_Expr(SLANG_VISITOR_RESULT_VISIT_IMPL, _) }; template @@ -171,23 +136,8 @@ struct ExprVisitor : IExprVisitor 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##NAME(obj); } - -#include "slang-object-meta-begin.h" -#include "slang-expr-defs.h" -#include "slang-object-meta-end.h" - -#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE) -#define SYNTAX_CLASS(NAME, BASE) \ - void visit##NAME(NAME* obj) \ - { ((Derived*) this)->visit##BASE(obj); } - -#include "slang-object-meta-begin.h" -#include "slang-expr-defs.h" -#include "slang-object-meta-end.h" + SLANG_CHILDREN_ASTNode_Expr(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_VOID_IMPL) + SLANG_CHILDREN_ASTNode_Expr(SLANG_VISITOR_VOID_VISIT_IMPL, _) }; template @@ -198,23 +148,8 @@ struct ExprVisitorWithArg : IExprVisitor obj->accept(this, (void*)&arg); } -#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */ -#define SYNTAX_CLASS(NAME, BASE) \ - virtual void dispatch_##NAME(NAME* obj, void* arg) override \ - { ((Derived*) this)->visit##NAME(obj, *(Arg*)arg); } - -#include "slang-object-meta-begin.h" -#include "slang-expr-defs.h" -#include "slang-object-meta-end.h" - -#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE) -#define SYNTAX_CLASS(NAME, BASE) \ - void visit##NAME(NAME* obj, Arg const& arg) \ - { ((Derived*) this)->visit##BASE(obj, arg); } - -#include "slang-object-meta-begin.h" -#include "slang-expr-defs.h" -#include "slang-object-meta-end.h" + SLANG_CHILDREN_ASTNode_Expr(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_ARG_IMPL) + SLANG_CHILDREN_ASTNode_Expr(SLANG_VISITOR_VOID_VISIT_ARG_IMPL, _) }; // @@ -223,13 +158,7 @@ struct ExprVisitorWithArg : IExprVisitor struct IStmtVisitor { -#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */ -#define SYNTAX_CLASS(NAME, BASE) \ - virtual void dispatch_##NAME(NAME* obj, void* extra) = 0; - -#include "slang-object-meta-begin.h" -#include "slang-stmt-defs.h" -#include "slang-object-meta-end.h" + SLANG_CHILDREN_ASTNode_Stmt(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_DECL) }; template @@ -242,23 +171,8 @@ struct StmtVisitor : IStmtVisitor 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##NAME(obj); } - -#include "slang-object-meta-begin.h" -#include "slang-stmt-defs.h" -#include "slang-object-meta-end.h" - -#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE) -#define SYNTAX_CLASS(NAME, BASE) \ - Result visit##NAME(NAME* obj) \ - { return ((Derived*) this)->visit##BASE(obj); } - -#include "slang-object-meta-begin.h" -#include "slang-stmt-defs.h" -#include "slang-object-meta-end.h" + SLANG_CHILDREN_ASTNode_Stmt(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_RESULT_IMPL) + SLANG_CHILDREN_ASTNode_Stmt(SLANG_VISITOR_RESULT_VISIT_IMPL, _) }; template @@ -269,23 +183,8 @@ struct StmtVisitor : IStmtVisitor 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##NAME(obj); } - -#include "slang-object-meta-begin.h" -#include "slang-stmt-defs.h" -#include "slang-object-meta-end.h" - -#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE) -#define SYNTAX_CLASS(NAME, BASE) \ - void visit##NAME(NAME* obj) \ - { ((Derived*) this)->visit##BASE(obj); } - -#include "slang-object-meta-begin.h" -#include "slang-stmt-defs.h" -#include "slang-object-meta-end.h" + SLANG_CHILDREN_ASTNode_Stmt(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_VOID_IMPL) + SLANG_CHILDREN_ASTNode_Stmt(SLANG_VISITOR_VOID_VISIT_IMPL, _) }; // @@ -294,13 +193,7 @@ struct StmtVisitor : IStmtVisitor struct IDeclVisitor { -#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */ -#define SYNTAX_CLASS(NAME, BASE) \ - virtual void dispatch_##NAME(NAME* obj, void* extra) = 0; - -#include "slang-object-meta-begin.h" -#include "slang-decl-defs.h" -#include "slang-object-meta-end.h" + SLANG_CHILDREN_ASTNode_DeclBase(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_DECL) }; template @@ -313,23 +206,8 @@ struct DeclVisitor : IDeclVisitor 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##NAME(obj); } - -#include "slang-object-meta-begin.h" -#include "slang-decl-defs.h" -#include "slang-object-meta-end.h" - -#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE) -#define SYNTAX_CLASS(NAME, BASE) \ - Result visit##NAME(NAME* obj) \ - { return ((Derived*) this)->visit##BASE(obj); } - -#include "slang-object-meta-begin.h" -#include "slang-decl-defs.h" -#include "slang-object-meta-end.h" + SLANG_CHILDREN_ASTNode_DeclBase(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_RESULT_IMPL) + SLANG_CHILDREN_ASTNode_DeclBase(SLANG_VISITOR_RESULT_VISIT_IMPL, _) }; template @@ -340,23 +218,8 @@ struct DeclVisitor : IDeclVisitor 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##NAME(obj); } - -#include "slang-object-meta-begin.h" -#include "slang-decl-defs.h" -#include "slang-object-meta-end.h" - -#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE) -#define SYNTAX_CLASS(NAME, BASE) \ - void visit##NAME(NAME* obj) \ - { ((Derived*) this)->visit##BASE(obj); } - -#include "slang-object-meta-begin.h" -#include "slang-decl-defs.h" -#include "slang-object-meta-end.h" + SLANG_CHILDREN_ASTNode_DeclBase(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_VOID_IMPL) + SLANG_CHILDREN_ASTNode_DeclBase(SLANG_VISITOR_VOID_VISIT_IMPL, _) }; template @@ -367,23 +230,8 @@ struct DeclVisitorWithArg : IDeclVisitor obj->accept(this, (void*)&arg); } -#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */ -#define SYNTAX_CLASS(NAME, BASE) \ - virtual void dispatch_##NAME(NAME* obj, void* arg) override \ - { ((Derived*) this)->visit##NAME(obj, *(Arg*)arg); } - -#include "slang-object-meta-begin.h" -#include "slang-decl-defs.h" -#include "slang-object-meta-end.h" - -#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE) -#define SYNTAX_CLASS(NAME, BASE) \ - void visit##NAME(NAME* obj, Arg const& arg) \ - { ((Derived*) this)->visit##BASE(obj, arg); } - -#include "slang-object-meta-begin.h" -#include "slang-decl-defs.h" -#include "slang-object-meta-end.h" + SLANG_CHILDREN_ASTNode_DeclBase(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_ARG_IMPL) + SLANG_CHILDREN_ASTNode_DeclBase(SLANG_VISITOR_VOID_VISIT_ARG_IMPL, _) }; @@ -393,13 +241,7 @@ struct DeclVisitorWithArg : IDeclVisitor struct IModifierVisitor { -#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) /* empty */ -#define SYNTAX_CLASS(NAME, BASE) \ - virtual void dispatch_##NAME(NAME* obj, void* extra) = 0; - -#include "slang-object-meta-begin.h" -#include "slang-modifier-defs.h" -#include "slang-object-meta-end.h" + SLANG_CHILDREN_ASTNode_Modifier(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_DECL) }; template @@ -412,23 +254,8 @@ struct ModifierVisitor : IModifierVisitor 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##NAME(obj); } - -#include "slang-object-meta-begin.h" -#include "slang-modifier-defs.h" -#include "slang-object-meta-end.h" - -#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE) -#define SYNTAX_CLASS(NAME, BASE) \ - Result visit##NAME(NAME* obj) \ - { return ((Derived*) this)->visit##BASE(obj); } - -#include "slang-object-meta-begin.h" -#include "slang-modifier-defs.h" -#include "slang-object-meta-end.h" + SLANG_CHILDREN_ASTNode_Modifier(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_RESULT_IMPL) + SLANG_CHILDREN_ASTNode_Modifier(SLANG_VISITOR_RESULT_VISIT_IMPL, _) }; template @@ -439,23 +266,8 @@ struct ModifierVisitor : IModifierVisitor 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##NAME(obj); } - -#include "slang-object-meta-begin.h" -#include "slang-modifier-defs.h" -#include "slang-object-meta-end.h" - -#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE) -#define SYNTAX_CLASS(NAME, BASE) \ - void visit##NAME(NAME* obj) \ - { ((Derived*) this)->visit##BASE(obj); } - -#include "slang-object-meta-begin.h" -#include "slang-modifier-defs.h" -#include "slang-object-meta-end.h" + SLANG_CHILDREN_ASTNode_Modifier(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_VOID_IMPL) + SLANG_CHILDREN_ASTNode_Modifier(SLANG_VISITOR_VOID_VISIT_IMPL, _) }; // @@ -464,13 +276,7 @@ struct ModifierVisitor : IModifierVisitor 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 "slang-object-meta-begin.h" -#include "slang-val-defs.h" -#include "slang-object-meta-end.h" + SLANG_CHILDREN_ASTNode_Val(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_DECL) }; template @@ -483,23 +289,8 @@ struct ValVisitor : TypeVisitor 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##NAME(obj); } - -#include "slang-object-meta-begin.h" -#include "slang-val-defs.h" -#include "slang-object-meta-end.h" - -#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE) -#define SYNTAX_CLASS(NAME, BASE) \ - Result visit##NAME(NAME* obj) \ - { return ((Derived*) this)->visit##BASE(obj); } - -#include "slang-object-meta-begin.h" -#include "slang-val-defs.h" -#include "slang-object-meta-end.h" + SLANG_CHILDREN_ASTNode_Val(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_RESULT_IMPL) + SLANG_CHILDREN_ASTNode_Val(SLANG_VISITOR_RESULT_VISIT_IMPL, _) }; template @@ -510,24 +301,8 @@ struct ValVisitor : TypeVisitor 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##NAME(obj); } - -#include "slang-object-meta-begin.h" -#include "slang-val-defs.h" -#include "slang-object-meta-end.h" - -#define ABSTRACT_SYNTAX_CLASS(NAME,BASE) SYNTAX_CLASS(NAME, BASE) -#define SYNTAX_CLASS(NAME, BASE) \ - void visit##NAME(NAME* obj) \ - { ((Derived*) this)->visit##BASE(obj); } - -#include "slang-object-meta-begin.h" -#include "slang-val-defs.h" -#include "slang-object-meta-end.h" - + SLANG_CHILDREN_ASTNode_Val(SLANG_CLASS_ONLY, SLANG_VISITOR_DISPATCH_VOID_IMPL) + SLANG_CHILDREN_ASTNode_Val(SLANG_VISITOR_VOID_VISIT_IMPL, _) }; } diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index 1f8f79af2..34f1402b5 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -116,19 +116,19 @@ void Session::init() // Set all the shared library function pointers to nullptr ::memset(m_sharedLibraryFunctions, 0, sizeof(m_sharedLibraryFunctions)); - { - static auto res = SyntaxClassBase::ClassInfo::initRanges(); - } - + // Initialize the lookup table of syntax classes: // We can just iterate over the class pointers. // NOTE! That this adds the names of the abstract classes too(!) { - const SyntaxClassBase::ClassInfo* info = SyntaxClassBase::ClassInfo::s_first; - for (; info; info = info->m_next) + for (Index i = 0; i < Index(ASTNodeType::CountOf); ++i) { - mapNameToSyntaxClass.Add(getNamePool()->getName(info->m_name), SyntaxClass(info)); + const ReflectClassInfo* info = ReflectClassInfo::getInfo(ASTNodeType(i)); + if (info) + { + mapNameToSyntaxClass.Add(getNamePool()->getName(info->m_name), SyntaxClass(info)); + } } } diff --git a/source/slang/slang.vcxproj b/source/slang/slang.vcxproj index e97d38256..cf5a81499 100644 --- a/source/slang/slang.vcxproj +++ b/source/slang/slang.vcxproj @@ -189,10 +189,20 @@ + + + + + + + + + + + - @@ -203,7 +213,6 @@ - @@ -244,10 +253,7 @@ - - - @@ -257,19 +263,15 @@ - - - - - + @@ -378,6 +380,19 @@ + + Document + "../../bin/windows-x86/debug/slang-cpp-extractor" -d %(RootDir)%(Directory)/ slang-ast-base.h slang-ast-decl.h slang-ast-expr.h slang-ast-modifier.h slang-ast-stmt.h slang-ast-type.h slang-ast-val.h -strip-prefix slang-ast- -o slang-ast-generated + "../../bin/windows-x64/debug/slang-cpp-extractor" -d %(RootDir)%(Directory)/ slang-ast-base.h slang-ast-decl.h slang-ast-expr.h slang-ast-modifier.h slang-ast-stmt.h slang-ast-type.h slang-ast-val.h -strip-prefix slang-ast- -o slang-ast-generated + "../../bin/windows-x86/release/slang-cpp-extractor" -d %(RootDir)%(Directory)/ slang-ast-base.h slang-ast-decl.h slang-ast-expr.h slang-ast-modifier.h slang-ast-stmt.h slang-ast-type.h slang-ast-val.h -strip-prefix slang-ast- -o slang-ast-generated + "../../bin/windows-x64/release/slang-cpp-extractor" -d %(RootDir)%(Directory)/ slang-ast-base.h slang-ast-decl.h slang-ast-expr.h slang-ast-modifier.h slang-ast-stmt.h slang-ast-type.h slang-ast-val.h -strip-prefix slang-ast- -o slang-ast-generated + %(RootDir)%(Directory)/slang-ast-generated.h;%(RootDir)%(Directory)/slang-ast-generated-macro.h + slang-cpp-extractor AST %(Identity) + ../../bin/windows-x86/debug/slang-cpp-extractor.exe;%(RootDir)%(Directory)/slang-ast-base.h;%(RootDir)%(Directory)/slang-ast-decl.h;%(RootDir)%(Directory)/slang-ast-expr.h;%(RootDir)%(Directory)/slang-ast-modifier.h;%(RootDir)%(Directory)/slang-ast-stmt.h;%(RootDir)%(Directory)/slang-ast-type.h;%(RootDir)%(Directory)/slang-ast-val.h + ../../bin/windows-x64/debug/slang-cpp-extractor.exe;%(RootDir)%(Directory)/slang-ast-base.h;%(RootDir)%(Directory)/slang-ast-decl.h;%(RootDir)%(Directory)/slang-ast-expr.h;%(RootDir)%(Directory)/slang-ast-modifier.h;%(RootDir)%(Directory)/slang-ast-stmt.h;%(RootDir)%(Directory)/slang-ast-type.h;%(RootDir)%(Directory)/slang-ast-val.h + ../../bin/windows-x86/release/slang-cpp-extractor.exe;%(RootDir)%(Directory)/slang-ast-base.h;%(RootDir)%(Directory)/slang-ast-decl.h;%(RootDir)%(Directory)/slang-ast-expr.h;%(RootDir)%(Directory)/slang-ast-modifier.h;%(RootDir)%(Directory)/slang-ast-stmt.h;%(RootDir)%(Directory)/slang-ast-type.h;%(RootDir)%(Directory)/slang-ast-val.h + ../../bin/windows-x64/release/slang-cpp-extractor.exe;%(RootDir)%(Directory)/slang-ast-base.h;%(RootDir)%(Directory)/slang-ast-decl.h;%(RootDir)%(Directory)/slang-ast-expr.h;%(RootDir)%(Directory)/slang-ast-modifier.h;%(RootDir)%(Directory)/slang-ast-stmt.h;%(RootDir)%(Directory)/slang-ast-type.h;%(RootDir)%(Directory)/slang-ast-val.h + diff --git a/source/slang/slang.vcxproj.filters b/source/slang/slang.vcxproj.filters index f46e77ebc..4060a6019 100644 --- a/source/slang/slang.vcxproj.filters +++ b/source/slang/slang.vcxproj.filters @@ -18,6 +18,39 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + Header Files @@ -27,9 +60,6 @@ Header Files - - Header Files - Header Files @@ -60,9 +90,6 @@ Header Files - - Header Files - Header Files @@ -183,18 +210,9 @@ Header Files - - Header Files - Header Files - - Header Files - - - Header Files - Header Files @@ -222,15 +240,6 @@ Header Files - - Header Files - - - Header Files - - - Header Files - Header Files @@ -240,23 +249,20 @@ Header Files - - Header Files - Header Files Header Files - - Header Files - Header Files + + Source Files + Source Files @@ -501,5 +507,11 @@ Source Files + + Source Files + + + Header Files + \ No newline at end of file -- cgit v1.2.3