model/struct-base.spice
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Copyright (c) 2021-2026 ChilliBits. All rights reserved. | ||
| 2 | |||
| 3 | // Std imports | ||
| 4 | import "std/data/vector"; | ||
| 5 | import "std/text/stringstream"; | ||
| 6 | import "std/bindings/llvm/llvm" as llvm; | ||
| 7 | |||
| 8 | // Own imports | ||
| 9 | import "@/ast/ast-nodes"; | ||
| 10 | import "@/reader/code-loc"; | ||
| 11 | import "@/model/generic-type"; | ||
| 12 | import "@/symboltablebuilder/super-type"; | ||
| 13 | import "@/symboltablebuilder/qual-type"; | ||
| 14 | import "@/symboltablebuilder/symbol-table-entry"; | ||
| 15 | import "@/symboltablebuilder/scope"; | ||
| 16 | import "@/util/common-util"; | ||
| 17 | |||
| 18 | // IR generator data of a struct or interface. The LLVM entities are wrappers around the respective LLVM C API refs, which are | ||
| 19 | // nil as long as they were not generated yet | ||
| 20 | 3562 | public type VTableData struct { | |
| 21 | public llvm::Type typeInfoType | ||
| 22 | public llvm::Type vtableType | ||
| 23 | public llvm::Value typeInfoName | ||
| 24 | public llvm::Value typeInfo | ||
| 25 | public llvm::Value vtable | ||
| 26 | } | ||
| 27 | |||
| 28 | 38121 | public type StructBase struct { | |
| 29 | public String name | ||
| 30 | public Vector<GenericType> templateTypes | ||
| 31 | public TypeMapping typeMapping | ||
| 32 | 3562 | public SymbolTableEntry* entry = nil<SymbolTableEntry*> | |
| 33 | 3562 | public Scope* scope = nil<Scope*> | |
| 34 | public ASTNode* declNode | ||
| 35 | 3562 | public unsigned long manifestationIndex = 0ul | |
| 36 | 3562 | public StructBase* genericPreset = nil<StructBase*> | |
| 37 | public VTableData vTableData | ||
| 38 | 3562 | public bool used = false | |
| 39 | 3562 | public bool isNewlyInserted = false | |
| 40 | // Whether it was already decided which compiler-generated default members (ctor, copy ctor, move ctor, dtor) this | ||
| 41 | // manifestation needs. The decision is taken exactly once per manifestation, as soon as it comes into existence. | ||
| 42 | 3562 | public bool implicitDefaultMembersDecided = false | |
| 43 | } | ||
| 44 | |||
| 45 | 3562 | public p StructBase.ctor(const String& name, SymbolTableEntry* entry, Scope* scope, const Vector<GenericType>& templateTypes, ASTNode* declNode) { | |
| 46 | 3562 | this.name = name; | |
| 47 | 3562 | this.entry = entry; | |
| 48 | 3562 | this.scope = scope; | |
| 49 | 3562 | this.templateTypes = templateTypes; | |
| 50 | 3562 | this.declNode = declNode; | |
| 51 | 3562 | } | |
| 52 | |||
| 53 | /** | ||
| 54 | * Get a string representation of the current struct | ||
| 55 | * | ||
| 56 | * @return String representation as struct signature | ||
| 57 | */ | ||
| 58 | 16584 | public f<String> StructBase.getSignature() { | |
| 59 | 16584 | QualTypeList templateSymbolTypes; | |
| 60 | 16584 | templateSymbolTypes.reserve(this.templateTypes.getSize()); | |
| 61 | 34998 | foreach const GenericType& genericType : this.templateTypes { | |
| 62 | 18414 | if genericType.qualType.is(SuperType::TY_GENERIC) && !this.typeMapping.isEmpty() { | |
| 63 | 2588 | assert this.typeMapping.contains(genericType.qualType.getSubType()); | |
| 64 | 2588 | templateSymbolTypes.pushBack(this.typeMapping.get(genericType.qualType.getSubType())); | |
| 65 | 2588 | } else { | |
| 66 | 15826 | templateSymbolTypes.pushBack(genericType.qualType); | |
| 67 | 15826 | } | |
| 68 | 18414 | } | |
| 69 | |||
| 70 | 33168 | return getStructSignature(this.name, templateSymbolTypes); | |
| 71 | 16584 | } | |
| 72 | |||
| 73 | /** | ||
| 74 | * Get the signature from the struct name and the concrete template types. This is a free function, since Spice has no | ||
| 75 | * static methods. | ||
| 76 | * | ||
| 77 | * Example: | ||
| 78 | * Pair<int,double> | ||
| 79 | * | ||
| 80 | * @param name Struct name | ||
| 81 | * @param concreteTemplateTypes Concrete template types | ||
| 82 | * @return Signature | ||
| 83 | */ | ||
| 84 | 26173 | public f<String> getStructSignature(const String& name, const QualTypeList& concreteTemplateTypes) { | |
| 85 | // Build template type string | ||
| 86 | 26173 | StringStream templateTyStr; | |
| 87 | 26173 | if !concreteTemplateTypes.isEmpty() { | |
| 88 | 19530 | templateTyStr << "<"; | |
| 89 | 44718 | foreach unsigned long i, const QualType& templateType : concreteTemplateTypes { | |
| 90 | 25188 | if i > 0ul { templateTyStr << ","; } | |
| 91 | 25188 | templateType.getName(templateTyStr, false, true); | |
| 92 | 25188 | } | |
| 93 | 19530 | templateTyStr << ">"; | |
| 94 | 19530 | } | |
| 95 | |||
| 96 | 52346 | return getLastFragment(name, SCOPE_ACCESS_TOKEN) + templateTyStr.str(); | |
| 97 | 26173 | } | |
| 98 | |||
| 99 | /** | ||
| 100 | * Checks if a struct contains generic template types. | ||
| 101 | * This would imply that the struct is not substantiated by its generic types yet. | ||
| 102 | * | ||
| 103 | * @return Substantiated generics or not | ||
| 104 | */ | ||
| 105 | 25051 | public f<bool> StructBase.hasSubstantiatedGenerics() { | |
| 106 | 36364 | foreach const GenericType& genericType : this.templateTypes { | |
| 107 | 17041 | if genericType.qualType.hasAnyGenericParts() { | |
| 108 | 5728 | return false; | |
| 109 | } | ||
| 110 | 11313 | } | |
| 111 | 19323 | return true; | |
| 112 | } | ||
| 113 | |||
| 114 | /** | ||
| 115 | * Checks if a struct has generic types present. | ||
| 116 | * This would imply that the struct is not fully substantiated yet. | ||
| 117 | * | ||
| 118 | * @return Fully substantiated or not | ||
| 119 | */ | ||
| 120 | 25051 | public f<bool> StructBase.isFullySubstantiated() { | |
| 121 | 25051 | return this.hasSubstantiatedGenerics(); | |
| 122 | } | ||
| 123 | |||
| 124 | /** | ||
| 125 | * Retrieve the template types as vector of symbol types | ||
| 126 | * | ||
| 127 | * @return Template types as vector of symbol types | ||
| 128 | */ | ||
| 129 | 4531 | public f<QualTypeList> StructBase.getTemplateTypes() { | |
| 130 | 4531 | result = Vector<QualType>(); | |
| 131 | 8216 | foreach GenericType& genericTemplateType : this.templateTypes { | |
| 132 | 3685 | result.pushBack(genericTemplateType.qualType); | |
| 133 | 3685 | } | |
| 134 | 4531 | } | |
| 135 | |||
| 136 | /** | ||
| 137 | * Retrieve the declaration code location of this struct | ||
| 138 | * | ||
| 139 | * @return Declaration code location | ||
| 140 | */ | ||
| 141 | 2987 | public f<const CodeLoc&> StructBase.getDeclCodeLoc() { | |
| 142 | 2987 | return this.declNode.codeLoc; | |
| 143 | } | ||
| 144 | |||
| 145 | /** | ||
| 146 | * Returns, if this struct is a substantiation of a generic one. | ||
| 147 | * | ||
| 148 | * @return Generic substantiation or not | ||
| 149 | */ | ||
| 150 | 21425 | public f<bool> StructBase.isGenericSubstantiation() { | |
| 151 | 21425 | return this.genericPreset != nil<StructBase*>; | |
| 152 | } | ||
| 153 |