// slang-ast-builder.cpp #include "slang-ast-builder.h" #include #include "slang-compiler.h" namespace Slang { // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SharedASTBuilder !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SharedASTBuilder::SharedASTBuilder() { } void SharedASTBuilder::init(Session* session) { m_namePool = session->getNamePool(); // Save the associated session m_session = session; // We just want as a place to store allocations of shared types { RefPtr astBuilder(new ASTBuilder); astBuilder->m_sharedASTBuilder = this; m_astBuilder = astBuilder.detach(); } // Clear the built in types memset(m_builtinTypes, 0, sizeof(m_builtinTypes)); // Create common shared types m_errorType = m_astBuilder->create(); m_initializerListType = m_astBuilder->create(); m_overloadedType = m_astBuilder->create(); // We can just iterate over the class pointers. // NOTE! That this adds the names of the abstract classes too(!) for (Index i = 0; i < Index(ASTNodeType::CountOf); ++i) { const ReflectClassInfo* info = ReflectClassInfo::getInfo(ASTNodeType(i)); if (info) { m_sliceToTypeMap.Add(UnownedStringSlice(info->m_name), info); Name* name = m_namePool->getName(String(info->m_name)); m_nameToTypeMap.Add(name, info); } } } const ReflectClassInfo* SharedASTBuilder::findClassInfo(const UnownedStringSlice& slice) { const ReflectClassInfo* typeInfo; return m_sliceToTypeMap.TryGetValue(slice, typeInfo) ? typeInfo : nullptr; } SyntaxClass SharedASTBuilder::findSyntaxClass(const UnownedStringSlice& slice) { const ReflectClassInfo* typeInfo; if (m_sliceToTypeMap.TryGetValue(slice, typeInfo)) { return SyntaxClass(typeInfo); } return SyntaxClass(); } const ReflectClassInfo* SharedASTBuilder::findClassInfo(Name* name) { const ReflectClassInfo* typeInfo; return m_nameToTypeMap.TryGetValue(name, typeInfo) ? typeInfo : nullptr; } SyntaxClass SharedASTBuilder::findSyntaxClass(Name* name) { const ReflectClassInfo* typeInfo; if (m_nameToTypeMap.TryGetValue(name, typeInfo)) { return SyntaxClass(typeInfo); } return SyntaxClass(); } Type* SharedASTBuilder::getStringType() { if (!m_stringType) { auto stringTypeDecl = findMagicDecl("StringType"); m_stringType = DeclRefType::create(m_astBuilder, makeDeclRef(stringTypeDecl)); } return m_stringType; } Type* SharedASTBuilder::getEnumTypeType() { if (!m_enumTypeType) { auto enumTypeTypeDecl = findMagicDecl("EnumTypeType"); m_enumTypeType = DeclRefType::create(m_astBuilder, makeDeclRef(enumTypeTypeDecl)); } return m_enumTypeType; } SharedASTBuilder::~SharedASTBuilder() { // Release built in types.. for (Index i = 0; i < SLANG_COUNT_OF(m_builtinTypes); ++i) { m_builtinTypes[i] = nullptr; } if (m_astBuilder) { m_astBuilder->releaseReference(); } } void SharedASTBuilder::registerBuiltinDecl(Decl* decl, BuiltinTypeModifier* modifier) { auto type = DeclRefType::create(m_astBuilder, DeclRef(decl, nullptr)); m_builtinTypes[Index(modifier->tag)] = type; } void SharedASTBuilder::registerMagicDecl(Decl* decl, MagicTypeModifier* modifier) { // In some cases the modifier will have been applied to the // "inner" declaration of a `GenericDecl`, but what we // actually want to register is the generic itself. // auto declToRegister = decl; if (auto genericDecl = as(decl->parentDecl)) declToRegister = genericDecl; m_magicDecls[modifier->name] = declToRegister; } Decl* SharedASTBuilder::findMagicDecl(const String& name) { return m_magicDecls[name].GetValue(); } // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ASTBuilder !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ASTBuilder::ASTBuilder(SharedASTBuilder* sharedASTBuilder, const String& name): m_sharedASTBuilder(sharedASTBuilder), m_name(name), m_id(sharedASTBuilder->m_id++), m_arena(2048) { SLANG_ASSERT(sharedASTBuilder); } ASTBuilder::ASTBuilder(): m_sharedASTBuilder(nullptr), m_id(-1), m_arena(2048) { m_name = "SharedASTBuilder::m_astBuilder"; } ASTBuilder::~ASTBuilder() { for (NodeBase* node : m_dtorNodes) { const ReflectClassInfo* info = ReflectClassInfo::getInfo(node->astNodeType); SLANG_ASSERT(info->m_destructorFunc); info->m_destructorFunc(node); } } PtrType* ASTBuilder::getPtrType(Type* valueType) { return dynamicCast(getPtrType(valueType, "PtrType")); } // Construct the type `Out` OutType* ASTBuilder::getOutType(Type* valueType) { return dynamicCast(getPtrType(valueType, "OutType")); } InOutType* ASTBuilder::getInOutType(Type* valueType) { return dynamicCast(getPtrType(valueType, "InOutType")); } RefType* ASTBuilder::getRefType(Type* valueType) { return dynamicCast(getPtrType(valueType, "RefType")); } PtrTypeBase* ASTBuilder::getPtrType(Type* valueType, char const* ptrTypeName) { auto genericDecl = dynamicCast(m_sharedASTBuilder->findMagicDecl(ptrTypeName)); return getPtrType(valueType, genericDecl); } PtrTypeBase* ASTBuilder::getPtrType(Type* valueType, GenericDecl* genericDecl) { auto typeDecl = genericDecl->inner; auto substitutions = create(); substitutions->genericDecl = genericDecl; substitutions->args.add(valueType); auto declRef = DeclRef(typeDecl, substitutions); auto rsType = DeclRefType::create(this, declRef); return as(rsType); } ArrayExpressionType* ASTBuilder::getArrayType(Type* elementType, IntVal* elementCount) { ArrayExpressionType* arrayType = create(); arrayType->baseType = elementType; arrayType->arrayLength = elementCount; return arrayType; } VectorExpressionType* ASTBuilder::getVectorType( Type* elementType, IntVal* elementCount) { auto vectorGenericDecl = as(m_sharedASTBuilder->findMagicDecl("Vector")); auto vectorTypeDecl = vectorGenericDecl->inner; auto substitutions = create(); substitutions->genericDecl = vectorGenericDecl; substitutions->args.add(elementType); substitutions->args.add(elementCount); auto declRef = DeclRef(vectorTypeDecl, substitutions); return as(DeclRefType::create(this, declRef)); } TypeType* ASTBuilder::getTypeType(Type* type) { return create(type); } } // namespace Slang