src/model/Function.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Copyright (c) 2021-2026 ChilliBits. All rights reserved. | ||
| 2 | |||
| 3 | #include "Function.h" | ||
| 4 | |||
| 5 | #include <ast/ASTBuilder.h> | ||
| 6 | #include <ast/ASTNodes.h> | ||
| 7 | #include <irgenerator/NameMangling.h> | ||
| 8 | #include <symboltablebuilder/SymbolTableBuilder.h> | ||
| 9 | |||
| 10 | namespace spice::compiler { | ||
| 11 | |||
| 12 | 107602 | Function::Function(std::string name, SymbolTableEntry *entry, const QualType &thisType, const QualType &returnType, | |
| 13 | ParamList paramList, std::vector<GenericType> templateTypes, ASTNode *declNode) | ||
| 14 | 322806 | : name(std::move(name)), thisType(thisType), returnType(returnType), paramList(std::move(paramList)), | |
| 15 | 215204 | templateTypes(std::move(templateTypes)), entry(entry), declNode(declNode) {} | |
| 16 | |||
| 17 | /** | ||
| 18 | * Retrieve the parameter types of the current function | ||
| 19 | * | ||
| 20 | * @return Vector of parameter types | ||
| 21 | */ | ||
| 22 | 585892 | QualTypeList Function::getParamTypes() const { | |
| 23 | 585892 | QualTypeList newParamTypes; | |
| 24 |
2/2✓ Branch 16 → 4 taken 937829 times.
✓ Branch 16 → 17 taken 585892 times.
|
2109613 | for (const auto &[qualType, isOptional] : paramList) |
| 25 |
1/2✓ Branch 6 → 7 taken 937829 times.
✗ Branch 6 → 19 not taken.
|
937829 | newParamTypes.push_back(qualType); |
| 26 | 585892 | return newParamTypes; | |
| 27 | ✗ | } | |
| 28 | |||
| 29 | /** | ||
| 30 | * Get a string representation of the current function. | ||
| 31 | * | ||
| 32 | * Example: | ||
| 33 | * string Vector<double>.setData<double>(double) | ||
| 34 | * | ||
| 35 | * @param withThisType Include 'this' type in signature | ||
| 36 | * @param withTemplateTypes Include concrete template types in the signature | ||
| 37 | * @param withTypeAliases Print type aliases as is and not decompose them | ||
| 38 | * @param withSize Print array sizes | ||
| 39 | * @return String representation as function signature | ||
| 40 | */ | ||
| 41 | 400911 | std::string Function::getSignature(bool withThisType /*=true*/, bool withTemplateTypes /*=true*/, bool withTypeAliases /*=true*/, | |
| 42 | bool withSize /*=false*/) const { | ||
| 43 | 400911 | QualTypeList concreteTemplateTypes; | |
| 44 |
2/2✓ Branch 2 → 3 taken 400907 times.
✓ Branch 2 → 34 taken 4 times.
|
400911 | if (withTemplateTypes) { |
| 45 |
1/2✓ Branch 4 → 5 taken 400907 times.
✗ Branch 4 → 40 not taken.
|
400907 | concreteTemplateTypes.reserve(templateTypes.size()); |
| 46 |
2/2✓ Branch 32 → 7 taken 230630 times.
✓ Branch 32 → 33 taken 400907 times.
|
1032444 | for (const GenericType &genericType : templateTypes) { |
| 47 |
7/8✓ Branch 9 → 10 taken 230630 times.
✗ Branch 9 → 39 not taken.
✓ Branch 10 → 11 taken 227596 times.
✓ Branch 10 → 14 taken 3034 times.
✓ Branch 12 → 13 taken 134752 times.
✓ Branch 12 → 14 taken 92844 times.
✓ Branch 15 → 16 taken 134752 times.
✓ Branch 15 → 22 taken 95878 times.
|
230630 | if (genericType.is(TY_GENERIC) && !typeMapping.empty()) { |
| 48 |
1/2✓ Branch 16 → 17 taken 134752 times.
✗ Branch 16 → 39 not taken.
|
134752 | const std::string &subType = genericType.getSubType(); |
| 49 |
2/4✓ Branch 17 → 18 taken 134752 times.
✗ Branch 17 → 39 not taken.
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 20 taken 134752 times.
|
134752 | assert(typeMapping.contains(subType)); |
| 50 |
2/4✓ Branch 20 → 21 taken 134752 times.
✗ Branch 20 → 39 not taken.
✓ Branch 21 → 23 taken 134752 times.
✗ Branch 21 → 39 not taken.
|
134752 | concreteTemplateTypes.push_back(typeMapping.at(subType)); |
| 51 | } else { | ||
| 52 |
1/2✓ Branch 22 → 23 taken 95878 times.
✗ Branch 22 → 39 not taken.
|
95878 | concreteTemplateTypes.push_back(genericType); |
| 53 | } | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | 400911 | return getSignature(name, thisType, returnType, paramList, concreteTemplateTypes, true, withThisType, true, withTypeAliases, | |
| 58 |
1/2✓ Branch 34 → 35 taken 400911 times.
✗ Branch 34 → 40 not taken.
|
801822 | withSize); |
| 59 | 400911 | } | |
| 60 | |||
| 61 | /** | ||
| 62 | * Get a string representation of the current function. | ||
| 63 | * | ||
| 64 | * @param name Function name | ||
| 65 | * @param thisType This symbol type | ||
| 66 | * @param returnType Return symbol type | ||
| 67 | * @param paramList Param symbol types | ||
| 68 | * @param concreteTemplateTypes Concrete template symbol types | ||
| 69 | * @param withReturnType Include return type in signature | ||
| 70 | * @param withThisType Include 'this' type in signature | ||
| 71 | * @param ignorePublic Not include public modifiers in signature | ||
| 72 | * @param withTypeAliases Print type aliases as is and not decompose them | ||
| 73 | * @param withSize Print array sizes | ||
| 74 | * @return Function signature | ||
| 75 | */ | ||
| 76 | 400935 | std::string Function::getSignature(const std::string &name, const QualType &thisType, const QualType &returnType, | |
| 77 | const ParamList ¶mList, const QualTypeList &concreteTemplateTypes, | ||
| 78 | bool withReturnType /*=true*/, bool withThisType /*=true*/, bool ignorePublic /*=false*/, | ||
| 79 | bool withTypeAliases /*=true*/, bool withSize /*=false*/) { | ||
| 80 |
1/2✓ Branch 2 → 3 taken 400935 times.
✗ Branch 2 → 66 not taken.
|
400935 | std::stringstream signature; |
| 81 | |||
| 82 | // Build return type string | ||
| 83 |
2/2✓ Branch 3 → 4 taken 400911 times.
✓ Branch 3 → 10 taken 24 times.
|
400935 | if (withReturnType) { |
| 84 |
3/4✓ Branch 4 → 5 taken 400911 times.
✗ Branch 4 → 64 not taken.
✓ Branch 5 → 6 taken 169121 times.
✓ Branch 5 → 7 taken 231790 times.
|
400911 | if (returnType.is(TY_DYN)) { |
| 85 |
1/2✓ Branch 6 → 10 taken 169121 times.
✗ Branch 6 → 64 not taken.
|
169121 | signature << "p "; |
| 86 | } else { | ||
| 87 |
1/2✓ Branch 7 → 8 taken 231790 times.
✗ Branch 7 → 64 not taken.
|
231790 | signature << "f<"; |
| 88 |
1/2✓ Branch 8 → 9 taken 231790 times.
✗ Branch 8 → 64 not taken.
|
231790 | returnType.getName(signature, withSize, ignorePublic, withTypeAliases); |
| 89 |
1/2✓ Branch 9 → 10 taken 231790 times.
✗ Branch 9 → 64 not taken.
|
231790 | signature << "> "; |
| 90 | } | ||
| 91 | } | ||
| 92 | |||
| 93 | // Build this type string | ||
| 94 |
7/8✓ Branch 10 → 11 taken 161742 times.
✓ Branch 10 → 14 taken 239193 times.
✓ Branch 11 → 12 taken 161742 times.
✗ Branch 11 → 64 not taken.
✓ Branch 12 → 13 taken 104355 times.
✓ Branch 12 → 14 taken 57387 times.
✓ Branch 15 → 16 taken 104355 times.
✓ Branch 15 → 33 taken 296580 times.
|
400935 | if (withThisType && !thisType.is(TY_DYN)) { |
| 95 |
3/6✓ Branch 16 → 17 taken 104355 times.
✗ Branch 16 → 63 not taken.
✓ Branch 17 → 18 taken 104355 times.
✗ Branch 17 → 63 not taken.
✓ Branch 18 → 19 taken 104355 times.
✗ Branch 18 → 63 not taken.
|
104355 | signature << thisType.getBase().getSubType(); |
| 96 |
1/2✓ Branch 19 → 20 taken 104355 times.
✗ Branch 19 → 64 not taken.
|
104355 | const QualTypeList &thisTemplateTypes = thisType.getTemplateTypes(); |
| 97 |
2/2✓ Branch 21 → 22 taken 54203 times.
✓ Branch 21 → 32 taken 50152 times.
|
104355 | if (!thisTemplateTypes.empty()) { |
| 98 |
1/2✓ Branch 22 → 23 taken 54203 times.
✗ Branch 22 → 64 not taken.
|
54203 | signature << "<"; |
| 99 |
2/2✓ Branch 30 → 24 taken 68734 times.
✓ Branch 30 → 31 taken 54203 times.
|
122937 | for (size_t i = 0; i < thisTemplateTypes.size(); i++) { |
| 100 |
2/2✓ Branch 24 → 25 taken 14531 times.
✓ Branch 24 → 26 taken 54203 times.
|
68734 | if (i > 0) |
| 101 |
1/2✓ Branch 25 → 26 taken 14531 times.
✗ Branch 25 → 64 not taken.
|
14531 | signature << ","; |
| 102 |
2/4✓ Branch 26 → 27 taken 68734 times.
✗ Branch 26 → 64 not taken.
✓ Branch 27 → 28 taken 68734 times.
✗ Branch 27 → 64 not taken.
|
68734 | thisTemplateTypes.at(i).getName(signature, withSize, ignorePublic, withTypeAliases); |
| 103 | } | ||
| 104 |
1/2✓ Branch 31 → 32 taken 54203 times.
✗ Branch 31 → 64 not taken.
|
54203 | signature << ">"; |
| 105 | } | ||
| 106 |
1/2✓ Branch 32 → 33 taken 104355 times.
✗ Branch 32 → 64 not taken.
|
104355 | signature << MEMBER_ACCESS_TOKEN; |
| 107 | } | ||
| 108 | |||
| 109 | // Name | ||
| 110 |
1/2✓ Branch 33 → 34 taken 400935 times.
✗ Branch 33 → 64 not taken.
|
400935 | signature << name; |
| 111 | |||
| 112 | // Build template type string | ||
| 113 |
2/2✓ Branch 35 → 36 taken 181072 times.
✓ Branch 35 → 46 taken 219863 times.
|
400935 | if (!concreteTemplateTypes.empty()) { |
| 114 |
1/2✓ Branch 36 → 37 taken 181072 times.
✗ Branch 36 → 64 not taken.
|
181072 | signature << "<"; |
| 115 |
2/2✓ Branch 44 → 38 taken 230630 times.
✓ Branch 44 → 45 taken 181072 times.
|
411702 | for (size_t i = 0; i < concreteTemplateTypes.size(); i++) { |
| 116 |
2/2✓ Branch 38 → 39 taken 49558 times.
✓ Branch 38 → 40 taken 181072 times.
|
230630 | if (i > 0) |
| 117 |
1/2✓ Branch 39 → 40 taken 49558 times.
✗ Branch 39 → 64 not taken.
|
49558 | signature << ","; |
| 118 |
2/4✓ Branch 40 → 41 taken 230630 times.
✗ Branch 40 → 64 not taken.
✓ Branch 41 → 42 taken 230630 times.
✗ Branch 41 → 64 not taken.
|
230630 | concreteTemplateTypes.at(i).getName(signature, withSize, ignorePublic, withTypeAliases); |
| 119 | } | ||
| 120 |
1/2✓ Branch 45 → 46 taken 181072 times.
✗ Branch 45 → 64 not taken.
|
181072 | signature << ">"; |
| 121 | } | ||
| 122 | |||
| 123 | // Parameter type string | ||
| 124 |
1/2✓ Branch 46 → 47 taken 400935 times.
✗ Branch 46 → 64 not taken.
|
400935 | signature << "("; |
| 125 |
2/2✓ Branch 56 → 48 taken 442188 times.
✓ Branch 56 → 57 taken 400935 times.
|
843123 | for (size_t i = 0; i < paramList.size(); i++) { |
| 126 |
1/2✓ Branch 48 → 49 taken 442188 times.
✗ Branch 48 → 64 not taken.
|
442188 | const auto &[qualType, isOptional] = paramList.at(i); |
| 127 |
2/2✓ Branch 49 → 50 taken 166415 times.
✓ Branch 49 → 51 taken 275773 times.
|
442188 | if (i > 0) |
| 128 |
1/2✓ Branch 50 → 51 taken 166415 times.
✗ Branch 50 → 64 not taken.
|
166415 | signature << ","; |
| 129 |
1/2✓ Branch 51 → 52 taken 442188 times.
✗ Branch 51 → 64 not taken.
|
442188 | qualType.getName(signature, withSize, ignorePublic, withTypeAliases); |
| 130 |
1/2✗ Branch 52 → 53 not taken.
✓ Branch 52 → 54 taken 442188 times.
|
442188 | if (isOptional) |
| 131 | ✗ | signature << "?"; | |
| 132 | } | ||
| 133 |
1/2✓ Branch 57 → 58 taken 400935 times.
✗ Branch 57 → 64 not taken.
|
400935 | signature << ")"; |
| 134 | |||
| 135 |
1/2✓ Branch 58 → 59 taken 400935 times.
✗ Branch 58 → 64 not taken.
|
801870 | return signature.str(); |
| 136 | 400935 | } | |
| 137 | |||
| 138 | /** | ||
| 139 | * Get the name of the scope, where members and the body of the function live | ||
| 140 | * | ||
| 141 | * @return Scope name | ||
| 142 | */ | ||
| 143 | 239193 | std::string Function::getScopeName() const { return getSignature(false, true, false, true); } | |
| 144 | |||
| 145 | /** | ||
| 146 | * Get the mangled name of the function | ||
| 147 | * | ||
| 148 | * @return Mangled name | ||
| 149 | */ | ||
| 150 | 325079 | std::string Function::getMangledName() const { | |
| 151 | // Use predefined mangled name if available | ||
| 152 |
2/2✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 5 taken 325077 times.
|
325079 | if (!predefinedMangledName.empty()) |
| 153 | 2 | return predefinedMangledName; | |
| 154 | // Use function name if mangling is disabled | ||
| 155 |
2/2✓ Branch 5 → 6 taken 27132 times.
✓ Branch 5 → 7 taken 297945 times.
|
325077 | if (!mangleFunctionName) |
| 156 | 27132 | return name; | |
| 157 | // Use normal name mangling | ||
| 158 | 297945 | return NameMangling::mangleFunction(*this); | |
| 159 | } | ||
| 160 | |||
| 161 | /** | ||
| 162 | * Get the name of the symbol table entry of the function | ||
| 163 | * | ||
| 164 | * @param functionName Function name | ||
| 165 | * @param codeLoc Code location | ||
| 166 | * @return Symbol table entry name | ||
| 167 | */ | ||
| 168 | 160793 | std::string Function::getSymbolTableEntryName(const std::string &functionName, const CodeLoc &codeLoc) { | |
| 169 |
3/6✓ Branch 2 → 3 taken 160793 times.
✗ Branch 2 → 15 not taken.
✓ Branch 3 → 4 taken 160793 times.
✗ Branch 3 → 12 not taken.
✓ Branch 4 → 5 taken 160793 times.
✗ Branch 4 → 10 not taken.
|
321586 | return functionName + ":" + codeLoc.toString(); |
| 170 | } | ||
| 171 | |||
| 172 | /** | ||
| 173 | * Get the name of the symbol table entry of the default constructor of a struct | ||
| 174 | * | ||
| 175 | * @param structCodeLoc Code location of the struct | ||
| 176 | * @return Symbol table entry name | ||
| 177 | */ | ||
| 178 | 356 | std::string Function::getSymbolTableEntryNameDefaultCtor(const CodeLoc &structCodeLoc) { | |
| 179 |
5/10✓ Branch 2 → 3 taken 356 times.
✗ Branch 2 → 31 not taken.
✓ Branch 5 → 6 taken 356 times.
✗ Branch 5 → 23 not taken.
✓ Branch 6 → 7 taken 356 times.
✗ Branch 6 → 21 not taken.
✓ Branch 7 → 8 taken 356 times.
✗ Branch 7 → 19 not taken.
✓ Branch 8 → 9 taken 356 times.
✗ Branch 8 → 17 not taken.
|
1424 | return "default_" + std::string(CTOR_FUNCTION_NAME) + ":" + structCodeLoc.toString(); |
| 180 | } | ||
| 181 | |||
| 182 | /** | ||
| 183 | * Get the name of the symbol table entry of the default copy constructor of a struct | ||
| 184 | * | ||
| 185 | * @param structCodeLoc Code location of the struct | ||
| 186 | * @return Symbol table entry name | ||
| 187 | */ | ||
| 188 | 4189 | std::string Function::getSymbolTableEntryNameDefaultCopyCtor(const CodeLoc &structCodeLoc) { | |
| 189 |
5/10✓ Branch 2 → 3 taken 4189 times.
✗ Branch 2 → 31 not taken.
✓ Branch 5 → 6 taken 4189 times.
✗ Branch 5 → 23 not taken.
✓ Branch 6 → 7 taken 4189 times.
✗ Branch 6 → 21 not taken.
✓ Branch 7 → 8 taken 4189 times.
✗ Branch 7 → 19 not taken.
✓ Branch 8 → 9 taken 4189 times.
✗ Branch 8 → 17 not taken.
|
16756 | return "default_copy" + std::string(CTOR_FUNCTION_NAME) + ":" + structCodeLoc.toString(); |
| 190 | } | ||
| 191 | |||
| 192 | /** | ||
| 193 | * Get the name of the symbol table entry of the default move constructor of a struct | ||
| 194 | * | ||
| 195 | * @param structCodeLoc Code location of the struct | ||
| 196 | * @return Symbol table entry name | ||
| 197 | */ | ||
| 198 | 20 | std::string Function::getSymbolTableEntryNameDefaultMoveCtor(const CodeLoc &structCodeLoc) { | |
| 199 |
5/10✓ Branch 2 → 3 taken 20 times.
✗ Branch 2 → 31 not taken.
✓ Branch 5 → 6 taken 20 times.
✗ Branch 5 → 23 not taken.
✓ Branch 6 → 7 taken 20 times.
✗ Branch 6 → 21 not taken.
✓ Branch 7 → 8 taken 20 times.
✗ Branch 7 → 19 not taken.
✓ Branch 8 → 9 taken 20 times.
✗ Branch 8 → 17 not taken.
|
80 | return "default_move" + std::string(CTOR_FUNCTION_NAME) + ":" + structCodeLoc.toString(); |
| 200 | } | ||
| 201 | |||
| 202 | /** | ||
| 203 | * Get the name of the symbol table entry of the default destructor of a struct | ||
| 204 | * | ||
| 205 | * @param structCodeLoc Code location of the struct | ||
| 206 | * @return Symbol table entry name | ||
| 207 | */ | ||
| 208 | 3521 | std::string Function::getSymbolTableEntryNameDefaultDtor(const CodeLoc &structCodeLoc) { | |
| 209 |
5/10✓ Branch 2 → 3 taken 3521 times.
✗ Branch 2 → 31 not taken.
✓ Branch 5 → 6 taken 3521 times.
✗ Branch 5 → 23 not taken.
✓ Branch 6 → 7 taken 3521 times.
✗ Branch 6 → 21 not taken.
✓ Branch 7 → 8 taken 3521 times.
✗ Branch 7 → 19 not taken.
✓ Branch 8 → 9 taken 3521 times.
✗ Branch 8 → 17 not taken.
|
14084 | return "default_" + std::string(DTOR_FUNCTION_NAME) + ":" + structCodeLoc.toString(); |
| 210 | } | ||
| 211 | |||
| 212 | /** | ||
| 213 | * Checks if a function contains optional parameters. | ||
| 214 | * This would imply that the function is not substantiated by its optional parameters yet. | ||
| 215 | * | ||
| 216 | * @return Substantiated params or not | ||
| 217 | */ | ||
| 218 | 13100989 | bool Function::hasSubstantiatedParams() const { | |
| 219 | 32167594 | return std::ranges::none_of(paramList, [](const Param ¶m) { return param.isOptional; }); | |
| 220 | } | ||
| 221 | |||
| 222 | /** | ||
| 223 | * Checks if a function contains template types. | ||
| 224 | * This would imply that the function is not substantiated by its generic types yet. | ||
| 225 | * | ||
| 226 | * @return Substantiated generics or not | ||
| 227 | */ | ||
| 228 | 1003162 | bool Function::hasSubstantiatedGenerics() const { | |
| 229 | 1583416 | const auto predicate = [this](const GenericType &genericType) { | |
| 230 | // A template slot that is not generic (anymore) is already substantiated. This is the case for the default members | ||
| 231 | // of an already-concrete struct manifestation (e.g. HashEntry<int, String>::dtor()), whose template type list holds | ||
| 232 | // the concrete types instead of generic placeholders. Only generic types carry a sub type usable as a mapping key - | ||
| 233 | // getSubType() would assert on e.g. a primitive or a 'heap byte*'. | ||
| 234 |
4/4✓ Branch 3 → 4 taken 570180 times.
✓ Branch 3 → 7 taken 10074 times.
✓ Branch 6 → 7 taken 221942 times.
✓ Branch 6 → 8 taken 348238 times.
|
580254 | return !genericType.is(TY_GENERIC) || typeMapping.contains(genericType.getSubType()); |
| 235 | 1003162 | }; | |
| 236 |
1/2✓ Branch 2 → 3 taken 1003162 times.
✗ Branch 2 → 6 not taken.
|
2006324 | return std::ranges::all_of(templateTypes, predicate); |
| 237 | } | ||
| 238 | |||
| 239 | /** | ||
| 240 | * Checks if a function contains optional parameters or has generic types present. | ||
| 241 | * This would imply that the function is not fully substantiated yet. | ||
| 242 | * | ||
| 243 | * @return Fully substantiated or not | ||
| 244 | */ | ||
| 245 |
3/4✓ Branch 3 → 4 taken 1003162 times.
✗ Branch 3 → 7 not taken.
✓ Branch 5 → 6 taken 654924 times.
✓ Branch 5 → 7 taken 348238 times.
|
1003162 | bool Function::isFullySubstantiated() const { return hasSubstantiatedParams() && hasSubstantiatedGenerics(); } |
| 246 | |||
| 247 | /** | ||
| 248 | * Returns, if this function is a substantiation of a generic one. | ||
| 249 | * | ||
| 250 | * @return Generic substantiation or not | ||
| 251 | */ | ||
| 252 | 11312364 | bool Function::isGenericSubstantiation() const { return genericPreset != nullptr; } | |
| 253 | |||
| 254 | /** | ||
| 255 | * Retrieve the declaration code location of this function | ||
| 256 | * | ||
| 257 | * @return Declaration code location | ||
| 258 | */ | ||
| 259 | 43695 | const CodeLoc &Function::getDeclCodeLoc() const { return declNode->codeLoc; } | |
| 260 | |||
| 261 | } // namespace spice::compiler | ||
| 262 |