From a69516b917f128197691a139f7ea39dfc25a12f1 Mon Sep 17 00:00:00 2001 From: venko Date: Thu, 27 May 2021 11:53:01 -0700 Subject: [PATCH 1/7] Fixes typo and removes unused variable. --- src/typeutils.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/typeutils.c b/src/typeutils.c index a63420c..4ebddea 100644 --- a/src/typeutils.c +++ b/src/typeutils.c @@ -51,7 +51,6 @@ void ConvertIdCustomsToGenerics(IdNode *node) { /* FIXME: This function will need to be modified to handle type parameters over structs. */ void ConvertASTCustomsToGenerics(Node *node) { - uint32_t i; switch (node->syntaxKind) { case Declaration: @@ -78,6 +77,6 @@ void ConvertASTCustomsToGenerics(Node *node) { } default: - recurse(node, *ConvertASTCustomsToGenerics); + Recurse(node, *ConvertASTCustomsToGenerics); } } -- 2.25.1 From ece20a99b55b3bd1dd20598a6640f79d60603805 Mon Sep 17 00:00:00 2001 From: venko Date: Thu, 27 May 2021 14:10:44 -0700 Subject: [PATCH 2/7] Fixes printing bug for string literals --- src/ast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ast.c b/src/ast.c index 9604dbf..d87870b 100644 --- a/src/ast.c +++ b/src/ast.c @@ -705,7 +705,7 @@ void PrintNode(Node *node, uint32_t tabCount) return; case StringLiteral: - printf("%s", node->stringLiteral.string); + printf("%s\n", node->stringLiteral.string); return; case StructDeclaration: -- 2.25.1 From e3fc2826ea2a4e895d318f3ccd7370aa9685cd7f Mon Sep 17 00:00:00 2001 From: venko Date: Thu, 27 May 2021 16:17:25 -0700 Subject: [PATCH 3/7] Reimplements identifier lookup to work over the AST --- src/ast.c | 207 +++++++++++++++++++++++++++++++++++++++++++++++ src/ast.h | 3 + src/identcheck.c | 2 +- src/main.c | 1 + 4 files changed, 212 insertions(+), 1 deletion(-) diff --git a/src/ast.c b/src/ast.c index d87870b..f34fc61 100644 --- a/src/ast.c +++ b/src/ast.c @@ -1,5 +1,6 @@ #include "ast.h" +#include #include #include @@ -989,3 +990,209 @@ char *TypeTagToString(TypeTag *tag) } } } + +void LinkParentPointers(Node *node) +{ + static Node *parent = NULL; + + if (node == NULL) + { + fprintf(stderr, "wraith: Encountered NULL node while linking parent pointers.\n"); + return; + } + + node->parent = parent; + parent = node; + Recurse(node, *LinkParentPointers); +} + +Node *GetIdFromStruct(Node *structDecl) +{ + if (structDecl->syntaxKind != StructDeclaration) + { + fprintf(stderr, "wraith: Attempted to call GetIdFromStruct on node with kind: %s.\n", + SyntaxKindString(structDecl->syntaxKind)); + return NULL; + } + + return structDecl->structDeclaration.identifier; +} + +Node *GetIdFromFunction(Node *funcDecl) +{ + if (funcDecl->syntaxKind != FunctionDeclaration) + { + fprintf(stderr, "wraith: Attempted to call GetIdFromFunction on node with kind: %s.\n", + SyntaxKindString(funcDecl->syntaxKind)); + return NULL; + } + + Node *sig = funcDecl->functionDeclaration.functionSignature; + return sig->functionSignature.identifier; +} + +Node *GetIdFromDeclaration(Node *decl) +{ + if (decl->syntaxKind != Declaration) + { + fprintf(stderr, "wraith: Attempted to call GetIdFromDeclaration on node with kind: %s.\n", + SyntaxKindString(decl->syntaxKind)); + } + + return decl->declaration.identifier; +} + +bool AssignmentHasDeclaration(Node *assign) +{ + return (assign->syntaxKind == Assignment + && assign->assignmentStatement.left->syntaxKind == Declaration); +} + +Node *GetIdFromAssignment(Node *assign) +{ + if (assign->syntaxKind != Assignment) + { + fprintf(stderr, "wraith: Attempted to call GetIdFromAssignment on node with kind: %s.\n", + SyntaxKindString(assign->syntaxKind)); + } + + if (AssignmentHasDeclaration(assign)) + { + return GetIdFromDeclaration(assign->assignmentStatement.left); + } + + return NULL; +} + +bool NodeMayHaveId(Node *node) +{ + switch (node->syntaxKind) + { + case StructDeclaration: + case FunctionDeclaration: + case Declaration: + case Assignment: + return true; + default: + return false; + } +} + +Node *TryGetId(Node *node) +{ + switch (node->syntaxKind) + { + case StructDeclaration: + return GetIdFromStruct(node); + case FunctionDeclaration: + return GetIdFromFunction(node); + case Declaration: + return GetIdFromDeclaration(node); + default: + return NULL; + } +} + +Node *LookupFunctionArgId(Node *funcDecl, char *target) +{ + Node *args = + funcDecl->functionDeclaration.functionSignature->functionSignature.arguments; + + uint32_t i; + for (i = 0; i < args->functionArgumentSequence.count; i += 1) + { + Node *arg = args->functionArgumentSequence.sequence[i]; + if (arg->syntaxKind != Declaration) + { + fprintf(stderr, + "wraith: Encountered %s node in function signature args list.\n", + SyntaxKindString(arg->syntaxKind)); + continue; + } + + Node *argId = GetIdFromDeclaration(arg); + if (argId != NULL && strcmp(target, argId->identifier.name) == 0) + { + return argId; + } + } + + return NULL; +} + +Node *LookupIdNode(Node *current, Node *prev, char *target) +{ + if (current == NULL) return NULL; + + /* If this node may have an identifier declaration inside it, attempt to look up the identifier + * node itself, returning it if it matches the given target name. */ + if (NodeMayHaveId(current)) + { + Node *candidateId = TryGetId(current); + if (candidateId != NULL && strcmp(target, candidateId->identifier.name) == 0) + { + return candidateId; + } + + /* If the candidate node was not the one we wanted, but the current node is a function + * declaration, it's possible that the identifier we want is one of the function's + * parameters rather than the function's name itself. */ + if (current->syntaxKind == FunctionDeclaration) + { + Node *match = LookupFunctionArgId(current, target); + if (match != NULL) return match; + } + } + + /* If this is the start of our search, we should not attempt to look at + * child nodes. Only looking up the AST is valid at this point. + * + * This has the notable side-effect that this function will return NULL if + * you attempt to look up a struct's internals starting from the node + * representing the struct itself. */ + if (prev == NULL) + { + return LookupIdNode(current->parent, current, target); + } + + uint32_t i; + uint32_t idxLimit; + switch (current->syntaxKind) + { + case DeclarationSequence: + for (i = 0; i < current->declarationSequence.count; i += 1) + { + Node *decl = current->declarationSequence.sequence[i]; + Node *declId = TryGetId(decl); + if (declId != NULL) return declId; + } + break; + case StatementSequence: + idxLimit = current->statementSequence.count; + for (i = 0; i < current->statementSequence.count; i += 1) + { + if (current->statementSequence.sequence[i] == prev) + { + idxLimit = i; + break; + } + } + + for (i = 0; i < idxLimit; i += 1) + { + Node *stmt = current->statementSequence.sequence[i]; + if (stmt == prev) continue; + + if (NodeMayHaveId(stmt)) + { + Node *candidateId = TryGetId(current); + if (candidateId != NULL && strcmp(target, candidateId->identifier.name) == 0) + { + return candidateId; + } + } + } + break; + } + return LookupIdNode(current->parent, current, target); +} diff --git a/src/ast.h b/src/ast.h index 8ad54a0..967cbe5 100644 --- a/src/ast.h +++ b/src/ast.h @@ -373,7 +373,10 @@ const char *SyntaxKindString(SyntaxKind syntaxKind); * function in all other cases. */ void Recurse(Node *node, void (*func)(Node*)); +void LinkParentPointers(Node *node); + TypeTag *MakeTypeTag(Node *node); char *TypeTagToString(TypeTag *tag); +Node *LookupIdNode(Node *current, Node *prev, char *target); #endif /* WRAITH_AST_H */ diff --git a/src/identcheck.c b/src/identcheck.c index d2bd6c6..39498b0 100644 --- a/src/identcheck.c +++ b/src/identcheck.c @@ -187,7 +187,7 @@ IdNode *MakeIdTree(Node *astNode, IdNode *parent) { char *name = astNode->identifier.name; mainNode = MakeIdNode(Placeholder, name, parent); - IdNode *lookupNode = LookupId(mainNode, NULL, name); + Node *lookupNode = LookupIdNode(astNode, NULL, name); if (lookupNode == NULL) { fprintf(stderr, "wraith: Could not find IdNode for id %s\n", name); diff --git a/src/main.c b/src/main.c index cbb7e80..044210c 100644 --- a/src/main.c +++ b/src/main.c @@ -86,6 +86,7 @@ int main(int argc, char *argv[]) } else { + LinkParentPointers(rootNode); { IdNode *idTree = MakeIdTree(rootNode, NULL); printf("\n"); -- 2.25.1 From 7d5f5997120c1b91d6e7b5306c8888bd475c041f Mon Sep 17 00:00:00 2001 From: venko Date: Sat, 29 May 2021 18:27:13 -0700 Subject: [PATCH 4/7] Lots of bug fixes for id lookup --- src/ast.c | 315 +++++++++++++++++++++++++++++++++++++++++++++++------ src/ast.h | 4 +- src/main.c | 21 +--- 3 files changed, 291 insertions(+), 49 deletions(-) diff --git a/src/ast.c b/src/ast.c index f34fc61..51f416c 100644 --- a/src/ast.c +++ b/src/ast.c @@ -937,9 +937,16 @@ TypeTag *MakeTypeTag(Node *node) tag = MakeTypeTag(node->allocExpression.type); break; + case GenericArgument: + tag->type = Generic; + tag->value.genericType = strdup(node->genericArgument.identifier + ->identifier.name); + break; + case GenericTypeNode: tag->type = Generic; tag->value.genericType = strdup(node->genericType.name); + break; default: fprintf( @@ -949,6 +956,7 @@ TypeTag *MakeTypeTag(Node *node) SyntaxKindString(node->syntaxKind)); return NULL; } + return tag; } @@ -991,19 +999,167 @@ char *TypeTagToString(TypeTag *tag) } } -void LinkParentPointers(Node *node) +void LinkParentPointers(Node *node, Node *prev) { - static Node *parent = NULL; + if (node == NULL) return; - if (node == NULL) + node->parent = prev; + + uint32_t i; + switch (node->syntaxKind) { - fprintf(stderr, "wraith: Encountered NULL node while linking parent pointers.\n"); + case AccessExpression: + LinkParentPointers(node->accessExpression.accessee, node); + LinkParentPointers(node->accessExpression.accessor, node); + return; + + case AllocExpression: + LinkParentPointers(node->allocExpression.type, node); + return; + + case Assignment: + LinkParentPointers(node->assignmentStatement.left, node); + LinkParentPointers(node->assignmentStatement.right, node); + return; + + case BinaryExpression: + LinkParentPointers(node->binaryExpression.left, node); + LinkParentPointers(node->binaryExpression.right, node); + return; + + case Comment: + return; + + case CustomTypeNode: + return; + + case Declaration: + LinkParentPointers(node->declaration.type, node); + LinkParentPointers(node->declaration.identifier, node); + return; + + case DeclarationSequence: + for (i = 0; i < node->declarationSequence.count; i += 1) { + LinkParentPointers(node->declarationSequence.sequence[i], node); + } + return; + + case ForLoop: + LinkParentPointers(node->forLoop.declaration, node); + LinkParentPointers(node->forLoop.startNumber, node); + LinkParentPointers(node->forLoop.endNumber, node); + LinkParentPointers(node->forLoop.statementSequence, node); + return; + + case FunctionArgumentSequence: + for (i = 0; i < node->functionArgumentSequence.count; i += 1) { + LinkParentPointers(node->functionArgumentSequence.sequence[i], node); + } + return; + + case FunctionCallExpression: + LinkParentPointers(node->functionCallExpression.identifier, node); + LinkParentPointers(node->functionCallExpression.argumentSequence, node); + return; + + case FunctionDeclaration: + LinkParentPointers(node->functionDeclaration.functionSignature, node); + LinkParentPointers(node->functionDeclaration.functionBody, node); + return; + + case FunctionModifiers: + for (i = 0; i < node->functionModifiers.count; i += 1) { + LinkParentPointers(node->functionModifiers.sequence[i], node); + } + return; + + case FunctionSignature: + LinkParentPointers(node->functionSignature.identifier, node); + LinkParentPointers(node->functionSignature.type, node); + LinkParentPointers(node->functionSignature.arguments, node); + LinkParentPointers(node->functionSignature.modifiers, node); + LinkParentPointers(node->functionSignature.genericArguments, node); + return; + + case FunctionSignatureArguments: + for (i = 0; i < node->functionSignatureArguments.count; i += 1) { + LinkParentPointers(node->functionSignatureArguments.sequence[i], node); + } + return; + + case GenericArgument: + LinkParentPointers(node->genericArgument.identifier, node); + LinkParentPointers(node->genericArgument.constraint, node); + return; + + case GenericArguments: + for (i = 0; i < node->genericArguments.count; i += 1) { + LinkParentPointers(node->genericArguments.arguments[i], node); + } + return; + + case GenericTypeNode: + return; + + case Identifier: + return; + + case IfStatement: + LinkParentPointers(node->ifStatement.expression, node); + LinkParentPointers(node->ifStatement.statementSequence, node); + return; + + case IfElseStatement: + LinkParentPointers(node->ifElseStatement.ifStatement, node); + LinkParentPointers(node->ifElseStatement.elseStatement, node); + return; + + case Number: + return; + + case PrimitiveTypeNode: + return; + + case ReferenceTypeNode: + LinkParentPointers(node->referenceType.type, node); + return; + + case Return: + LinkParentPointers(node->returnStatement.expression, node); + return; + + case ReturnVoid: + return; + + case StatementSequence: + for (i = 0; i < node->statementSequence.count; i += 1) { + LinkParentPointers(node->statementSequence.sequence[i], node); + } + return; + + case StaticModifier: + return; + + case StringLiteral: + return; + + case StructDeclaration: + LinkParentPointers(node->structDeclaration.identifier, node); + LinkParentPointers(node->structDeclaration.declarationSequence, node); + return; + + case Type: + return; + + case UnaryExpression: + LinkParentPointers(node->unaryExpression.child, node); + return; + + default: + fprintf(stderr, "wraith: Unhandled SyntaxKind %s in recurse function.\n", + SyntaxKindString(node->syntaxKind)); return; } - - node->parent = parent; - parent = node; - Recurse(node, *LinkParentPointers); } Node *GetIdFromStruct(Node *structDecl) @@ -1082,12 +1238,14 @@ Node *TryGetId(Node *node) { switch (node->syntaxKind) { - case StructDeclaration: - return GetIdFromStruct(node); - case FunctionDeclaration: - return GetIdFromFunction(node); + case Assignment: + return GetIdFromAssignment(node); case Declaration: return GetIdFromDeclaration(node); + case FunctionDeclaration: + return GetIdFromFunction(node); + case StructDeclaration: + return GetIdFromStruct(node); default: return NULL; } @@ -1120,36 +1278,69 @@ Node *LookupFunctionArgId(Node *funcDecl, char *target) return NULL; } -Node *LookupIdNode(Node *current, Node *prev, char *target) +Node *LookupStructInternalId(Node *structDecl, char *target) { - if (current == NULL) return NULL; + Node *decls = structDecl->structDeclaration.declarationSequence; + uint32_t i; + for (i = 0; i < decls->declarationSequence.count; i += 1) + { + Node *match = TryGetId(decls->declarationSequence.sequence[i]); + if (match != NULL && strcmp(target, match->identifier.name) == 0) + return match; + } + + return NULL; +} + +Node *InspectNode(Node *node, char *target) +{ /* If this node may have an identifier declaration inside it, attempt to look up the identifier * node itself, returning it if it matches the given target name. */ - if (NodeMayHaveId(current)) + if (NodeMayHaveId(node)) { - Node *candidateId = TryGetId(current); + Node *candidateId = TryGetId(node); if (candidateId != NULL && strcmp(target, candidateId->identifier.name) == 0) { return candidateId; } - - /* If the candidate node was not the one we wanted, but the current node is a function - * declaration, it's possible that the identifier we want is one of the function's - * parameters rather than the function's name itself. */ - if (current->syntaxKind == FunctionDeclaration) - { - Node *match = LookupFunctionArgId(current, target); - if (match != NULL) return match; - } } + /* If the candidate node was not the one we wanted, but the node node is a function + * declaration, it's possible that the identifier we want is one of the function's + * parameters rather than the function's name itself. */ + if (node->syntaxKind == FunctionDeclaration) + { + Node *match = LookupFunctionArgId(node, target); + if (match != NULL) return match; + } + + /* Likewise if the node node is a struct declaration, inspect the struct's internals + * to see if a top-level definition is the one we're looking for. */ + if (node->syntaxKind == StructDeclaration) + { + Node *match = LookupStructInternalId(node, target); + if (match != NULL) return match; + } + + return NULL; +} + +Node *LookupIdNode(Node *current, Node *prev, char *target) +{ + if (current == NULL) return NULL; + Node *match; + + /* First inspect the current node to see if it contains the target identifier. */ + match = InspectNode(current, target); + if (match != NULL) return match; + /* If this is the start of our search, we should not attempt to look at * child nodes. Only looking up the AST is valid at this point. * * This has the notable side-effect that this function will return NULL if * you attempt to look up a struct's internals starting from the node - * representing the struct itself. */ + * representing the struct itself. The same is true for functions. */ if (prev == NULL) { return LookupIdNode(current->parent, current, target); @@ -1163,8 +1354,11 @@ Node *LookupIdNode(Node *current, Node *prev, char *target) for (i = 0; i < current->declarationSequence.count; i += 1) { Node *decl = current->declarationSequence.sequence[i]; - Node *declId = TryGetId(decl); - if (declId != NULL) return declId; + match = InspectNode(decl, target); + if (match != NULL) return match; + /*Node *declId = TryGetId(decl); + if (declId != NULL && strcmp(target, declId->identifier.name) == 0) + return declId;*/ } break; case StatementSequence: @@ -1183,16 +1377,73 @@ Node *LookupIdNode(Node *current, Node *prev, char *target) Node *stmt = current->statementSequence.sequence[i]; if (stmt == prev) continue; - if (NodeMayHaveId(stmt)) + if (strcmp(target, "g") == 0) { + printf("info: %s\n", SyntaxKindString(stmt->syntaxKind)); + } + + match = InspectNode(stmt, target); + if (match != NULL) return match; + /*if (NodeMayHaveId(stmt)) { Node *candidateId = TryGetId(current); if (candidateId != NULL && strcmp(target, candidateId->identifier.name) == 0) - { return candidateId; - } - } + }*/ } break; } + return LookupIdNode(current->parent, current, target); } + +void IdentifierPass(Node *node) +{ + if (node == NULL) return; + + switch (node->syntaxKind) + { + case AllocExpression: + node->typeTag = MakeTypeTag(node); + break; + + case Declaration: + node->declaration.identifier->typeTag = MakeTypeTag(node); + break; + + case FunctionDeclaration: + node->functionDeclaration.functionSignature + ->functionSignature.identifier->typeTag = MakeTypeTag(node); + break;; + + case StructDeclaration: + node->structDeclaration.identifier->typeTag = MakeTypeTag(node); + break; + + case GenericArgument: + node->genericArgument.identifier->typeTag = MakeTypeTag(node); + break; + + case Identifier: + { + if (node->typeTag != NULL) return; + + char *name = node->identifier.name; + Node *declaration = LookupIdNode(node, NULL, name); + if (declaration == NULL) + { + /* FIXME: Express this case as an error with AST information. */ + fprintf(stderr, "wraith: Could not find definition of identifier %s.\n", name); + TypeTag *tag = (TypeTag *)malloc(sizeof(TypeTag)); + tag->type = Unknown; + node->typeTag = tag; + } + else + { + node->typeTag = declaration->typeTag; + } + break; + } + } + + Recurse(node, *IdentifierPass); +} \ No newline at end of file diff --git a/src/ast.h b/src/ast.h index 967cbe5..251f0f6 100644 --- a/src/ast.h +++ b/src/ast.h @@ -373,10 +373,12 @@ const char *SyntaxKindString(SyntaxKind syntaxKind); * function in all other cases. */ void Recurse(Node *node, void (*func)(Node*)); -void LinkParentPointers(Node *node); +void LinkParentPointers(Node *node, Node *prev); TypeTag *MakeTypeTag(Node *node); char *TypeTagToString(TypeTag *tag); Node *LookupIdNode(Node *current, Node *prev, char *target); + +void IdentifierPass(Node *node); #endif /* WRAITH_AST_H */ diff --git a/src/main.c b/src/main.c index 044210c..1b7c70b 100644 --- a/src/main.c +++ b/src/main.c @@ -86,23 +86,12 @@ int main(int argc, char *argv[]) } else { - LinkParentPointers(rootNode); - { - IdNode *idTree = MakeIdTree(rootNode, NULL); - printf("\n"); - PrintIdTree(idTree, /*tabCount=*/0); + LinkParentPointers(rootNode, NULL); + IdentifierPass(rootNode); + /*ConvertASTCustomsToGenerics(rootNode);*/ + PrintNode(rootNode, 0); - printf("\nConverting custom types in the ID-tree.\n"); - ConvertIdCustomsToGenerics(idTree); - printf("\n"); - PrintIdTree(idTree, /*tabCount=*/0); - - printf("\nConverting custom type nodes in the AST.\n"); - ConvertASTCustomsToGenerics(rootNode); - printf("\n"); - PrintNode(rootNode, /*tabCount=*/0); - - } + printf("Beginning codegen.\n"); exitCode = Codegen(rootNode, optimizationLevel); } } -- 2.25.1 From 7f2ca56b731b3397dd3a139cda7dd7f6cc71cd95 Mon Sep 17 00:00:00 2001 From: venko Date: Sun, 30 May 2021 13:07:12 -0700 Subject: [PATCH 5/7] Applies clang-format --- src/ast.c | 187 +++++++++++++++++++++++++++++++++++------------------- src/ast.h | 11 ++-- 2 files changed, 128 insertions(+), 70 deletions(-) diff --git a/src/ast.c b/src/ast.c index 51f416c..4e244c3 100644 --- a/src/ast.c +++ b/src/ast.c @@ -639,7 +639,8 @@ void PrintNode(Node *node, uint32_t tabCount) case GenericArguments: printf("\n"); - for (i = 0; i < node->genericArguments.count; i += 1) { + for (i = 0; i < node->genericArguments.count; i += 1) + { PrintNode(node->genericArguments.arguments[i], tabCount + 1); } return; @@ -727,7 +728,7 @@ void PrintNode(Node *node, uint32_t tabCount) } } -void Recurse(Node *node, void (*func)(Node*)) +void Recurse(Node *node, void (*func)(Node *)) { uint32_t i; switch (node->syntaxKind) @@ -763,7 +764,8 @@ void Recurse(Node *node, void (*func)(Node*)) return; case DeclarationSequence: - for (i = 0; i < node->declarationSequence.count; i += 1) { + for (i = 0; i < node->declarationSequence.count; i += 1) + { func(node->declarationSequence.sequence[i]); } return; @@ -776,7 +778,8 @@ void Recurse(Node *node, void (*func)(Node*)) return; case FunctionArgumentSequence: - for (i = 0; i < node->functionArgumentSequence.count; i += 1) { + for (i = 0; i < node->functionArgumentSequence.count; i += 1) + { func(node->functionArgumentSequence.sequence[i]); } return; @@ -792,7 +795,8 @@ void Recurse(Node *node, void (*func)(Node*)) return; case FunctionModifiers: - for (i = 0; i < node->functionModifiers.count; i += 1) { + for (i = 0; i < node->functionModifiers.count; i += 1) + { func(node->functionModifiers.sequence[i]); } return; @@ -806,7 +810,8 @@ void Recurse(Node *node, void (*func)(Node*)) return; case FunctionSignatureArguments: - for (i = 0; i < node->functionSignatureArguments.count; i += 1) { + for (i = 0; i < node->functionSignatureArguments.count; i += 1) + { func(node->functionSignatureArguments.sequence[i]); } return; @@ -817,7 +822,8 @@ void Recurse(Node *node, void (*func)(Node*)) return; case GenericArguments: - for (i = 0; i < node->genericArguments.count; i += 1) { + for (i = 0; i < node->genericArguments.count; i += 1) + { func(node->genericArguments.arguments[i]); } return; @@ -856,7 +862,8 @@ void Recurse(Node *node, void (*func)(Node*)) return; case StatementSequence: - for (i = 0; i < node->statementSequence.count; i += 1) { + for (i = 0; i < node->statementSequence.count; i += 1) + { func(node->statementSequence.sequence[i]); } return; @@ -880,8 +887,10 @@ void Recurse(Node *node, void (*func)(Node*)) return; default: - fprintf(stderr, "wraith: Unhandled SyntaxKind %s in recurse function.\n", - SyntaxKindString(node->syntaxKind)); + fprintf( + stderr, + "wraith: Unhandled SyntaxKind %s in recurse function.\n", + SyntaxKindString(node->syntaxKind)); return; } } @@ -939,8 +948,8 @@ TypeTag *MakeTypeTag(Node *node) case GenericArgument: tag->type = Generic; - tag->value.genericType = strdup(node->genericArgument.identifier - ->identifier.name); + tag->value.genericType = + strdup(node->genericArgument.identifier->identifier.name); break; case GenericTypeNode: @@ -986,13 +995,15 @@ char *TypeTagToString(TypeTag *tag) } case Custom: { - char *result = malloc(sizeof(char) * (strlen(tag->value.customType) + 8)); + char *result = + malloc(sizeof(char) * (strlen(tag->value.customType) + 8)); sprintf(result, "Custom<%s>", tag->value.customType); return result; } case Generic: { - char *result = malloc(sizeof(char) * (strlen(tag->value.customType) + 9)); + char *result = + malloc(sizeof(char) * (strlen(tag->value.customType) + 9)); sprintf(result, "Generic<%s>", tag->value.customType); return result; } @@ -1001,7 +1012,8 @@ char *TypeTagToString(TypeTag *tag) void LinkParentPointers(Node *node, Node *prev) { - if (node == NULL) return; + if (node == NULL) + return; node->parent = prev; @@ -1039,7 +1051,8 @@ void LinkParentPointers(Node *node, Node *prev) return; case DeclarationSequence: - for (i = 0; i < node->declarationSequence.count; i += 1) { + for (i = 0; i < node->declarationSequence.count; i += 1) + { LinkParentPointers(node->declarationSequence.sequence[i], node); } return; @@ -1052,8 +1065,11 @@ void LinkParentPointers(Node *node, Node *prev) return; case FunctionArgumentSequence: - for (i = 0; i < node->functionArgumentSequence.count; i += 1) { - LinkParentPointers(node->functionArgumentSequence.sequence[i], node); + for (i = 0; i < node->functionArgumentSequence.count; i += 1) + { + LinkParentPointers( + node->functionArgumentSequence.sequence[i], + node); } return; @@ -1068,7 +1084,8 @@ void LinkParentPointers(Node *node, Node *prev) return; case FunctionModifiers: - for (i = 0; i < node->functionModifiers.count; i += 1) { + for (i = 0; i < node->functionModifiers.count; i += 1) + { LinkParentPointers(node->functionModifiers.sequence[i], node); } return; @@ -1082,8 +1099,11 @@ void LinkParentPointers(Node *node, Node *prev) return; case FunctionSignatureArguments: - for (i = 0; i < node->functionSignatureArguments.count; i += 1) { - LinkParentPointers(node->functionSignatureArguments.sequence[i], node); + for (i = 0; i < node->functionSignatureArguments.count; i += 1) + { + LinkParentPointers( + node->functionSignatureArguments.sequence[i], + node); } return; @@ -1093,7 +1113,8 @@ void LinkParentPointers(Node *node, Node *prev) return; case GenericArguments: - for (i = 0; i < node->genericArguments.count; i += 1) { + for (i = 0; i < node->genericArguments.count; i += 1) + { LinkParentPointers(node->genericArguments.arguments[i], node); } return; @@ -1132,7 +1153,8 @@ void LinkParentPointers(Node *node, Node *prev) return; case StatementSequence: - for (i = 0; i < node->statementSequence.count; i += 1) { + for (i = 0; i < node->statementSequence.count; i += 1) + { LinkParentPointers(node->statementSequence.sequence[i], node); } return; @@ -1156,8 +1178,10 @@ void LinkParentPointers(Node *node, Node *prev) return; default: - fprintf(stderr, "wraith: Unhandled SyntaxKind %s in recurse function.\n", - SyntaxKindString(node->syntaxKind)); + fprintf( + stderr, + "wraith: Unhandled SyntaxKind %s in recurse function.\n", + SyntaxKindString(node->syntaxKind)); return; } } @@ -1166,20 +1190,26 @@ Node *GetIdFromStruct(Node *structDecl) { if (structDecl->syntaxKind != StructDeclaration) { - fprintf(stderr, "wraith: Attempted to call GetIdFromStruct on node with kind: %s.\n", - SyntaxKindString(structDecl->syntaxKind)); + fprintf( + stderr, + "wraith: Attempted to call GetIdFromStruct on node with kind: " + "%s.\n", + SyntaxKindString(structDecl->syntaxKind)); return NULL; } return structDecl->structDeclaration.identifier; } -Node *GetIdFromFunction(Node *funcDecl) +Node *GetIdFromFunction(Node *funcDecl) { if (funcDecl->syntaxKind != FunctionDeclaration) { - fprintf(stderr, "wraith: Attempted to call GetIdFromFunction on node with kind: %s.\n", - SyntaxKindString(funcDecl->syntaxKind)); + fprintf( + stderr, + "wraith: Attempted to call GetIdFromFunction on node with kind: " + "%s.\n", + SyntaxKindString(funcDecl->syntaxKind)); return NULL; } @@ -1191,8 +1221,11 @@ Node *GetIdFromDeclaration(Node *decl) { if (decl->syntaxKind != Declaration) { - fprintf(stderr, "wraith: Attempted to call GetIdFromDeclaration on node with kind: %s.\n", - SyntaxKindString(decl->syntaxKind)); + fprintf( + stderr, + "wraith: Attempted to call GetIdFromDeclaration on node with kind: " + "%s.\n", + SyntaxKindString(decl->syntaxKind)); } return decl->declaration.identifier; @@ -1200,16 +1233,20 @@ Node *GetIdFromDeclaration(Node *decl) bool AssignmentHasDeclaration(Node *assign) { - return (assign->syntaxKind == Assignment - && assign->assignmentStatement.left->syntaxKind == Declaration); + return ( + assign->syntaxKind == Assignment && + assign->assignmentStatement.left->syntaxKind == Declaration); } Node *GetIdFromAssignment(Node *assign) { if (assign->syntaxKind != Assignment) { - fprintf(stderr, "wraith: Attempted to call GetIdFromAssignment on node with kind: %s.\n", - SyntaxKindString(assign->syntaxKind)); + fprintf( + stderr, + "wraith: Attempted to call GetIdFromAssignment on node with kind: " + "%s.\n", + SyntaxKindString(assign->syntaxKind)); } if (AssignmentHasDeclaration(assign)) @@ -1253,8 +1290,8 @@ Node *TryGetId(Node *node) Node *LookupFunctionArgId(Node *funcDecl, char *target) { - Node *args = - funcDecl->functionDeclaration.functionSignature->functionSignature.arguments; + Node *args = funcDecl->functionDeclaration.functionSignature + ->functionSignature.arguments; uint32_t i; for (i = 0; i < args->functionArgumentSequence.count; i += 1) @@ -1262,15 +1299,17 @@ Node *LookupFunctionArgId(Node *funcDecl, char *target) Node *arg = args->functionArgumentSequence.sequence[i]; if (arg->syntaxKind != Declaration) { - fprintf(stderr, - "wraith: Encountered %s node in function signature args list.\n", - SyntaxKindString(arg->syntaxKind)); + fprintf( + stderr, + "wraith: Encountered %s node in function signature args " + "list.\n", + SyntaxKindString(arg->syntaxKind)); continue; } Node *argId = GetIdFromDeclaration(arg); if (argId != NULL && strcmp(target, argId->identifier.name) == 0) - { + { return argId; } } @@ -1295,32 +1334,37 @@ Node *LookupStructInternalId(Node *structDecl, char *target) Node *InspectNode(Node *node, char *target) { - /* If this node may have an identifier declaration inside it, attempt to look up the identifier + /* If this node may have an identifier declaration inside it, attempt to + * look up the identifier * node itself, returning it if it matches the given target name. */ if (NodeMayHaveId(node)) { Node *candidateId = TryGetId(node); - if (candidateId != NULL && strcmp(target, candidateId->identifier.name) == 0) + if (candidateId != NULL && + strcmp(target, candidateId->identifier.name) == 0) { return candidateId; } } - /* If the candidate node was not the one we wanted, but the node node is a function - * declaration, it's possible that the identifier we want is one of the function's - * parameters rather than the function's name itself. */ + /* If the candidate node was not the one we wanted, but the node node is a + * function declaration, it's possible that the identifier we want is one of + * the function's parameters rather than the function's name itself. */ if (node->syntaxKind == FunctionDeclaration) { Node *match = LookupFunctionArgId(node, target); - if (match != NULL) return match; + if (match != NULL) + return match; } - /* Likewise if the node node is a struct declaration, inspect the struct's internals + /* Likewise if the node node is a struct declaration, inspect the struct's + * internals * to see if a top-level definition is the one we're looking for. */ if (node->syntaxKind == StructDeclaration) { Node *match = LookupStructInternalId(node, target); - if (match != NULL) return match; + if (match != NULL) + return match; } return NULL; @@ -1328,12 +1372,15 @@ Node *InspectNode(Node *node, char *target) Node *LookupIdNode(Node *current, Node *prev, char *target) { - if (current == NULL) return NULL; + if (current == NULL) + return NULL; Node *match; - /* First inspect the current node to see if it contains the target identifier. */ + /* First inspect the current node to see if it contains the target + * identifier. */ match = InspectNode(current, target); - if (match != NULL) return match; + if (match != NULL) + return match; /* If this is the start of our search, we should not attempt to look at * child nodes. Only looking up the AST is valid at this point. @@ -1355,7 +1402,8 @@ Node *LookupIdNode(Node *current, Node *prev, char *target) { Node *decl = current->declarationSequence.sequence[i]; match = InspectNode(decl, target); - if (match != NULL) return match; + if (match != NULL) + return match; /*Node *declId = TryGetId(decl); if (declId != NULL && strcmp(target, declId->identifier.name) == 0) return declId;*/ @@ -1375,19 +1423,22 @@ Node *LookupIdNode(Node *current, Node *prev, char *target) for (i = 0; i < idxLimit; i += 1) { Node *stmt = current->statementSequence.sequence[i]; - if (stmt == prev) continue; + if (stmt == prev) + continue; - if (strcmp(target, "g") == 0) { + if (strcmp(target, "g") == 0) + { printf("info: %s\n", SyntaxKindString(stmt->syntaxKind)); } match = InspectNode(stmt, target); - if (match != NULL) return match; + if (match != NULL) + return match; /*if (NodeMayHaveId(stmt)) { Node *candidateId = TryGetId(current); - if (candidateId != NULL && strcmp(target, candidateId->identifier.name) == 0) - return candidateId; + if (candidateId != NULL && strcmp(target, + candidateId->identifier.name) == 0) return candidateId; }*/ } break; @@ -1398,7 +1449,8 @@ Node *LookupIdNode(Node *current, Node *prev, char *target) void IdentifierPass(Node *node) { - if (node == NULL) return; + if (node == NULL) + return; switch (node->syntaxKind) { @@ -1411,9 +1463,10 @@ void IdentifierPass(Node *node) break; case FunctionDeclaration: - node->functionDeclaration.functionSignature - ->functionSignature.identifier->typeTag = MakeTypeTag(node); - break;; + node->functionDeclaration.functionSignature->functionSignature + .identifier->typeTag = MakeTypeTag(node); + break; + ; case StructDeclaration: node->structDeclaration.identifier->typeTag = MakeTypeTag(node); @@ -1425,14 +1478,18 @@ void IdentifierPass(Node *node) case Identifier: { - if (node->typeTag != NULL) return; + if (node->typeTag != NULL) + return; char *name = node->identifier.name; Node *declaration = LookupIdNode(node, NULL, name); if (declaration == NULL) { /* FIXME: Express this case as an error with AST information. */ - fprintf(stderr, "wraith: Could not find definition of identifier %s.\n", name); + fprintf( + stderr, + "wraith: Could not find definition of identifier %s.\n", + name); TypeTag *tag = (TypeTag *)malloc(sizeof(TypeTag)); tag->type = Unknown; node->typeTag = tag; diff --git a/src/ast.h b/src/ast.h index 251f0f6..179d0e6 100644 --- a/src/ast.h +++ b/src/ast.h @@ -367,11 +367,12 @@ Node *MakeForLoopNode( void PrintNode(Node *node, uint32_t tabCount); const char *SyntaxKindString(SyntaxKind syntaxKind); -/* Helper function for applying a void function generically over the children of an AST node. - * Used for functions that need to traverse the entire tree but only perform operations on a subset - * of node types. Such functions can match the syntaxKinds relevant to their purpose and invoke this - * function in all other cases. */ -void Recurse(Node *node, void (*func)(Node*)); +/* Helper function for applying a void function generically over the children of + * an AST node. Used for functions that need to traverse the entire tree but + * only perform operations on a subset of node types. Such functions can match + * the syntaxKinds relevant to their purpose and invoke this function in all + * other cases. */ +void Recurse(Node *node, void (*func)(Node *)); void LinkParentPointers(Node *node, Node *prev); -- 2.25.1 From a65fea070ab76dfa6a64caeb19ce9e6c32371979 Mon Sep 17 00:00:00 2001 From: venko Date: Sun, 30 May 2021 13:20:17 -0700 Subject: [PATCH 6/7] Removes extraneous semicolon --- src/ast.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ast.c b/src/ast.c index 4e244c3..6252788 100644 --- a/src/ast.c +++ b/src/ast.c @@ -1466,7 +1466,6 @@ void IdentifierPass(Node *node) node->functionDeclaration.functionSignature->functionSignature .identifier->typeTag = MakeTypeTag(node); break; - ; case StructDeclaration: node->structDeclaration.identifier->typeTag = MakeTypeTag(node); -- 2.25.1 From 3553269fb0199234474bd7e46ec4331b68dd57b3 Mon Sep 17 00:00:00 2001 From: venko Date: Mon, 31 May 2021 17:03:18 -0700 Subject: [PATCH 7/7] Refactors out identcheck and typeutils code --- CMakeLists.txt | 6 +- access.w | 13 ++ ordering.w | 15 ++ src/ast.c | 319 ----------------------------- src/ast.h | 3 - src/identcheck.c | 507 ----------------------------------------------- src/identcheck.h | 51 ----- src/main.c | 10 +- src/typeutils.c | 82 -------- src/typeutils.h | 13 -- src/validation.c | 452 ++++++++++++++++++++++++++++++++++++++++++ src/validation.h | 10 + 12 files changed, 498 insertions(+), 983 deletions(-) create mode 100644 access.w create mode 100644 ordering.w delete mode 100644 src/identcheck.c delete mode 100644 src/identcheck.h delete mode 100644 src/typeutils.c delete mode 100644 src/typeutils.h create mode 100644 src/validation.c create mode 100644 src/validation.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4cb94d8..1b7a9e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,15 +41,13 @@ add_executable( # Source src/ast.h src/codegen.h - src/identcheck.h src/parser.h - src/typeutils.h + src/validation.h src/util.h src/ast.c src/codegen.c - src/identcheck.c src/parser.c - src/typeutils.c + src/validation.c src/util.c src/main.c # Generated code diff --git a/access.w b/access.w new file mode 100644 index 0000000..2534dd2 --- /dev/null +++ b/access.w @@ -0,0 +1,13 @@ +struct G { + Foo(t: bool): bool { + return t; + } +} + +struct Program { + static main(): int { + g: G = alloc G; + g.Foo(true); + return 0; + } +} \ No newline at end of file diff --git a/ordering.w b/ordering.w new file mode 100644 index 0000000..f446a68 --- /dev/null +++ b/ordering.w @@ -0,0 +1,15 @@ +struct Foo { + static Func(): void { + Func2(); + } + + static Func2(): void { + Func(); + } +} + +struct Program { + static main(): int { + return 0; + } +} \ No newline at end of file diff --git a/src/ast.c b/src/ast.c index 6252788..d57ef1f 100644 --- a/src/ast.c +++ b/src/ast.c @@ -1,6 +1,5 @@ #include "ast.h" -#include #include #include @@ -1185,321 +1184,3 @@ void LinkParentPointers(Node *node, Node *prev) return; } } - -Node *GetIdFromStruct(Node *structDecl) -{ - if (structDecl->syntaxKind != StructDeclaration) - { - fprintf( - stderr, - "wraith: Attempted to call GetIdFromStruct on node with kind: " - "%s.\n", - SyntaxKindString(structDecl->syntaxKind)); - return NULL; - } - - return structDecl->structDeclaration.identifier; -} - -Node *GetIdFromFunction(Node *funcDecl) -{ - if (funcDecl->syntaxKind != FunctionDeclaration) - { - fprintf( - stderr, - "wraith: Attempted to call GetIdFromFunction on node with kind: " - "%s.\n", - SyntaxKindString(funcDecl->syntaxKind)); - return NULL; - } - - Node *sig = funcDecl->functionDeclaration.functionSignature; - return sig->functionSignature.identifier; -} - -Node *GetIdFromDeclaration(Node *decl) -{ - if (decl->syntaxKind != Declaration) - { - fprintf( - stderr, - "wraith: Attempted to call GetIdFromDeclaration on node with kind: " - "%s.\n", - SyntaxKindString(decl->syntaxKind)); - } - - return decl->declaration.identifier; -} - -bool AssignmentHasDeclaration(Node *assign) -{ - return ( - assign->syntaxKind == Assignment && - assign->assignmentStatement.left->syntaxKind == Declaration); -} - -Node *GetIdFromAssignment(Node *assign) -{ - if (assign->syntaxKind != Assignment) - { - fprintf( - stderr, - "wraith: Attempted to call GetIdFromAssignment on node with kind: " - "%s.\n", - SyntaxKindString(assign->syntaxKind)); - } - - if (AssignmentHasDeclaration(assign)) - { - return GetIdFromDeclaration(assign->assignmentStatement.left); - } - - return NULL; -} - -bool NodeMayHaveId(Node *node) -{ - switch (node->syntaxKind) - { - case StructDeclaration: - case FunctionDeclaration: - case Declaration: - case Assignment: - return true; - default: - return false; - } -} - -Node *TryGetId(Node *node) -{ - switch (node->syntaxKind) - { - case Assignment: - return GetIdFromAssignment(node); - case Declaration: - return GetIdFromDeclaration(node); - case FunctionDeclaration: - return GetIdFromFunction(node); - case StructDeclaration: - return GetIdFromStruct(node); - default: - return NULL; - } -} - -Node *LookupFunctionArgId(Node *funcDecl, char *target) -{ - Node *args = funcDecl->functionDeclaration.functionSignature - ->functionSignature.arguments; - - uint32_t i; - for (i = 0; i < args->functionArgumentSequence.count; i += 1) - { - Node *arg = args->functionArgumentSequence.sequence[i]; - if (arg->syntaxKind != Declaration) - { - fprintf( - stderr, - "wraith: Encountered %s node in function signature args " - "list.\n", - SyntaxKindString(arg->syntaxKind)); - continue; - } - - Node *argId = GetIdFromDeclaration(arg); - if (argId != NULL && strcmp(target, argId->identifier.name) == 0) - { - return argId; - } - } - - return NULL; -} - -Node *LookupStructInternalId(Node *structDecl, char *target) -{ - Node *decls = structDecl->structDeclaration.declarationSequence; - - uint32_t i; - for (i = 0; i < decls->declarationSequence.count; i += 1) - { - Node *match = TryGetId(decls->declarationSequence.sequence[i]); - if (match != NULL && strcmp(target, match->identifier.name) == 0) - return match; - } - - return NULL; -} - -Node *InspectNode(Node *node, char *target) -{ - /* If this node may have an identifier declaration inside it, attempt to - * look up the identifier - * node itself, returning it if it matches the given target name. */ - if (NodeMayHaveId(node)) - { - Node *candidateId = TryGetId(node); - if (candidateId != NULL && - strcmp(target, candidateId->identifier.name) == 0) - { - return candidateId; - } - } - - /* If the candidate node was not the one we wanted, but the node node is a - * function declaration, it's possible that the identifier we want is one of - * the function's parameters rather than the function's name itself. */ - if (node->syntaxKind == FunctionDeclaration) - { - Node *match = LookupFunctionArgId(node, target); - if (match != NULL) - return match; - } - - /* Likewise if the node node is a struct declaration, inspect the struct's - * internals - * to see if a top-level definition is the one we're looking for. */ - if (node->syntaxKind == StructDeclaration) - { - Node *match = LookupStructInternalId(node, target); - if (match != NULL) - return match; - } - - return NULL; -} - -Node *LookupIdNode(Node *current, Node *prev, char *target) -{ - if (current == NULL) - return NULL; - Node *match; - - /* First inspect the current node to see if it contains the target - * identifier. */ - match = InspectNode(current, target); - if (match != NULL) - return match; - - /* If this is the start of our search, we should not attempt to look at - * child nodes. Only looking up the AST is valid at this point. - * - * This has the notable side-effect that this function will return NULL if - * you attempt to look up a struct's internals starting from the node - * representing the struct itself. The same is true for functions. */ - if (prev == NULL) - { - return LookupIdNode(current->parent, current, target); - } - - uint32_t i; - uint32_t idxLimit; - switch (current->syntaxKind) - { - case DeclarationSequence: - for (i = 0; i < current->declarationSequence.count; i += 1) - { - Node *decl = current->declarationSequence.sequence[i]; - match = InspectNode(decl, target); - if (match != NULL) - return match; - /*Node *declId = TryGetId(decl); - if (declId != NULL && strcmp(target, declId->identifier.name) == 0) - return declId;*/ - } - break; - case StatementSequence: - idxLimit = current->statementSequence.count; - for (i = 0; i < current->statementSequence.count; i += 1) - { - if (current->statementSequence.sequence[i] == prev) - { - idxLimit = i; - break; - } - } - - for (i = 0; i < idxLimit; i += 1) - { - Node *stmt = current->statementSequence.sequence[i]; - if (stmt == prev) - continue; - - if (strcmp(target, "g") == 0) - { - printf("info: %s\n", SyntaxKindString(stmt->syntaxKind)); - } - - match = InspectNode(stmt, target); - if (match != NULL) - return match; - /*if (NodeMayHaveId(stmt)) - { - Node *candidateId = TryGetId(current); - if (candidateId != NULL && strcmp(target, - candidateId->identifier.name) == 0) return candidateId; - }*/ - } - break; - } - - return LookupIdNode(current->parent, current, target); -} - -void IdentifierPass(Node *node) -{ - if (node == NULL) - return; - - switch (node->syntaxKind) - { - case AllocExpression: - node->typeTag = MakeTypeTag(node); - break; - - case Declaration: - node->declaration.identifier->typeTag = MakeTypeTag(node); - break; - - case FunctionDeclaration: - node->functionDeclaration.functionSignature->functionSignature - .identifier->typeTag = MakeTypeTag(node); - break; - - case StructDeclaration: - node->structDeclaration.identifier->typeTag = MakeTypeTag(node); - break; - - case GenericArgument: - node->genericArgument.identifier->typeTag = MakeTypeTag(node); - break; - - case Identifier: - { - if (node->typeTag != NULL) - return; - - char *name = node->identifier.name; - Node *declaration = LookupIdNode(node, NULL, name); - if (declaration == NULL) - { - /* FIXME: Express this case as an error with AST information. */ - fprintf( - stderr, - "wraith: Could not find definition of identifier %s.\n", - name); - TypeTag *tag = (TypeTag *)malloc(sizeof(TypeTag)); - tag->type = Unknown; - node->typeTag = tag; - } - else - { - node->typeTag = declaration->typeTag; - } - break; - } - } - - Recurse(node, *IdentifierPass); -} \ No newline at end of file diff --git a/src/ast.h b/src/ast.h index 179d0e6..3d36cf6 100644 --- a/src/ast.h +++ b/src/ast.h @@ -1,7 +1,6 @@ #ifndef WRAITH_AST_H #define WRAITH_AST_H -#include "identcheck.h" #include /* -Wpedantic nameless union/struct silencing */ @@ -300,7 +299,6 @@ struct Node } unaryExpression; }; TypeTag *typeTag; - IdNode *idLink; }; const char *SyntaxKindString(SyntaxKind syntaxKind); @@ -381,5 +379,4 @@ char *TypeTagToString(TypeTag *tag); Node *LookupIdNode(Node *current, Node *prev, char *target); -void IdentifierPass(Node *node); #endif /* WRAITH_AST_H */ diff --git a/src/identcheck.c b/src/identcheck.c deleted file mode 100644 index 39498b0..0000000 --- a/src/identcheck.c +++ /dev/null @@ -1,507 +0,0 @@ -#include -#include -#include -#include -#include - -#include "ast.h" -#include "identcheck.h" - -IdNode *MakeIdNode(NodeType type, char *name, IdNode *parent) -{ - IdNode *node = (IdNode *)malloc(sizeof(IdNode)); - node->type = type; - node->name = strdup(name); - node->parent = parent; - node->childCount = 0; - node->childCapacity = 0; - node->children = NULL; - node->typeTag = NULL; - return node; -} - -void AddChildToNode(IdNode *node, IdNode *child) -{ - if (child == NULL) - return; - - if (node->children == NULL) - { - node->childCapacity = 2; - node->children = - (IdNode **)malloc(sizeof(IdNode *) * node->childCapacity); - } - else if (node->childCount == node->childCapacity) - { - node->childCapacity *= 2; - node->children = (IdNode **)realloc( - node->children, - sizeof(IdNode *) * node->childCapacity); - } - - node->children[node->childCount] = child; - node->childCount += 1; -} - -IdNode *MakeIdTree(Node *astNode, IdNode *parent) -{ - uint32_t i; - IdNode *mainNode; - switch (astNode->syntaxKind) - { - case AccessExpression: - AddChildToNode( - parent, - MakeIdTree(astNode->accessExpression.accessee, parent)); - AddChildToNode( - parent, - MakeIdTree(astNode->accessExpression.accessor, parent)); - return NULL; - - case AllocExpression: - astNode->typeTag = MakeTypeTag(astNode); - return NULL; - - case Assignment: - { - if (astNode->assignmentStatement.left->syntaxKind == Declaration) - { - return MakeIdTree(astNode->assignmentStatement.left, parent); - } - else - { - AddChildToNode( - parent, - MakeIdTree(astNode->assignmentStatement.left, parent)); - AddChildToNode( - parent, - MakeIdTree(astNode->assignmentStatement.right, parent)); - return NULL; - } - } - - case BinaryExpression: - AddChildToNode( - parent, - MakeIdTree(astNode->binaryExpression.left, parent)); - AddChildToNode( - parent, - MakeIdTree(astNode->binaryExpression.right, parent)); - return NULL; - - case Declaration: - { - Node *idNode = astNode->declaration.identifier; - mainNode = MakeIdNode(Variable, idNode->identifier.name, parent); - mainNode->typeTag = MakeTypeTag(astNode); - idNode->typeTag = mainNode->typeTag; - break; - } - - case DeclarationSequence: - { - mainNode = MakeIdNode(UnorderedScope, "", parent); - for (i = 0; i < astNode->declarationSequence.count; i++) - { - AddChildToNode( - mainNode, - MakeIdTree(astNode->declarationSequence.sequence[i], mainNode)); - } - break; - } - - case ForLoop: - { - Node *loopDecl = astNode->forLoop.declaration; - Node *loopBody = astNode->forLoop.statementSequence; - mainNode = MakeIdNode(OrderedScope, "for-loop", parent); - AddChildToNode(mainNode, MakeIdTree(loopDecl, mainNode)); - AddChildToNode(mainNode, MakeIdTree(loopBody, mainNode)); - break; - } - - case FunctionArgumentSequence: - for (i = 0; i < astNode->functionArgumentSequence.count; i++) - { - AddChildToNode( - parent, - MakeIdTree( - astNode->functionArgumentSequence.sequence[i], - parent)); - } - return NULL; - - case FunctionCallExpression: - AddChildToNode( - parent, - MakeIdTree(astNode->functionCallExpression.identifier, parent)); - AddChildToNode( - parent, - MakeIdTree( - astNode->functionCallExpression.argumentSequence, - parent)); - return NULL; - - case FunctionDeclaration: - { - Node *sigNode = astNode->functionDeclaration.functionSignature; - Node *idNode = sigNode->functionSignature.identifier; - char *funcName = idNode->identifier.name; - mainNode = MakeIdNode(Function, funcName, parent); - mainNode->typeTag = MakeTypeTag(astNode); - idNode->typeTag = mainNode->typeTag; - MakeIdTree(sigNode->functionSignature.genericArguments, mainNode); - MakeIdTree(sigNode->functionSignature.arguments, mainNode); - MakeIdTree(astNode->functionDeclaration.functionBody, mainNode); - break; - } - - case FunctionSignatureArguments: - { - for (i = 0; i < astNode->functionSignatureArguments.count; i++) - { - Node *argNode = astNode->functionSignatureArguments.sequence[i]; - AddChildToNode(parent, MakeIdTree(argNode, parent)); - } - return NULL; - } - - case GenericArgument: - { - char *name = astNode->genericArgument.identifier->identifier.name; - mainNode = MakeIdNode(GenericType, name, parent); - break; - } - - case GenericArguments: - { - for (i = 0; i < astNode->genericArguments.count; i += 1) - { - Node *argNode = astNode->genericArguments.arguments[i]; - AddChildToNode(parent, MakeIdTree(argNode, parent)); - } - return NULL; - } - - case Identifier: - { - char *name = astNode->identifier.name; - mainNode = MakeIdNode(Placeholder, name, parent); - Node *lookupNode = LookupIdNode(astNode, NULL, name); - if (lookupNode == NULL) - { - fprintf(stderr, "wraith: Could not find IdNode for id %s\n", name); - TypeTag *tag = (TypeTag *)malloc(sizeof(TypeTag)); - tag->type = Unknown; - astNode->typeTag = tag; - } - else - { - astNode->typeTag = lookupNode->typeTag; - } - break; - } - - case IfStatement: - { - Node *clause = astNode->ifStatement.expression; - Node *stmtSeq = astNode->ifStatement.statementSequence; - mainNode = MakeIdNode(OrderedScope, "if", parent); - MakeIdTree(clause, mainNode); - MakeIdTree(stmtSeq, mainNode); - break; - } - - case IfElseStatement: - { - Node *ifNode = astNode->ifElseStatement.ifStatement; - Node *elseStmts = astNode->ifElseStatement.elseStatement; - mainNode = MakeIdNode(OrderedScope, "if-else", parent); - IdNode *ifBranch = MakeIdTree(ifNode, mainNode); - AddChildToNode(mainNode, ifBranch); - IdNode *elseScope = MakeIdNode(OrderedScope, "else", mainNode); - MakeIdTree(elseStmts, elseScope); - AddChildToNode(mainNode, elseScope); - break; - } - - case ReferenceTypeNode: - AddChildToNode(parent, MakeIdTree(astNode->referenceType.type, parent)); - return NULL; - - case Return: - AddChildToNode( - parent, - MakeIdTree(astNode->returnStatement.expression, parent)); - return NULL; - - case StatementSequence: - { - for (i = 0; i < astNode->statementSequence.count; i++) - { - Node *argNode = astNode->statementSequence.sequence[i]; - AddChildToNode(parent, MakeIdTree(argNode, parent)); - } - return NULL; - } - - case StructDeclaration: - { - Node *idNode = astNode->structDeclaration.identifier; - Node *declsNode = astNode->structDeclaration.declarationSequence; - mainNode = MakeIdNode(Struct, idNode->identifier.name, parent); - mainNode->typeTag = MakeTypeTag(astNode); - for (i = 0; i < declsNode->declarationSequence.count; i++) - { - Node *decl = declsNode->declarationSequence.sequence[i]; - AddChildToNode(mainNode, MakeIdTree(decl, mainNode)); - } - break; - } - - case Type: - AddChildToNode(parent, MakeIdTree(astNode->type.typeNode, parent)); - return NULL; - - case UnaryExpression: - AddChildToNode( - parent, - MakeIdTree(astNode->unaryExpression.child, parent)); - return NULL; - - case Comment: - case CustomTypeNode: - case FunctionModifiers: - case FunctionSignature: - case Number: - case PrimitiveTypeNode: - case ReturnVoid: - case StaticModifier: - case StringLiteral: - return NULL; - } - - astNode->idLink = mainNode; - return mainNode; -} - -void PrintIdNode(IdNode *node) -{ - if (node == NULL) - { - fprintf( - stderr, - "wraith: Attempted to call PrintIdNode with null value.\n"); - return; - } - - switch (node->type) - { - case Placeholder: - printf("Placeholder (%s)\n", node->name); - break; - case OrderedScope: - printf("OrderedScope (%s)\n", node->name); - break; - case UnorderedScope: - printf("UnorderedScope (%s)\n", node->name); - break; - case Struct: - printf("%s : %s\n", node->name, TypeTagToString(node->typeTag)); - break; - case Function: - printf( - "%s : Function<%s>\n", - node->name, - TypeTagToString(node->typeTag)); - break; - case Variable: - printf("%s : %s\n", node->name, TypeTagToString(node->typeTag)); - break; - case GenericType: - printf("Generic type: %s\n", node->name); - break; - case Alloc: - printf("Alloc: %s\n", TypeTagToString(node->typeTag)); - break; - } -} - -void PrintIdTree(IdNode *tree, uint32_t tabCount) -{ - if (tree == NULL) - { - fprintf( - stderr, - "wraith: Attempted to call PrintIdTree on a null value.\n"); - return; - } - - uint32_t i; - for (i = 0; i < tabCount; i++) - { - printf("| "); - } - - PrintIdNode(tree); - - for (i = 0; i < tree->childCount; i++) - { - PrintIdTree(tree->children[i], tabCount + 1); - } -} - -int PrintAncestors(IdNode *node) -{ - if (node == NULL) - return -1; - - int i; - int indent = 1; - indent += PrintAncestors(node->parent); - for (i = 0; i < indent; i++) - { - printf(" "); - } - PrintIdNode(node); - return indent; -} - -IdNode *LookdownId(IdNode *root, NodeType targetType, char *targetName) -{ - if (root == NULL) - { - fprintf( - stderr, - "wraith: Attempted to call LookdownId on a null value.\n"); - return NULL; - } - - IdNode *result = NULL; - IdNode **frontier = (IdNode **)malloc(sizeof(IdNode *)); - frontier[0] = root; - uint32_t frontierCount = 1; - - while (frontierCount > 0) - { - IdNode *current = frontier[0]; - - if (current->type == targetType && - strcmp(current->name, targetName) == 0) - { - result = current; - break; - } - - uint32_t i; - for (i = 1; i < frontierCount; i++) - { - frontier[i - 1] = frontier[i]; - } - size_t newSize = frontierCount + current->childCount - 1; - if (frontierCount != newSize) - { - frontier = (IdNode **)realloc(frontier, sizeof(IdNode *) * newSize); - } - for (i = 0; i < current->childCount; i++) - { - frontier[frontierCount + i - 1] = current->children[i]; - } - frontierCount = newSize; - } - - free(frontier); - return result; -} - -bool ScopeHasOrdering(IdNode *node) -{ - switch (node->type) - { - case OrderedScope: - case Function: - case Variable: /* this is only technically true */ - return true; - default: - return false; - } -} - -IdNode *LookupId(IdNode *node, IdNode *prev, char *target) -{ - if (node == NULL) - { - return NULL; - } - - if (strcmp(node->name, target) == 0 && node->type != Placeholder) - { - return node; - } - - /* If this is the start of our search, we should not attempt to look at - * child nodes. Only looking up the scope tree is valid at this point. - * - * This has the notable side-effect that this function will return NULL if - * you attempt to look up a struct's internals starting from the node - * representing the struct itself. This is because an IdNode corresponds to - * the location *where an identifier is first declared.* Thus, an identifier - * has no knowledge of identifiers declared "inside" of it. - */ - if (prev == NULL) - { - return LookupId(node->parent, node, target); - } - - /* If the current node forms an ordered scope then we want to prevent - * ourselves from looking up identifiers declared after the scope we have - * just come from. - */ - uint32_t idxLimit; - if (ScopeHasOrdering(node)) - { - uint32_t i; - for (i = 0, idxLimit = 0; i < node->childCount; i++, idxLimit++) - { - if (node->children[i] == prev) - { - break; - } - } - } - else - { - idxLimit = node->childCount; - } - - uint32_t i; - for (i = 0; i < idxLimit; i++) - { - IdNode *child = node->children[i]; - if (child == prev || child->type == Placeholder) - { - /* Do not inspect the node we just came from or placeholders. */ - continue; - } - - if (strcmp(child->name, target) == 0) - { - return child; - } - - if (child->type == Struct) - { - uint32_t j; - for (j = 0; j < child->childCount; j++) - { - IdNode *grandchild = child->children[j]; - if (strcmp(grandchild->name, target) == 0) - { - return grandchild; - } - } - } - } - - return LookupId(node->parent, node, target); -} diff --git a/src/identcheck.h b/src/identcheck.h deleted file mode 100644 index 8b287dd..0000000 --- a/src/identcheck.h +++ /dev/null @@ -1,51 +0,0 @@ -/* Validates identifier usage in an AST. */ - -#ifndef WRAITH_IDENTCHECK_H -#define WRAITH_IDENTCHECK_H - -#include - -#include "ast.h" - -struct TypeTag; -struct Node; - -typedef enum NodeType -{ - Placeholder, - UnorderedScope, - OrderedScope, - Struct, - Function, - Variable, - GenericType, - Alloc -} NodeType; - -typedef struct IdNode -{ - NodeType type; - char *name; - struct TypeTag *typeTag; - struct IdNode *parent; - struct IdNode **children; - uint32_t childCount; - uint32_t childCapacity; -} IdNode; - -typedef struct IdStatus -{ - enum StatusCode - { - Valid, - } StatusCode; -} IdStatus; - -IdNode *MakeIdTree(struct Node *astNode, IdNode *parent); -void PrintIdNode(IdNode *node); -void PrintIdTree(IdNode *tree, uint32_t tabCount); -int PrintAncestors(IdNode *node); -IdNode *LookdownId(IdNode *root, NodeType targetType, char *targetName); -IdNode *LookupId(IdNode *node, IdNode *prev, char *target); - -#endif /* WRAITH_IDENTCHECK_H */ diff --git a/src/main.c b/src/main.c index 1b7c70b..f3f8d36 100644 --- a/src/main.c +++ b/src/main.c @@ -2,9 +2,8 @@ #include #include "codegen.h" -#include "identcheck.h" #include "parser.h" -#include "typeutils.h" +#include "validation.h" int main(int argc, char *argv[]) { @@ -87,8 +86,11 @@ int main(int argc, char *argv[]) else { LinkParentPointers(rootNode, NULL); - IdentifierPass(rootNode); - /*ConvertASTCustomsToGenerics(rootNode);*/ + /* FIXME: ValidateIdentifiers should return some sort of + error status object. */ + ValidateIdentifiers(rootNode); + TagIdentifierTypes(rootNode); + ConvertCustomsToGenerics(rootNode); PrintNode(rootNode, 0); printf("Beginning codegen.\n"); diff --git a/src/typeutils.c b/src/typeutils.c deleted file mode 100644 index 4ebddea..0000000 --- a/src/typeutils.c +++ /dev/null @@ -1,82 +0,0 @@ -#include "typeutils.h" - -#include -#include -#include - -void ConvertIdCustomsToGenerics(IdNode *node) { - uint32_t i; - switch(node->type) - { - case UnorderedScope: - case OrderedScope: - case Struct: - /* FIXME: This case will need to be modified to handle type parameters over structs. */ - for (i = 0; i < node->childCount; i += 1) { - ConvertIdCustomsToGenerics(node->children[i]); - } - return; - - case Variable: { - TypeTag *varType = node->typeTag; - if (varType->type == Custom) { - IdNode *x = LookupId(node->parent, node, varType->value.customType); - if (x != NULL && x->type == GenericType) { - varType->type = Generic; - } - } - return; - } - - case Function: { - TypeTag *funcType = node->typeTag; - if (funcType->type == Custom) { - /* For functions we have to handle the type lookup manually since the generic type - * identifiers are declared as children of the function's IdNode. */ - for (i = 0; i < node->childCount; i += 1) { - IdNode *child = node->children[i]; - if (child->type == GenericType && strcmp(child->name, funcType->value.customType) == 0) { - funcType->type = Generic; - } - } - } - - for (i = 0; i < node->childCount; i += 1) { - ConvertIdCustomsToGenerics(node->children[i]); - } - return; - } - } -} - -/* FIXME: This function will need to be modified to handle type parameters over structs. */ -void ConvertASTCustomsToGenerics(Node *node) { - switch (node->syntaxKind) - { - case Declaration: - { - Node *type = node->declaration.type->type.typeNode; - Node *id = node->declaration.identifier; - if (id->typeTag->type == Generic && type->syntaxKind == CustomTypeNode) { - free(node->declaration.type); - node->declaration.type = MakeGenericTypeNode(id->typeTag->value.genericType); - } - return; - } - - case FunctionSignature: - { - Node *id = node->functionSignature.identifier; - Node *type = node->functionSignature.type; - if (id->typeTag->type == Generic && type->syntaxKind == CustomTypeNode) { - free(node->functionSignature.type); - node->functionSignature.type = MakeGenericTypeNode(id->typeTag->value.genericType); - } - ConvertASTCustomsToGenerics(node->functionSignature.arguments); - return; - } - - default: - Recurse(node, *ConvertASTCustomsToGenerics); - } -} diff --git a/src/typeutils.h b/src/typeutils.h deleted file mode 100644 index 2e752e0..0000000 --- a/src/typeutils.h +++ /dev/null @@ -1,13 +0,0 @@ -/* Helper functions for working with types in the AST and ID-tree. */ - -#ifndef WRAITH_TYPEUTILS_H -#define WRAITH_TYPEUTILS_H - -#include "ast.h" -#include "identcheck.h" - -/* FIXME: These two functions will need to be modified to handle type parameters over structs. */ -void ConvertIdCustomsToGenerics(IdNode *node); -void ConvertASTCustomsToGenerics(Node *node); - -#endif /* WRAITH_TYPEUTILS_H */ diff --git a/src/validation.c b/src/validation.c new file mode 100644 index 0000000..e62c4dd --- /dev/null +++ b/src/validation.c @@ -0,0 +1,452 @@ +#include "validation.h" + +#include +#include +#include +#include + +Node *GetIdFromStruct(Node *structDecl) +{ + if (structDecl->syntaxKind != StructDeclaration) + { + fprintf( + stderr, + "wraith: Attempted to call GetIdFromStruct on node with kind: " + "%s.\n", + SyntaxKindString(structDecl->syntaxKind)); + return NULL; + } + + return structDecl->structDeclaration.identifier; +} + +Node *GetIdFromFunction(Node *funcDecl) +{ + if (funcDecl->syntaxKind != FunctionDeclaration) + { + fprintf( + stderr, + "wraith: Attempted to call GetIdFromFunction on node with kind: " + "%s.\n", + SyntaxKindString(funcDecl->syntaxKind)); + return NULL; + } + + Node *sig = funcDecl->functionDeclaration.functionSignature; + return sig->functionSignature.identifier; +} + +Node *GetIdFromDeclaration(Node *decl) +{ + if (decl->syntaxKind != Declaration) + { + fprintf( + stderr, + "wraith: Attempted to call GetIdFromDeclaration on node with kind: " + "%s.\n", + SyntaxKindString(decl->syntaxKind)); + } + + return decl->declaration.identifier; +} + +bool AssignmentHasDeclaration(Node *assign) +{ + return ( + assign->syntaxKind == Assignment && + assign->assignmentStatement.left->syntaxKind == Declaration); +} + +Node *GetIdFromAssignment(Node *assign) +{ + if (assign->syntaxKind != Assignment) + { + fprintf( + stderr, + "wraith: Attempted to call GetIdFromAssignment on node with kind: " + "%s.\n", + SyntaxKindString(assign->syntaxKind)); + } + + if (AssignmentHasDeclaration(assign)) + { + return GetIdFromDeclaration(assign->assignmentStatement.left); + } + + return NULL; +} + +bool NodeMayHaveId(Node *node) +{ + switch (node->syntaxKind) + { + case StructDeclaration: + case FunctionDeclaration: + case Declaration: + case Assignment: + return true; + default: + return false; + } +} + +Node *TryGetId(Node *node) +{ + switch (node->syntaxKind) + { + case Assignment: + return GetIdFromAssignment(node); + case Declaration: + return GetIdFromDeclaration(node); + case FunctionDeclaration: + return GetIdFromFunction(node); + case StructDeclaration: + return GetIdFromStruct(node); + default: + return NULL; + } +} + +Node *LookupFunctionArgId(Node *funcDecl, char *target) +{ + Node *args = funcDecl->functionDeclaration.functionSignature + ->functionSignature.arguments; + + uint32_t i; + for (i = 0; i < args->functionArgumentSequence.count; i += 1) + { + Node *arg = args->functionArgumentSequence.sequence[i]; + if (arg->syntaxKind != Declaration) + { + fprintf( + stderr, + "wraith: Encountered %s node in function signature args " + "list.\n", + SyntaxKindString(arg->syntaxKind)); + continue; + } + + Node *argId = GetIdFromDeclaration(arg); + if (argId != NULL && strcmp(target, argId->identifier.name) == 0) + return argId; + } + + return NULL; +} + +Node *LookupStructInternalId(Node *structDecl, char *target) +{ + Node *decls = structDecl->structDeclaration.declarationSequence; + + uint32_t i; + for (i = 0; i < decls->declarationSequence.count; i += 1) + { + Node *match = TryGetId(decls->declarationSequence.sequence[i]); + if (match != NULL && strcmp(target, match->identifier.name) == 0) + return match; + } + + return NULL; +} + +Node *InspectNode(Node *node, char *target) +{ + /* If this node may have an identifier declaration inside it, attempt to + * look up the identifier + * node itself, returning it if it matches the given target name. */ + if (NodeMayHaveId(node)) + { + Node *candidateId = TryGetId(node); + if (candidateId != NULL && + strcmp(target, candidateId->identifier.name) == 0) + return candidateId; + } + + /* If the candidate node was not the one we wanted, but the node node is a + * function declaration, it's possible that the identifier we want is one of + * the function's parameters rather than the function's name itself. */ + if (node->syntaxKind == FunctionDeclaration) + { + Node *match = LookupFunctionArgId(node, target); + if (match != NULL) + return match; + } + + /* Likewise if the node node is a struct declaration, inspect the struct's + * internals + * to see if a top-level definition is the one we're looking for. */ + if (node->syntaxKind == StructDeclaration) + { + Node *match = LookupStructInternalId(node, target); + if (match != NULL) + return match; + } + + return NULL; +} + +/* FIXME: Handle staged lookups for AccessExpressions. */ +/* FIXME: Similar to above, disallow inspection of struct internals outside of + * AccessExpressions. */ +Node *LookupId(Node *current, Node *prev, char *target) +{ + if (current == NULL) + return NULL; + + Node *match; + + /* First inspect the current node to see if it contains the target + * identifier. */ + match = InspectNode(current, target); + if (match != NULL) + return match; + + /* If this is the start of our search, we should not attempt to look at + * child nodes. Only looking up the AST is valid at this point. + * + * This has the notable side-effect that this function will return NULL if + * you attempt to look up a struct's internals starting from the node + * representing the struct itself. The same is true for functions. */ + if (prev == NULL) + return LookupId(current->parent, current, target); + + uint32_t i; + uint32_t idxLimit; + switch (current->syntaxKind) + { + case DeclarationSequence: + for (i = 0; i < current->declarationSequence.count; i += 1) + { + Node *decl = current->declarationSequence.sequence[i]; + match = InspectNode(decl, target); + if (match != NULL) + return match; + } + break; + case StatementSequence: + idxLimit = current->statementSequence.count; + for (i = 0; i < current->statementSequence.count; i += 1) + { + if (current->statementSequence.sequence[i] == prev) + { + idxLimit = i; + break; + } + } + + for (i = 0; i < idxLimit; i += 1) + { + Node *stmt = current->statementSequence.sequence[i]; + if (stmt == prev) + break; + + match = InspectNode(stmt, target); + if (match != NULL) + return match; + } + break; + } + + return LookupId(current->parent, current, target); +} + +/* FIXME: This function should be extended to handle multi-stage ID lookups for + * AccessExpression nodes. */ +/* FIXME: Make this function return an error status object of some kind. + * A non-OK status should halt compilation. */ +void ValidateIdentifiers(Node *node) +{ + if (node == NULL) + return; + + /* Skip over generic arguments. They contain Identifiers but are not + * actually identifiers, they declare types. */ + if (node->syntaxKind == GenericArguments) + return; + + if (node->syntaxKind != Identifier) + { + Recurse(node, *ValidateIdentifiers); + return; + } + + char *name = node->identifier.name; + Node *decl = LookupId(node, NULL, name); + if (decl == NULL) + { + /* FIXME: Express this case as an error with AST information, see the + * FIXME comment above. */ + fprintf( + stderr, + "wraith: Could not find definition of identifier %s.\n", + name); + } +} + +/* FIXME: This function should be extended to handle multi-stage ID lookups for + * AccessExpression nodes. */ +void TagIdentifierTypes(Node *node) +{ + if (node == NULL) + return; + + switch (node->syntaxKind) + { + case AllocExpression: + node->typeTag = MakeTypeTag(node); + break; + + case Declaration: + node->declaration.identifier->typeTag = MakeTypeTag(node); + break; + + case FunctionDeclaration: + node->functionDeclaration.functionSignature->functionSignature + .identifier->typeTag = MakeTypeTag(node); + break; + + case StructDeclaration: + node->structDeclaration.identifier->typeTag = MakeTypeTag(node); + break; + + case GenericArgument: + node->genericArgument.identifier->typeTag = MakeTypeTag(node); + break; + + case Identifier: + { + if (node->typeTag != NULL) + return; + + char *name = node->identifier.name; + Node *declaration = LookupId(node, NULL, name); + /* FIXME: Remove this case once ValidateIdentifiers returns error status + * info and halts compilation. See ValidateIdentifiers FIXME. */ + if (declaration == NULL) + { + TypeTag *tag = (TypeTag *)malloc(sizeof(TypeTag)); + tag->type = Unknown; + node->typeTag = tag; + } + else + { + node->typeTag = declaration->typeTag; + } + break; + } + } + + Recurse(node, *TagIdentifierTypes); +} + +Node *LookupType(Node *current, char *target) +{ + if (current == NULL) + return NULL; + + switch (current->syntaxKind) + { + /* If we've encountered a function declaration, check to see if it's generic + * and, if so, if one of its type parameters is the target. */ + case FunctionDeclaration: + { + Node *typeArgs = current->functionDeclaration.functionSignature + ->functionSignature.genericArguments; + uint32_t i; + for (i = 0; i < typeArgs->genericArguments.count; i += 1) + { + Node *arg = typeArgs->genericArguments.arguments[i]; + Node *argId = arg->genericArgument.identifier; + char *argName = argId->identifier.name; + /* note: return the GenericArgument, not the Identifier, so that + * the caller can differentiate between generics and customs. */ + if (strcmp(target, argName) == 0) + return arg; + } + + return LookupType(current->parent, target); + } + + case StructDeclaration: + { + Node *structId = GetIdFromStruct(current); + if (strcmp(target, structId->identifier.name) == 0) + return structId; + + return LookupType(current->parent, target); + } + + /* If we encounter a declaration sequence, search each of its children for + * struct definitions in case one of them is the target. */ + case DeclarationSequence: + { + uint32_t i; + for (i = 0; i < current->declarationSequence.count; i += 1) + { + Node *decl = current->declarationSequence.sequence[i]; + if (decl->syntaxKind == StructDeclaration) + { + Node *structId = GetIdFromStruct(decl); + if (strcmp(target, structId->identifier.name) == 0) + return structId; + } + } + + return LookupType(current->parent, target); + } + + default: + return LookupType(current->parent, target); + } +} + +/* FIXME: This function should be modified to handle type parameters over + * structs. */ +void ConvertCustomsToGenerics(Node *node) +{ + if (node == NULL) + return; + + switch (node->syntaxKind) + { + case Declaration: + { + Node *id = node->declaration.identifier; + Node *type = node->declaration.type->type.typeNode; + if (type->syntaxKind == CustomTypeNode) + { + char *target = id->typeTag->value.customType; + Node *typeLookup = LookupType(node, target); + if (typeLookup != NULL && typeLookup->syntaxKind == GenericArgument) + { + id->typeTag->type = Generic; + free(node->declaration.type); + node->declaration.type = + MakeGenericTypeNode(id->typeTag->value.genericType); + } + } + break; + } + + case FunctionSignature: + { + Node *id = node->functionSignature.identifier; + Node *type = node->functionSignature.type->type.typeNode; + if (type->syntaxKind == CustomTypeNode) + { + char *target = id->typeTag->value.customType; + Node *typeLookup = LookupType(node, target); + if (typeLookup != NULL && typeLookup->syntaxKind == GenericArgument) + { + id->typeTag->type = Generic; + free(node->functionSignature.type); + node->functionSignature.type = + MakeGenericTypeNode(id->typeTag->value.genericType); + } + } + break; + } + } + + Recurse(node, *ConvertCustomsToGenerics); +} diff --git a/src/validation.h b/src/validation.h new file mode 100644 index 0000000..50c5432 --- /dev/null +++ b/src/validation.h @@ -0,0 +1,10 @@ +#ifndef WRAITH_VALIDATION_H +#define WRAITH_VALIDATION_H + +#include "ast.h" + +void ValidateIdentifiers(Node *node); +void TagIdentifierTypes(Node *node); +void ConvertCustomsToGenerics(Node *node); + +#endif /* WRAITH_VALIDATION_H */ -- 2.25.1