Skip to content

Commit

Permalink
Add support for public type aliases (#565)
Browse files Browse the repository at this point in the history
  • Loading branch information
marcauberer authored May 25, 2024
1 parent b8951c4 commit ccb3d9d
Show file tree
Hide file tree
Showing 18 changed files with 51 additions and 35 deletions.
10 changes: 8 additions & 2 deletions media/test-project/test.spice
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import "std/os/env";
import "test2";

f<int> main() {
TestAlias ta;
}

/*import "std/os/env";
import "bootstrap/ast/ast-nodes";
import "bootstrap/lexer/lexer";
import "bootstrap/parser/parser";
Expand All @@ -10,4 +16,4 @@ f<int> main() {
ASTEntryNode* ast = parser.parse();
assert ast != nil<ASTEntryNode*>;
printf("All assertions passed!\n");
}
}*/
4 changes: 1 addition & 3 deletions media/test-project/test2.spice
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
public f<int> functionInModuleB(int x, int y) {
return x + y;
}
public type TestAlias alias int;
2 changes: 1 addition & 1 deletion src/SourceFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ struct CompilerOutput {

struct NameRegistryEntry {
std::string name;
uint64_t typeId; // Set for structs, interfaces and enums
uint64_t typeId; // Set for structs, interfaces, enums and aliases
SymbolTableEntry *targetEntry;
Scope *targetScope;
SymbolTableEntry *importEntry = nullptr;
Expand Down
1 change: 1 addition & 0 deletions src/ast/ASTBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ std::any ASTBuilder::visitAliasDef(SpiceParser::AliasDefContext *ctx) {
// Enrich
aliasDefNode->aliasName = getIdentifier(ctx->TYPE_IDENTIFIER());
aliasDefNode->dataTypeString = ctx->dataType()->getText();
aliasDefNode->typeId = resourceManager.getNextCustomTypeId();

// Visit children
visitChildren(ctx);
Expand Down
1 change: 1 addition & 0 deletions src/ast/ASTNodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,7 @@ class AliasDefNode : public TopLevelDefNode {
TypeSpecifiers aliasSpecifiers = TypeSpecifiers::of(TY_ALIAS);
std::string aliasName;
std::string dataTypeString;
uint64_t typeId;
SymbolTableEntry *entry = nullptr;
SymbolTableEntry *aliasedTypeContainerEntry = nullptr;
};
Expand Down
2 changes: 2 additions & 0 deletions src/symboltablebuilder/SymbolTableBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,8 @@ std::any SymbolTableBuilder::visitAliasDef(AliasDefNode *node) {

// Add the alias to the symbol table
node->entry = rootScope->insert(node->aliasName, node);
// Register the name in the exported name registry
sourceFile->addNameRegistryEntry(node->aliasName, node->typeId, node->entry, rootScope, true);

// Add another symbol for the aliased type container
const std::string aliasedTypeContainerName = node->aliasName + ALIAS_CONTAINER_SUFFIX;
Expand Down
21 changes: 9 additions & 12 deletions src/typechecker/TypeChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2392,25 +2392,14 @@ std::any TypeChecker::visitCustomDataType(CustomDataTypeNode *node) {
return node->setEvaluatedSymbolType(symbolType, manIdx);
}

// Check if it is a type alias
SymbolTableEntry *aliasEntry = rootScope->lookupStrict(firstFragment);
if (!isImported && aliasEntry && aliasEntry->getQualType().is(TY_ALIAS)) {
// Set alias entry used
aliasEntry->used = true;
// Get type of aliased type container entry
const std::string aliasedContainerEntryName = aliasEntry->name + ALIAS_CONTAINER_SUFFIX;
SymbolTableEntry *aliasedTypeContainerEntry = rootScope->lookupStrict(aliasedContainerEntryName);
assert(aliasedTypeContainerEntry != nullptr);
return node->setEvaluatedSymbolType(aliasedTypeContainerEntry->getQualType(), manIdx);
}

// Check if the type exists in the exported names registry
const NameRegistryEntry *registryEntry = sourceFile->getNameRegistryEntry(node->fqTypeName);
if (!registryEntry)
SOFT_ERROR_QT(node, UNKNOWN_DATATYPE, "Unknown datatype '" + node->fqTypeName + "'")
assert(registryEntry->targetEntry != nullptr && registryEntry->targetScope != nullptr);
SymbolTableEntry *entry = registryEntry->targetEntry;
assert(entry != nullptr);
entry->used = true;
localAccessScope = registryEntry->targetScope->parent;

// Get struct type
Expand Down Expand Up @@ -2467,6 +2456,14 @@ std::any TypeChecker::visitCustomDataType(CustomDataTypeNode *node) {
return node->setEvaluatedSymbolType(entryType, manIdx);
}

if (entryType.is(TY_ALIAS)) {
// Get type of aliased type container entry
const std::string aliasedContainerEntryName = entry->name + ALIAS_CONTAINER_SUFFIX;
SymbolTableEntry *aliasedTypeContainerEntry = entry->scope->lookupStrict(aliasedContainerEntryName);
assert(aliasedTypeContainerEntry != nullptr);
return node->setEvaluatedSymbolType(aliasedTypeContainerEntry->getQualType(), manIdx);
}

const bool isInvalid = entryType.is(TY_INVALID);
SOFT_ERROR_QT(node, EXPECTED_TYPE, isInvalid ? "Used type before declared" : "Expected type, but got " + entryType.getName())
}
Expand Down
5 changes: 2 additions & 3 deletions src/typechecker/TypeCheckerPrepare.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -566,9 +566,8 @@ std::any TypeChecker::visitAliasDefPrepare(AliasDefNode *node) {
assert(node->entry != nullptr && node->aliasedTypeContainerEntry != nullptr);

// Update type of alias entry
QualType aliasType(TY_ALIAS, node->dataTypeString);
aliasType.setSpecifiers(node->aliasSpecifiers);
node->entry->updateType(aliasType, false);
const Type *type = TypeRegistry::getOrInsert(TY_ALIAS, node->aliasName, node->typeId, {}, {});
node->entry->updateType(QualType(type, node->aliasSpecifiers), false);

// Update type of the aliased type container entry
auto aliasedType = std::any_cast<QualType>(visit(node->dataType()));
Expand Down
13 changes: 3 additions & 10 deletions src/util/CommonUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,20 +110,13 @@ bool CommonUtil::isValidMangledName(const std::string &mangledName) {
* @return Error message
*/
std::string CommonUtil::getCircularImportMessage(std::stack<const SourceFile *> &sourceFiles) {
// Reverse the stack to print source files in the correct order
std::stack<const char *> sourceFileNames;
while (!sourceFiles.empty()) {
sourceFileNames.push(sourceFiles.top()->fileName.c_str());
sourceFiles.pop();
}

std::stringstream message;
message << "*-----*\n";
message << "| |\n";
while (!sourceFileNames.empty()) {
message << "| " << sourceFileNames.top() << "\n";
while (!sourceFiles.empty()) {
message << "| " << sourceFiles.top()->fileName << "\n";
message << "| |\n";
sourceFileNames.pop();
sourceFiles.pop();
}
message << "*-----*";
return message.str();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Error*
Pthread_attr_t
Pthread_attr_t&
Pthread_attr_t*
Pthread_t
Thread
Thread
Thread&
Expand All @@ -27,7 +28,6 @@ import
int
invalid
long
long
long*
p()
p()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@
"name": "Alias",
"orderIndex": 2,
"state": "declared",
"type": "TestStruct<long>"
"type": "Alias"
},
{
"codeLoc": "L3C1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ Circular import detected: Circular import detected while importing 'source.spice

*-----*
| |
| source2.spice
| source.spice
| |
| source1.spice
| |
| source.spice
| source2.spice
| |
*-----*

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import "source1";

f<int> main() {
TestStruct ts;
TestInterface ti;
TestEnum te;
TestAlias ta;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
public type TestStruct struct {}

public type TestInterface interface {}

public type TestEnum enum {
A,
B,
C
}

public type TestAlias alias TestStruct*;

0 comments on commit ccb3d9d

Please sign in to comment.