Skip to content

Commit

Permalink
Add mechanism to generate implicit functions (#322)
Browse files Browse the repository at this point in the history
  • Loading branch information
marcauberer committed Sep 15, 2023
1 parent 6377f39 commit cad161a
Show file tree
Hide file tree
Showing 92 changed files with 1,052 additions and 785 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci-cpp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ jobs:
echo "/usr/lib/ccache:/usr/local/opt/ccache/libexec" >> $GITHUB_PATH
mkdir ./bin
cd ./bin
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DSPICE_BUILT_BY="ghactions" -DSPICE_LINK_STATIC=OFF -DSPICE_LTO=ON -DSPICE_RUN_COVERAGE=ON -GNinja -Wattributes ..
cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DSPICE_BUILT_BY="ghactions" -DSPICE_LINK_STATIC=OFF -DSPICE_LTO=ON -DSPICE_RUN_COVERAGE=ON -GNinja -Wattributes ..
cmake --build . --target spicetest -j$(nproc)
# - name: Build Test target
Expand Down
5 changes: 2 additions & 3 deletions media/specs/ctors-and-dtors.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
## Roadmap

- [x] Produce error when using `heap` specifier on non-pointer types
- [ ] Add mechanism to generate functions and methods, that are not part of the AST
- [ ] Generate default dtor
- [x] Add mechanism to generate functions and methods, that are not part of the AST
- [x] Generate default dtor
- [ ] Generate default ctor
- [ ] Generate default copy ctor
- [ ] (Generate default move ctor)
Expand Down Expand Up @@ -70,7 +70,6 @@ with the following signature:

```spice
p TestStruct.dtor() {
// Code for dtor body
// Call the dtor of all fields, that are of type struct and have a dtor
// Free all fields, that are marked with the `heap` specifier
}
Expand Down
27 changes: 24 additions & 3 deletions media/test-project/test.spice
Original file line number Diff line number Diff line change
@@ -1,4 +1,25 @@
import "std/data/vector" as vec;

f<int> main() {
int t = 123;
heap int test = t;
}
vec::Vector<double> v1 = vec::Vector<double>(3);
v1.pushBack(1.2);
v1.pushBack(7.4964598);
v1.pushBack(5.3);
v1.pushBack(-238974.23);
v1.pushBack(23234.2);
v1.pushBack(-1234.9);
v1.pushBack(0.0);
printf("Vector size: %d\n", v1.getSize());
printf("Vector capacity: %d\n", v1.getCapacity());
printf("Vector item 5: %f\n", v1.get(5));
}

/*type TestStruct struct {
int a = 123
short b = 1s
}

f<int> main() {
TestStruct ts;
printf("%d %d\n", ts.a, ts.b);
}*/
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ set(SOURCES
typechecker/TypeChecker.h
typechecker/TypeCheckerPrepare.cpp
typechecker/TypeCheckerCheck.cpp
typechecker/TypeCheckerImplicit.cpp
typechecker/OpRuleManager.cpp
typechecker/OpRuleManager.h
typechecker/FunctionManager.cpp
Expand All @@ -86,6 +87,7 @@ set(SOURCES
irgenerator/GenBuiltinFunctions.cpp
irgenerator/GenExpressions.cpp
irgenerator/GenValues.cpp
irgenerator/GenImplicit.cpp
irgenerator/StdFunctionManager.cpp
irgenerator/StdFunctionManager.h
irgenerator/OpRuleConversionManager.cpp
Expand Down
1 change: 1 addition & 0 deletions src/CompilerPass.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class CompilerPass {
const CliOptions &cliOptions;
SourceFile *sourceFile;
Scope *rootScope;
size_t manIdx = 0;

public:
// Public members
Expand Down
10 changes: 7 additions & 3 deletions src/SourceFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,10 @@ void SourceFile::addDependency(SourceFile *sourceFile, const ASTNode *declNode,
sourceFile->dependants.push_back(this);
}

bool SourceFile::imports(const SourceFile *sourceFile) const {
return std::ranges::any_of(dependencies, [=](const auto &dependency) { return dependency.second.first == sourceFile; });
}

bool SourceFile::isAlreadyImported(const std::string &filePathSearch) const { // NOLINT(misc-no-recursion)
// Check if the current source file corresponds to the path to search
if (filePath == filePathSearch)
Expand All @@ -574,12 +578,12 @@ bool SourceFile::isAlreadyImported(const std::string &filePathSearch) const { //
return parent != nullptr && parent->isAlreadyImported(filePathSearch);
}

void SourceFile::requestRuntimeModule(RuntimeModule runtimeModule) {
SourceFile *SourceFile::requestRuntimeModule(RuntimeModule runtimeModule) {
// Check if the module was already imported
if (importedRuntimeModules & runtimeModule)
return;
return resourceManager.runtimeModuleManager.getModule(runtimeModule);

resourceManager.runtimeModuleManager.requestModule(this, runtimeModule);
return resourceManager.runtimeModuleManager.requestModule(this, runtimeModule);
}

void SourceFile::addNameRegistryEntry(const std::string &symbolName, SymbolTableEntry *entry, Scope *scope,
Expand Down
3 changes: 2 additions & 1 deletion src/SourceFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,9 @@ class SourceFile {

// Public methods
void addDependency(SourceFile *sourceFile, const ASTNode *declNode, const std::string &dependencyName, const std::string &path);
[[nodiscard]] bool imports(const SourceFile *sourceFile) const;
[[nodiscard]] bool isAlreadyImported(const std::string &filePathSearch) const;
void requestRuntimeModule(RuntimeModule runtimeModule);
SourceFile *requestRuntimeModule(RuntimeModule runtimeModule);
void addNameRegistryEntry(const std::string &symbolName, SymbolTableEntry *entry, Scope *scope, bool keepNewOnCollision = true,
SymbolTableEntry *importEntry = nullptr, const std::string &predecessorName = "");
[[nodiscard]] const NameRegistryEntry *getNameRegistryEntry(std::string symbolName) const;
Expand Down
32 changes: 16 additions & 16 deletions src/ast/ASTNodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,8 @@ class ASTNode {
return children.size() == 1 && children.front()->returnsOnAllControlPaths(overrideUnreachable);
}

[[nodiscard]] virtual std::vector<Function *> *getFctManifestations() {
assert(false && "Must be called on a FctDefNode, ProcDefNode or ExtDeclNode");
[[nodiscard]] virtual std::vector<Function *> *getFctManifestations(const std::string &fctName) {
assert(false && "Must be called on a FctDefNode, ProcDefNode, ExtDeclNode, StructDefNode or SignatureNode");
return nullptr;
}

Expand All @@ -168,6 +168,7 @@ class ASTNode {
}

[[nodiscard]] virtual bool isFctOrProcDef() const { return false; }
[[nodiscard]] virtual bool isStructDef() const { return false; }
[[nodiscard]] virtual bool isStmtNode() const { return false; }
[[nodiscard]] virtual bool isAssignExpr() const { return false; }

Expand Down Expand Up @@ -287,13 +288,9 @@ class FctDefNode : public ASTNode {

// Other methods
[[nodiscard]] std::string getScopeId() const { return "fct:" + codeLoc.toString(); }
[[nodiscard]] std::string getSymbolTableEntryName() const {
const FctNameNode *functionName = getChild<FctNameNode>();
assert(functionName != nullptr);
return functionName->name + ":" + codeLoc.toPrettyLineAndColumn();
}
[[nodiscard]] std::string getSymbolTableEntryName() const { return Function::getSymbolTableEntryName(fctName->name, codeLoc); }
[[nodiscard]] bool returnsOnAllControlPaths(bool *overrideUnreachable) const override;
std::vector<Function *> *getFctManifestations() override { return &fctManifestations; }
std::vector<Function *> *getFctManifestations(const std::string &_) override { return &fctManifestations; }
[[nodiscard]] bool isFctOrProcDef() const override { return true; }

// Public members
Expand Down Expand Up @@ -328,13 +325,9 @@ class ProcDefNode : public ASTNode {

// Other methods
[[nodiscard]] std::string getScopeId() const { return "proc:" + codeLoc.toString(); }
[[nodiscard]] std::string getSymbolTableEntryName() const {
const FctNameNode *functionName = getChild<FctNameNode>();
assert(functionName != nullptr);
return functionName->name + ":" + codeLoc.toPrettyLineAndColumn();
}
[[nodiscard]] std::string getSymbolTableEntryName() const { return Function::getSymbolTableEntryName(procName->name, codeLoc); }
bool returnsOnAllControlPaths(bool *overrideUnreachable) const override;
std::vector<Function *> *getFctManifestations() override { return &procManifestations; }
std::vector<Function *> *getFctManifestations(const std::string &_) override { return &procManifestations; }
[[nodiscard]] bool isFctOrProcDef() const override { return true; }

// Public members
Expand Down Expand Up @@ -369,6 +362,12 @@ class StructDefNode : public ASTNode {

// Other methods
std::vector<Struct *> *getStructManifestations() override { return &structManifestations; }
std::vector<Function *> *getFctManifestations(const std::string &fctName) override {
if (!defaultFctManifestations.contains(fctName))
defaultFctManifestations.insert({fctName, {}});
return &defaultFctManifestations.at(fctName);
}
[[nodiscard]] bool isStructDef() const override { return true; }

// Public members
std::string structName;
Expand All @@ -377,6 +376,7 @@ class StructDefNode : public ASTNode {
SymbolTableEntry *entry = nullptr;
TypeSpecifiers structSpecifiers = TypeSpecifiers::of(TY_STRUCT);
std::vector<Struct *> structManifestations;
std::map<const std::string, std::vector<Function *>> defaultFctManifestations;
Scope *structScope = nullptr;
};

Expand Down Expand Up @@ -511,7 +511,7 @@ class ExtDeclNode : public ASTNode {
[[nodiscard]] TypeLstNode *argTypeLst() const { return getChild<TypeLstNode>(); }

// Other methods
std::vector<Function *> *getFctManifestations() override { return &extFunctionManifestations; }
std::vector<Function *> *getFctManifestations(const std::string &_) override { return &extFunctionManifestations; }

// Public members
std::string extFunctionName;
Expand Down Expand Up @@ -903,7 +903,7 @@ class SignatureNode : public ASTNode {
[[nodiscard]] TypeLstNode *paramTypeLst() const { return getChild<TypeLstNode>(hasTemplateTypes ? 1 : 0); }

// Other methods
std::vector<Function *> *getFctManifestations() override { return &signatureManifestations; }
std::vector<Function *> *getFctManifestations(const std::string &_) override { return &signatureManifestations; }

// Public members
Type signatureType = SignatureNode::TYPE_NONE;
Expand Down
1 change: 1 addition & 0 deletions src/exception/SemanticError.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
namespace spice::compiler {

SemanticError::SemanticError(const ASTNode *node, const SemanticErrorType &type, const std::string &message) {
assert(node != nullptr);
errorMessage = "[Error|Semantic] " + node->codeLoc.toPrettyString() + ":\n";
errorMessage += getMessagePrefix(type) + ": " + message;
if (!node->errorMessage.empty())
Expand Down
5 changes: 5 additions & 0 deletions src/global/RuntimeModuleManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ SourceFile *RuntimeModuleManager::requestModule(SourceFile *parentSourceFile, Ru
return rtFile;
}

SourceFile *RuntimeModuleManager::getModule(RuntimeModule requestedModule) const {
assert(isModuleAvailable(requestedModule));
return modules.at(requestedModule);
}

bool RuntimeModuleManager::isModuleAvailable(RuntimeModule requestedModule) const { return modules.contains(requestedModule); }

SourceFile *RuntimeModuleManager::loadModule(SourceFile *parentSourceFile, RuntimeModule requestedModule) {
Expand Down
1 change: 1 addition & 0 deletions src/global/RuntimeModuleManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class RuntimeModuleManager {

// Public methods
SourceFile *requestModule(SourceFile *parentSourceFile, RuntimeModule requestedModule);
[[nodiscard]] SourceFile *getModule(RuntimeModule requestedModule) const;
[[nodiscard]] bool isModuleAvailable(RuntimeModule requestedModule) const;

private:
Expand Down
2 changes: 1 addition & 1 deletion src/irgenerator/DebugInfoGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ llvm::DIType *DebugInfoGenerator::getDITypeForSymbolType(const ASTNode *node, co
for (size_t i = 0; i < spiceStruct->fieldTypes.size(); i++) {
// Get field entry
SymbolTableEntry *fieldEntry = spiceStruct->structScope->symbolTable.lookupStrictByIndex(i);
assert(fieldEntry != nullptr);
assert(fieldEntry != nullptr && fieldEntry->isField());
const SymbolType fieldType = fieldEntry->getType();
const size_t fieldLineNo = fieldEntry->declNode->codeLoc.line;
const size_t offsetInBits = structLayout->getElementOffsetInBits(i);
Expand Down
Loading

0 comments on commit cad161a

Please sign in to comment.