From 6ec5479db18efb738e6a6716c798028e5aa670a2 Mon Sep 17 00:00:00 2001 From: venko Date: Thu, 6 May 2021 17:15:17 -0700 Subject: [PATCH 01/15] Moves strdup function to utility file --- src/ast.c | 15 +-------------- src/ast.h | 1 - src/util.c | 16 ++++++++++++++++ src/util.h | 6 ++++++ 4 files changed, 23 insertions(+), 15 deletions(-) create mode 100644 src/util.c create mode 100644 src/util.h diff --git a/src/ast.c b/src/ast.c index 4f33a63..d08c224 100644 --- a/src/ast.c +++ b/src/ast.c @@ -2,21 +2,8 @@ #include #include -#include -char* strdup (const char* s) -{ - size_t slen = strlen(s); - char* result = malloc(slen + 1); - - if(result == NULL) - { - return NULL; - } - - memcpy(result, s, slen+1); - return result; -} +#include "util.h" const char* SyntaxKindString(SyntaxKind syntaxKind) { diff --git a/src/ast.h b/src/ast.h index 8e49ace..5c04d76 100644 --- a/src/ast.h +++ b/src/ast.h @@ -89,7 +89,6 @@ typedef struct Node PrimitiveType primitiveType; } Node; -char* strdup (const char* s); const char* SyntaxKindString(SyntaxKind syntaxKind); uint8_t IsPrimitiveType(Node *typeNode); diff --git a/src/util.c b/src/util.c new file mode 100644 index 0000000..ae1654f --- /dev/null +++ b/src/util.c @@ -0,0 +1,16 @@ +#include "util.h" + +#include + +char* strdup (const char* s) +{ + size_t slen = strlen(s); + char* result = malloc(slen + 1); + if(result == NULL) + { + return NULL; + } + + memcpy(result, s, slen+1); + return result; +} \ No newline at end of file diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000..2c305ec --- /dev/null +++ b/src/util.h @@ -0,0 +1,6 @@ +#ifndef WRAITH_UTIL_H +#define WRAITH_UTIL_H + +char* strdup (const char* s); + +#endif /* WRAITH_UTIL_H */ -- 2.25.1 From aeb36f9540a96e64a660e83f9e38f85b64cb5f18 Mon Sep 17 00:00:00 2001 From: venko Date: Thu, 6 May 2021 17:16:10 -0700 Subject: [PATCH 02/15] Adds type for validating identifiers --- CMakeLists.txt | 4 +- src/identcheck.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++ src/identcheck.h | 36 +++++++++++++ 3 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 src/identcheck.c create mode 100644 src/identcheck.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 56d5ca6..a3cbf9e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package(LLVM) include_directories(${CMAKE_SOURCE_DIR}) -BISON_TARGET(Parser generators/wraith.y ${CMAKE_CURRENT_BINARY_DIR}/y.tab.c COMPILE_FLAGS "-d -v -t -Wcounterexamples") +BISON_TARGET(Parser generators/wraith.y ${CMAKE_CURRENT_BINARY_DIR}/y.tab.c COMPILE_FLAGS "-d -v -t") FLEX_TARGET(Scanner generators/wraith.lex ${CMAKE_CURRENT_BINARY_DIR}/lex.yy.c) ADD_FLEX_BISON_DEPENDENCY(Scanner Parser) @@ -41,9 +41,11 @@ add_executable( # Source src/ast.h src/codegen.h + src/identcheck.h src/parser.h src/ast.c src/codegen.c + src/identcheck.c src/parser.c src/main.c # Generated code diff --git a/src/identcheck.c b/src/identcheck.c new file mode 100644 index 0000000..66b964e --- /dev/null +++ b/src/identcheck.c @@ -0,0 +1,130 @@ +#include +#include +#include +#include + +#include "ast.h" +#include "identcheck.h" + +IdNode* MakeIdNode(NodeType type, char *name) { + IdNode *node = (IdNode*)malloc(sizeof(IdNode)); + node->type = type; + node->name = strdup(name); + node->childCount = 0; + node->childCapacity = 0; + node->children = 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 = realloc(node->children, sizeof(IdNode*) * node->childCapacity); + } + + node->children[node->childCount] = child; + node->childCount += 1; +} + +IdNode* FindId(IdNode *root, NodeType targetType, char *targetName) { + 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)) { + result = current; + break; + } + + IdNode **temp = + (IdNode**)malloc(sizeof(IdNode*) * (frontierCount - 1 + current->childCount)); + uint32_t i; + for (i = 1; i < frontierCount; i++) { + temp[i - 1] = frontier[i]; + } + uint32_t offset = i; + for (i = 0; i < current->childCount; i++) { + temp[offset + i] = current->children[i]; + } + frontier = temp; + frontierCount += current->childCount - 1; + } + + free(frontier); + return result; +} + +IdNode* MakeIdTree(Node *astNode) { + switch (astNode->syntaxKind) { + case Declaration: + return MakeIdNode(Variable, astNode->children[1]->value.string); + + case DeclarationSequence: { + IdNode *declSeqNode = MakeIdNode(LexicalScope, ""); + uint32_t i; + for (i = 0; i < astNode->childCount; i++) { + AddChildToNode(declSeqNode, MakeIdTree(astNode->children[i])); + } + return declSeqNode; + } + + case StructDeclaration: { + Node *idNode = astNode->children[0]; + Node *declsNode = astNode->children[1]; + IdNode *structNode = MakeIdNode(Struct, idNode->value.string); + uint32_t i; + for (i = 0; i < declsNode->childCount; i++) { + AddChildToNode(structNode, MakeIdTree(declsNode->children[i])); + } + return structNode; + } + + case FunctionDeclaration: { + Node *sigNode = astNode->children[0]; + Node *funcNameNode = sigNode->children[0]; + Node *funcArgsNode = sigNode->children[2]; + + Node *bodyStatementsNode = astNode->children[1]; + + IdNode *funcNode = MakeIdNode(Function, funcNameNode->value.string); + uint32_t i; + for (i = 0; i < funcArgsNode->childCount; i++) { + AddChildToNode(funcNode, MakeIdTree(funcArgsNode->children[i])); + } + for (i = 0; i < bodyStatementsNode->childCount; i++) { + AddChildToNode(funcNode, MakeIdTree(bodyStatementsNode->children[i])); + } + return funcNode; + } + + default: + return NULL; + } +} + +void PrintIdTree(IdNode *tree, uint32_t tabCount) { + uint32_t i; + for (i = 0; i < tabCount; i++) { + printf("| "); + } + + switch(tree->type) { + case LexicalScope: printf("Scope\n"); break; + case Struct: printf("%s : Struct\n", tree->name); break; + case Function: printf("%s : Function\n", tree->name); break; + case Variable: printf("%s : Variable\n", tree->name); break; + } + + for (i = 0; i < tree->childCount; i++) { + PrintIdTree(tree->children[i], tabCount + 1); + } +} diff --git a/src/identcheck.h b/src/identcheck.h new file mode 100644 index 0000000..395a73c --- /dev/null +++ b/src/identcheck.h @@ -0,0 +1,36 @@ +// Validates identifier usage in an AST. +#ifndef WRAITH_IDENTCHECK_H +#define WRAITH_IDENTCHECK_H + +#include + +#include "ast.h" + +typedef enum NodeType { + LexicalScope, + Struct, + Function, + Variable +} NodeType; + +typedef struct IdNode { + NodeType type; + char *name; + struct IdNode **children; + uint32_t childCount; + uint32_t childCapacity; +} IdNode; + +typedef struct IdStatus { + enum StatusCode { + Valid, + } StatusCode; +} IdStatus; + + +IdNode* MakeIdTree(Node *astNode); +void PrintIdTree(IdNode *tree, uint32_t tabCount); + +//IdStatus CheckIds(Node *root); + +#endif /* WRAITH_IDENTCHECK_H */ -- 2.25.1 From 27587d1fb0426b3835004ecb3a6abb8167cff131 Mon Sep 17 00:00:00 2001 From: venko Date: Thu, 6 May 2021 19:53:28 -0700 Subject: [PATCH 03/15] Implements identifier trees for for-loops and conditional branching --- iftest.w | 27 ++++++++++++++++++++ src/ast.c | 2 ++ src/identcheck.c | 65 +++++++++++++++++++++++++++++++++++++----------- src/main.c | 2 ++ src/util.h | 2 ++ 5 files changed, 84 insertions(+), 14 deletions(-) create mode 100644 iftest.w diff --git a/iftest.w b/iftest.w new file mode 100644 index 0000000..90d5d11 --- /dev/null +++ b/iftest.w @@ -0,0 +1,27 @@ +struct Program { // Scope () + static Main(): int { // | Program : Struct + myInt: int = 54; // | | Main : Function + if (myInt < 0) { // | | | myInt : Variable + signTag: int = 0 - 1; // | | | Scope (if-else) + } else if (myInt == 0) { // | | | | Scope (if) + signTag: int = 0; // | | | | | signTag : Variable + } else { // | | | | Scope (else) + signTag: int = 1; // | | | | | Scope (if) + } // | | | | | | signTag : Variable + // | | | myBool : Variable + myBool: bool; // | | | Scope (if) + if (myBool) { // | | | | Scope (if) + if (myBool) { // | | | | | Scope (if) + if (myBool) { // | | | | | | Scope (if) + if (myBool) { // | | | | | | | Scope (if) + if (myBool) { // | | | | | | | | lol : Variable + lol: int = 69; + } + } + } + } + } + + return 0; + } +} diff --git a/src/ast.c b/src/ast.c index d08c224..4c39ba0 100644 --- a/src/ast.c +++ b/src/ast.c @@ -16,6 +16,8 @@ const char* SyntaxKindString(SyntaxKind syntaxKind) case Comment: return "Comment"; case CustomTypeNode: return "CustomTypeNode"; case Declaration: return "Declaration"; + case Expression: return "Expression"; + case ForLoop: return "ForLoop"; case DeclarationSequence: return "DeclarationSequence"; case FunctionArgumentSequence: return "FunctionArgumentSequence"; case FunctionCallExpression: return "FunctionCallExpression"; diff --git a/src/identcheck.c b/src/identcheck.c index 66b964e..772628b 100644 --- a/src/identcheck.c +++ b/src/identcheck.c @@ -64,24 +64,56 @@ IdNode* FindId(IdNode *root, NodeType targetType, char *targetName) { } IdNode* MakeIdTree(Node *astNode) { + uint32_t i; switch (astNode->syntaxKind) { + case Assignment: + return (astNode->children[0]->syntaxKind == Declaration) + ? MakeIdTree(astNode->children[0]) + : NULL; + + case IfStatement: { + Node *stmtSeq = astNode->children[1]; + IdNode *ifNode = MakeIdNode(LexicalScope, "if"); + for (i = 0; i < stmtSeq->childCount; i++) { + AddChildToNode(ifNode, MakeIdTree(stmtSeq->children[i])); + } + return ifNode; + } + + case IfElseStatement: { + Node *ifNode = astNode->children[0]; + Node *elseStmts = astNode->children[1]; + IdNode *ifElseNode = MakeIdNode(LexicalScope, "if-else"); + IdNode *ifBranch = MakeIdTree(ifNode); + IdNode *elseBranch = MakeIdNode(LexicalScope, "else"); + + AddChildToNode(ifElseNode, ifBranch); + AddChildToNode(ifElseNode, elseBranch); + for (i = 0; i < elseStmts->childCount; i++) { + AddChildToNode(elseBranch, MakeIdTree(elseStmts->children[i])); + } + + return ifElseNode; + } + + case ForLoop: { + Node *loopDecl = astNode->children[0]; + Node *loopBody = astNode->children[3]; + IdNode *loopNode = MakeIdNode(LexicalScope, "for-loop"); + AddChildToNode(loopNode, MakeIdTree(loopDecl)); + for (i = 0; i < loopBody->childCount; i++) { + AddChildToNode(loopNode, MakeIdTree(loopBody->children[i])); + } + return loopNode; + } + case Declaration: return MakeIdNode(Variable, astNode->children[1]->value.string); - case DeclarationSequence: { - IdNode *declSeqNode = MakeIdNode(LexicalScope, ""); - uint32_t i; - for (i = 0; i < astNode->childCount; i++) { - AddChildToNode(declSeqNode, MakeIdTree(astNode->children[i])); - } - return declSeqNode; - } - case StructDeclaration: { Node *idNode = astNode->children[0]; Node *declsNode = astNode->children[1]; IdNode *structNode = MakeIdNode(Struct, idNode->value.string); - uint32_t i; for (i = 0; i < declsNode->childCount; i++) { AddChildToNode(structNode, MakeIdTree(declsNode->children[i])); } @@ -92,11 +124,8 @@ IdNode* MakeIdTree(Node *astNode) { Node *sigNode = astNode->children[0]; Node *funcNameNode = sigNode->children[0]; Node *funcArgsNode = sigNode->children[2]; - Node *bodyStatementsNode = astNode->children[1]; - IdNode *funcNode = MakeIdNode(Function, funcNameNode->value.string); - uint32_t i; for (i = 0; i < funcArgsNode->childCount; i++) { AddChildToNode(funcNode, MakeIdTree(funcArgsNode->children[i])); } @@ -106,6 +135,14 @@ IdNode* MakeIdTree(Node *astNode) { return funcNode; } + case DeclarationSequence: { + IdNode *declSeqNode = MakeIdNode(LexicalScope, ""); + for (i = 0; i < astNode->childCount; i++) { + AddChildToNode(declSeqNode, MakeIdTree(astNode->children[i])); + } + return declSeqNode; + } + default: return NULL; } @@ -118,7 +155,7 @@ void PrintIdTree(IdNode *tree, uint32_t tabCount) { } switch(tree->type) { - case LexicalScope: printf("Scope\n"); break; + case LexicalScope: printf("Scope (%s)\n", tree->name); break; case Struct: printf("%s : Struct\n", tree->name); break; case Function: printf("%s : Function\n", tree->name); break; case Variable: printf("%s : Variable\n", tree->name); break; diff --git a/src/main.c b/src/main.c index 48a2301..10668c2 100644 --- a/src/main.c +++ b/src/main.c @@ -3,6 +3,7 @@ #include "parser.h" #include "codegen.h" +#include "identcheck.h" int main(int argc, char *argv[]) { @@ -64,6 +65,7 @@ int main(int argc, char *argv[]) } else { + PrintIdTree(MakeIdTree(rootNode), /*tabCount=*/0); exitCode = Codegen(rootNode, optimizationLevel); } } diff --git a/src/util.h b/src/util.h index 2c305ec..99ffaa7 100644 --- a/src/util.h +++ b/src/util.h @@ -1,6 +1,8 @@ #ifndef WRAITH_UTIL_H #define WRAITH_UTIL_H +#include + char* strdup (const char* s); #endif /* WRAITH_UTIL_H */ -- 2.25.1 From 8f86392cf33f31e04886475561532c0269075f6b Mon Sep 17 00:00:00 2001 From: venko Date: Fri, 7 May 2021 13:22:51 -0700 Subject: [PATCH 04/15] Makes id-tree doubly linked. Fixes id-tree search. --- iftest.w | 35 +++++++------ src/identcheck.c | 132 ++++++++++++++++++++++++++--------------------- src/identcheck.h | 5 +- src/main.c | 9 +++- 4 files changed, 104 insertions(+), 77 deletions(-) diff --git a/iftest.w b/iftest.w index 90d5d11..73df20c 100644 --- a/iftest.w +++ b/iftest.w @@ -1,20 +1,21 @@ -struct Program { // Scope () - static Main(): int { // | Program : Struct - myInt: int = 54; // | | Main : Function - if (myInt < 0) { // | | | myInt : Variable - signTag: int = 0 - 1; // | | | Scope (if-else) - } else if (myInt == 0) { // | | | | Scope (if) - signTag: int = 0; // | | | | | signTag : Variable - } else { // | | | | Scope (else) - signTag: int = 1; // | | | | | Scope (if) - } // | | | | | | signTag : Variable - // | | | myBool : Variable - myBool: bool; // | | | Scope (if) - if (myBool) { // | | | | Scope (if) - if (myBool) { // | | | | | Scope (if) - if (myBool) { // | | | | | | Scope (if) - if (myBool) { // | | | | | | | Scope (if) - if (myBool) { // | | | | | | | | lol : Variable +struct Program { + static Main(): int { + myInt: int = 54; + if (myInt < 0) { + signTag: int = 0 - 1; + } else if (myInt == 0) { + signTag: int = 0; + } else { + signTag: int = 1; + } + + lol: int = 420; + myBool: bool; + if (myBool) { + if (myBool) { + if (myBool) { + if (myBool) { + if (myBool) { lol: int = 69; } } diff --git a/src/identcheck.c b/src/identcheck.c index 772628b..1796ca6 100644 --- a/src/identcheck.c +++ b/src/identcheck.c @@ -6,10 +6,11 @@ #include "ast.h" #include "identcheck.h" -IdNode* MakeIdNode(NodeType type, char *name) { +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; @@ -31,51 +32,19 @@ void AddChildToNode(IdNode *node, IdNode *child) { node->childCount += 1; } -IdNode* FindId(IdNode *root, NodeType targetType, char *targetName) { - 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)) { - result = current; - break; - } - - IdNode **temp = - (IdNode**)malloc(sizeof(IdNode*) * (frontierCount - 1 + current->childCount)); - uint32_t i; - for (i = 1; i < frontierCount; i++) { - temp[i - 1] = frontier[i]; - } - uint32_t offset = i; - for (i = 0; i < current->childCount; i++) { - temp[offset + i] = current->children[i]; - } - frontier = temp; - frontierCount += current->childCount - 1; - } - - free(frontier); - return result; -} - -IdNode* MakeIdTree(Node *astNode) { +IdNode* MakeIdTree(Node *astNode, IdNode *parent) { uint32_t i; switch (astNode->syntaxKind) { case Assignment: return (astNode->children[0]->syntaxKind == Declaration) - ? MakeIdTree(astNode->children[0]) + ? MakeIdTree(astNode->children[0], parent) : NULL; case IfStatement: { Node *stmtSeq = astNode->children[1]; - IdNode *ifNode = MakeIdNode(LexicalScope, "if"); + IdNode *ifNode = MakeIdNode(LexicalScope, "if", parent); for (i = 0; i < stmtSeq->childCount; i++) { - AddChildToNode(ifNode, MakeIdTree(stmtSeq->children[i])); + AddChildToNode(ifNode, MakeIdTree(stmtSeq->children[i], ifNode)); } return ifNode; } @@ -83,14 +52,14 @@ IdNode* MakeIdTree(Node *astNode) { case IfElseStatement: { Node *ifNode = astNode->children[0]; Node *elseStmts = astNode->children[1]; - IdNode *ifElseNode = MakeIdNode(LexicalScope, "if-else"); - IdNode *ifBranch = MakeIdTree(ifNode); - IdNode *elseBranch = MakeIdNode(LexicalScope, "else"); + IdNode *ifElseNode = MakeIdNode(LexicalScope, "if-else", parent); + IdNode *ifBranch = MakeIdTree(ifNode, ifElseNode); + IdNode *elseBranch = MakeIdNode(LexicalScope, "else", ifElseNode); AddChildToNode(ifElseNode, ifBranch); AddChildToNode(ifElseNode, elseBranch); for (i = 0; i < elseStmts->childCount; i++) { - AddChildToNode(elseBranch, MakeIdTree(elseStmts->children[i])); + AddChildToNode(elseBranch, MakeIdTree(elseStmts->children[i], elseBranch)); } return ifElseNode; @@ -99,23 +68,23 @@ IdNode* MakeIdTree(Node *astNode) { case ForLoop: { Node *loopDecl = astNode->children[0]; Node *loopBody = astNode->children[3]; - IdNode *loopNode = MakeIdNode(LexicalScope, "for-loop"); - AddChildToNode(loopNode, MakeIdTree(loopDecl)); + IdNode *loopNode = MakeIdNode(LexicalScope, "for-loop", parent); + AddChildToNode(loopNode, MakeIdTree(loopDecl, loopNode)); for (i = 0; i < loopBody->childCount; i++) { - AddChildToNode(loopNode, MakeIdTree(loopBody->children[i])); + AddChildToNode(loopNode, MakeIdTree(loopBody->children[i], loopNode)); } return loopNode; } case Declaration: - return MakeIdNode(Variable, astNode->children[1]->value.string); + return MakeIdNode(Variable, astNode->children[1]->value.string, parent); case StructDeclaration: { Node *idNode = astNode->children[0]; Node *declsNode = astNode->children[1]; - IdNode *structNode = MakeIdNode(Struct, idNode->value.string); + IdNode *structNode = MakeIdNode(Struct, idNode->value.string, parent); for (i = 0; i < declsNode->childCount; i++) { - AddChildToNode(structNode, MakeIdTree(declsNode->children[i])); + AddChildToNode(structNode, MakeIdTree(declsNode->children[i], structNode)); } return structNode; } @@ -125,20 +94,20 @@ IdNode* MakeIdTree(Node *astNode) { Node *funcNameNode = sigNode->children[0]; Node *funcArgsNode = sigNode->children[2]; Node *bodyStatementsNode = astNode->children[1]; - IdNode *funcNode = MakeIdNode(Function, funcNameNode->value.string); + IdNode *funcNode = MakeIdNode(Function, funcNameNode->value.string, parent); for (i = 0; i < funcArgsNode->childCount; i++) { - AddChildToNode(funcNode, MakeIdTree(funcArgsNode->children[i])); + AddChildToNode(funcNode, MakeIdTree(funcArgsNode->children[i], funcNode)); } for (i = 0; i < bodyStatementsNode->childCount; i++) { - AddChildToNode(funcNode, MakeIdTree(bodyStatementsNode->children[i])); + AddChildToNode(funcNode, MakeIdTree(bodyStatementsNode->children[i], funcNode)); } return funcNode; } case DeclarationSequence: { - IdNode *declSeqNode = MakeIdNode(LexicalScope, ""); + IdNode *declSeqNode = MakeIdNode(LexicalScope, "", parent); for (i = 0; i < astNode->childCount; i++) { - AddChildToNode(declSeqNode, MakeIdTree(astNode->children[i])); + AddChildToNode(declSeqNode, MakeIdTree(astNode->children[i], declSeqNode)); } return declSeqNode; } @@ -148,20 +117,67 @@ IdNode* MakeIdTree(Node *astNode) { } } +void PrintIdNode(IdNode *node) { + switch(node->type) { + case LexicalScope: printf("Scope (%s)\n", node->name); break; + case Struct: printf("%s : Struct\n", node->name); break; + case Function: printf("%s : Function\n", node->name); break; + case Variable: printf("%s : Variable\n", node->name); break; + } +} + void PrintIdTree(IdNode *tree, uint32_t tabCount) { uint32_t i; for (i = 0; i < tabCount; i++) { printf("| "); } - switch(tree->type) { - case LexicalScope: printf("Scope (%s)\n", tree->name); break; - case Struct: printf("%s : Struct\n", tree->name); break; - case Function: printf("%s : Function\n", tree->name); break; - case Variable: printf("%s : Variable\n", tree->name); break; - } + 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* FindId(IdNode *root, NodeType targetType, char *targetName) { + IdNode *result = NULL; + IdNode **frontier = (IdNode**)malloc(sizeof(IdNode*)); + frontier[0] = root; + uint32_t frontierCount = 1; + uint32_t cursor = 0; + + while (frontierCount > 0 && cursor < frontierCount) { + IdNode *current = frontier[cursor]; + + if (current->type == targetType && strcmp(current->name, targetName) == 0) { + result = current; + break; + } + + int newSize = frontierCount + current->childCount; + frontier = realloc(frontier, sizeof(IdNode*) * newSize); + uint32_t i; + for (i = 0; i < current->childCount; i++) { + frontier[frontierCount + i] = current->children[i]; + } + frontierCount += current->childCount; + cursor += 1; + } + + free(frontier); + return result; +} \ No newline at end of file diff --git a/src/identcheck.h b/src/identcheck.h index 395a73c..0afa6ac 100644 --- a/src/identcheck.h +++ b/src/identcheck.h @@ -16,6 +16,7 @@ typedef enum NodeType { typedef struct IdNode { NodeType type; char *name; + struct IdNode *parent; struct IdNode **children; uint32_t childCount; uint32_t childCapacity; @@ -28,8 +29,10 @@ typedef struct IdStatus { } IdStatus; -IdNode* MakeIdTree(Node *astNode); +IdNode* FindId(IdNode *root, NodeType targetType, char *targetName); +IdNode* MakeIdTree(Node *astNode, IdNode *parent); void PrintIdTree(IdNode *tree, uint32_t tabCount); +int PrintAncestors(IdNode *node); //IdStatus CheckIds(Node *root); diff --git a/src/main.c b/src/main.c index 10668c2..ab08167 100644 --- a/src/main.c +++ b/src/main.c @@ -65,7 +65,14 @@ int main(int argc, char *argv[]) } else { - PrintIdTree(MakeIdTree(rootNode), /*tabCount=*/0); + IdNode *idTree = MakeIdTree(rootNode, NULL); + PrintIdTree(idTree, /*tabCount=*/0); + + { + printf("Searching for a variable named 'lol' and printing its ancestors\n"); + IdNode *deepest = FindId(idTree, Variable, "lol"); + PrintAncestors(deepest); + } exitCode = Codegen(rootNode, optimizationLevel); } } -- 2.25.1 From 565d815deb72647a5660a6d296270fa939b25fe2 Mon Sep 17 00:00:00 2001 From: venko Date: Fri, 7 May 2021 13:35:28 -0700 Subject: [PATCH 05/15] Adds error message to FindId, extra test code in main --- commenttest.w | 6 ++++++ src/identcheck.c | 5 +++++ src/main.c | 14 +++++++++++--- 3 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 commenttest.w diff --git a/commenttest.w b/commenttest.w new file mode 100644 index 0000000..70cd73e --- /dev/null +++ b/commenttest.w @@ -0,0 +1,6 @@ +struct Program { + // This triggers a parse error + static Main(): int { + return 0; + } +} \ No newline at end of file diff --git a/src/identcheck.c b/src/identcheck.c index 1796ca6..a05543d 100644 --- a/src/identcheck.c +++ b/src/identcheck.c @@ -154,6 +154,11 @@ int PrintAncestors(IdNode *node) { } IdNode* FindId(IdNode *root, NodeType targetType, char *targetName) { + if (root == NULL) { + fprintf(stderr, "wraith: Attempted to call FindId on a null value.\n"); + return NULL; + } + IdNode *result = NULL; IdNode **frontier = (IdNode**)malloc(sizeof(IdNode*)); frontier[0] = root; diff --git a/src/main.c b/src/main.c index ab08167..03985fc 100644 --- a/src/main.c +++ b/src/main.c @@ -65,13 +65,21 @@ int main(int argc, char *argv[]) } else { - IdNode *idTree = MakeIdTree(rootNode, NULL); - PrintIdTree(idTree, /*tabCount=*/0); - { + IdNode *idTree = MakeIdTree(rootNode, NULL); + PrintIdTree(idTree, /*tabCount=*/0); + printf("\n"); + printf("Searching for a variable named 'lol' and printing its ancestors\n"); IdNode *deepest = FindId(idTree, Variable, "lol"); PrintAncestors(deepest); + printf("\n"); + + printf("Now searching for the same variable but with the caveat that it" + " must be inside an if-block, and printing its ancestors\n"); + deepest = FindId(idTree, LexicalScope, "if"); + deepest = FindId(deepest, Variable, "lol"); + PrintAncestors(deepest); } exitCode = Codegen(rootNode, optimizationLevel); } -- 2.25.1 From 71ba1f945428cfa95eabac971adfe9d6bf274139 Mon Sep 17 00:00:00 2001 From: venko Date: Fri, 7 May 2021 14:07:57 -0700 Subject: [PATCH 06/15] Minimizes memory footprint of id-tree search --- src/identcheck.c | 25 +++++++++++++++---------- src/main.c | 14 +------------- 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/src/identcheck.c b/src/identcheck.c index a05543d..9cb69f7 100644 --- a/src/identcheck.c +++ b/src/identcheck.c @@ -163,26 +163,31 @@ IdNode* FindId(IdNode *root, NodeType targetType, char *targetName) { IdNode **frontier = (IdNode**)malloc(sizeof(IdNode*)); frontier[0] = root; uint32_t frontierCount = 1; - uint32_t cursor = 0; - while (frontierCount > 0 && cursor < frontierCount) { - IdNode *current = frontier[cursor]; + while (frontierCount > 0) { + IdNode *current = frontier[0]; if (current->type == targetType && strcmp(current->name, targetName) == 0) { result = current; break; } - int newSize = frontierCount + current->childCount; - frontier = realloc(frontier, sizeof(IdNode*) * newSize); uint32_t i; - for (i = 0; i < current->childCount; i++) { - frontier[frontierCount + i] = current->children[i]; + for(i = 1; i < frontierCount; i++) { + frontier[i-1] = frontier[i]; } - frontierCount += current->childCount; - cursor += 1; + + size_t newSize = frontierCount + current->childCount - 1; + if (frontierCount != newSize) { + frontier = 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; -} \ No newline at end of file +} diff --git a/src/main.c b/src/main.c index 03985fc..691c1db 100644 --- a/src/main.c +++ b/src/main.c @@ -65,21 +65,9 @@ int main(int argc, char *argv[]) } else { - { + if (parseVerbose) { IdNode *idTree = MakeIdTree(rootNode, NULL); PrintIdTree(idTree, /*tabCount=*/0); - printf("\n"); - - printf("Searching for a variable named 'lol' and printing its ancestors\n"); - IdNode *deepest = FindId(idTree, Variable, "lol"); - PrintAncestors(deepest); - printf("\n"); - - printf("Now searching for the same variable but with the caveat that it" - " must be inside an if-block, and printing its ancestors\n"); - deepest = FindId(idTree, LexicalScope, "if"); - deepest = FindId(deepest, Variable, "lol"); - PrintAncestors(deepest); } exitCode = Codegen(rootNode, optimizationLevel); } -- 2.25.1 From fddacae487597151ab0e8c786bb188f833eeb15a Mon Sep 17 00:00:00 2001 From: venko Date: Fri, 7 May 2021 14:19:56 -0700 Subject: [PATCH 07/15] tiny refactor --- src/identcheck.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/identcheck.c b/src/identcheck.c index 9cb69f7..32408d8 100644 --- a/src/identcheck.c +++ b/src/identcheck.c @@ -176,7 +176,6 @@ IdNode* FindId(IdNode *root, NodeType targetType, char *targetName) { for(i = 1; i < frontierCount; i++) { frontier[i-1] = frontier[i]; } - size_t newSize = frontierCount + current->childCount - 1; if (frontierCount != newSize) { frontier = realloc(frontier, sizeof(IdNode*) * newSize); @@ -184,7 +183,6 @@ IdNode* FindId(IdNode *root, NodeType targetType, char *targetName) { for (i = 0; i < current->childCount; i++) { frontier[frontierCount + i - 1] = current->children[i]; } - frontierCount = newSize; } -- 2.25.1 From e2bca66dc4a289bdc3674ee85ce972872acd4a3a Mon Sep 17 00:00:00 2001 From: venko Date: Fri, 7 May 2021 14:36:37 -0700 Subject: [PATCH 08/15] Adds null-guard to PrintIdTree --- src/identcheck.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/identcheck.c b/src/identcheck.c index 32408d8..75e966c 100644 --- a/src/identcheck.c +++ b/src/identcheck.c @@ -127,6 +127,11 @@ void PrintIdNode(IdNode *node) { } 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("| "); -- 2.25.1 From 5ab3cc533d493930bb16e52da720f0a17883a07b Mon Sep 17 00:00:00 2001 From: venko Date: Fri, 7 May 2021 17:49:35 -0700 Subject: [PATCH 09/15] Adds type tags to the id-tree --- src/ast.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ast.h | 25 ++++++++++++++++ src/identcheck.c | 30 +++++++++++++++---- src/identcheck.h | 1 + 4 files changed, 128 insertions(+), 6 deletions(-) diff --git a/src/ast.c b/src/ast.c index 4c39ba0..3fb4869 100644 --- a/src/ast.c +++ b/src/ast.c @@ -526,3 +526,81 @@ void PrintTree(Node *node, uint32_t tabCount) PrintTree(node->children[i], tabCount + 1); } } + +TypeTag* MakeTypeTag(Node *node) { + if (node == NULL) { + fprintf(stderr, "wraith: Attempted to call MakeTypeTag on null value.\n"); + return NULL; + } + + TypeTag *tag = (TypeTag*)malloc(sizeof(TypeTag)); + switch (node->syntaxKind) { + case Type: + tag = MakeTypeTag(node->children[0]); + break; + + case PrimitiveTypeNode: + tag->type = Primitive; + tag->value.primitiveType = node->primitiveType; + break; + + case ReferenceTypeNode: + tag->type = Reference; + tag->value.referenceType = MakeTypeTag(node->children[0]); + break; + + case CustomTypeNode: + tag->type = Custom; + tag->value.customType = strdup(node->value.string); + break; + + case Declaration: + tag = MakeTypeTag(node->children[0]); + break; + + case StructDeclaration: + tag->type = Custom; + tag->value.customType = strdup(node->children[0]->value.string); + break; + + case FunctionDeclaration: + tag = MakeTypeTag(node->children[0]->children[1]); + break; + + default: + fprintf(stderr, + "wraith: Attempted to call MakeTypeTag on" + " node with unsupported SyntaxKind: %s\n", + SyntaxKindString(node->syntaxKind)); + return NULL; + } + return tag; +} + +char* TypeTagToString(TypeTag *tag) { + if (tag == NULL) { + fprintf(stderr, "wraith: Attempted to call TypeTagToString with null value\n"); + return NULL; + } + + switch (tag->type) { + case Unknown: + return "Unknown"; + case Primitive: + return PrimitiveTypeToString(tag->value.primitiveType); + case Reference: { + char *inner = TypeTagToString(tag->value.referenceType); + size_t innerStrLen = strlen(inner); + char *result = malloc(sizeof(char) * (innerStrLen + 5)); + sprintf(result, "Ref<%s>", inner); + return result; + } + case Custom: + return tag->value.customType; + } +} + +void AddTypeTags(Node *ast) +{ + fprintf(stderr, "wraith: AddTypeTags not implemented yet.\n"); +} \ No newline at end of file diff --git a/src/ast.h b/src/ast.h index 5c04d76..9c5d4fc 100644 --- a/src/ast.h +++ b/src/ast.h @@ -71,6 +71,26 @@ typedef union BinaryOperator binaryOperator; } Operator; +typedef struct TypeTag +{ + enum Type + { + Unknown, + Primitive, + Reference, + Custom + } type; + union + { + // Valid when type = Primitive. + PrimitiveType primitiveType; + // Valid when type = Reference. + struct TypeTag *referenceType; + // Valid when type = Custom. + char *customType; + } value; +} TypeTag; + typedef struct Node { SyntaxKind syntaxKind; @@ -87,6 +107,7 @@ typedef struct Node uint64_t number; } value; PrimitiveType primitiveType; + TypeTag *typeTag; } Node; const char* SyntaxKindString(SyntaxKind syntaxKind); @@ -211,4 +232,8 @@ Node* MakeForLoopNode( void PrintTree(Node *node, uint32_t tabCount); +TypeTag* MakeTypeTag(Node *node); +char* TypeTagToString(TypeTag *tag); +void AddTypeTags(Node *ast); + #endif /* WRAITH_AST_H */ diff --git a/src/identcheck.c b/src/identcheck.c index 75e966c..14c6175 100644 --- a/src/identcheck.c +++ b/src/identcheck.c @@ -76,13 +76,17 @@ IdNode* MakeIdTree(Node *astNode, IdNode *parent) { return loopNode; } - case Declaration: - return MakeIdNode(Variable, astNode->children[1]->value.string, parent); + case Declaration: { + IdNode *declNode = MakeIdNode(Variable, astNode->children[1]->value.string, parent); + declNode->typeTag = MakeTypeTag(astNode); + return declNode; + } case StructDeclaration: { Node *idNode = astNode->children[0]; Node *declsNode = astNode->children[1]; IdNode *structNode = MakeIdNode(Struct, idNode->value.string, parent); + structNode->typeTag = MakeTypeTag(astNode); for (i = 0; i < declsNode->childCount; i++) { AddChildToNode(structNode, MakeIdTree(declsNode->children[i], structNode)); } @@ -95,6 +99,7 @@ IdNode* MakeIdTree(Node *astNode, IdNode *parent) { Node *funcArgsNode = sigNode->children[2]; Node *bodyStatementsNode = astNode->children[1]; IdNode *funcNode = MakeIdNode(Function, funcNameNode->value.string, parent); + funcNode->typeTag = MakeTypeTag(astNode); for (i = 0; i < funcArgsNode->childCount; i++) { AddChildToNode(funcNode, MakeIdTree(funcArgsNode->children[i], funcNode)); } @@ -118,11 +123,24 @@ IdNode* MakeIdTree(Node *astNode, IdNode *parent) { } void PrintIdNode(IdNode *node) { + if (node == NULL) { + fprintf(stderr, "wraith: Attempted to call PrintIdNode with null value.\n"); + return; + } + switch(node->type) { - case LexicalScope: printf("Scope (%s)\n", node->name); break; - case Struct: printf("%s : Struct\n", node->name); break; - case Function: printf("%s : Function\n", node->name); break; - case Variable: printf("%s : Variable\n", node->name); break; + case LexicalScope: + printf("Scope (%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; } } diff --git a/src/identcheck.h b/src/identcheck.h index 0afa6ac..78feed9 100644 --- a/src/identcheck.h +++ b/src/identcheck.h @@ -16,6 +16,7 @@ typedef enum NodeType { typedef struct IdNode { NodeType type; char *name; + TypeTag *typeTag; struct IdNode *parent; struct IdNode **children; uint32_t childCount; -- 2.25.1 From 743828450c1955e8a0ee6a01be9cb1888ee7f7b5 Mon Sep 17 00:00:00 2001 From: venko Date: Fri, 7 May 2021 17:51:23 -0700 Subject: [PATCH 10/15] Explicitly sets IdNode type tags on creation. --- src/identcheck.c | 1 + types.w | 14 ++++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 types.w diff --git a/src/identcheck.c b/src/identcheck.c index 14c6175..9bb8f09 100644 --- a/src/identcheck.c +++ b/src/identcheck.c @@ -14,6 +14,7 @@ IdNode* MakeIdNode(NodeType type, char *name, IdNode *parent) { node->childCount = 0; node->childCapacity = 0; node->children = NULL; + node->typeTag = NULL; return node; } diff --git a/types.w b/types.w new file mode 100644 index 0000000..f83e5e5 --- /dev/null +++ b/types.w @@ -0,0 +1,14 @@ +struct MyStruct { + foo: int; + bar: bool; + MyFunction(): int { + return foo * 420; + } +} + +struct Program { + static Main(): int { + decl: Reference>>>>; + return 0; + } +} \ No newline at end of file -- 2.25.1 From 252dc9b87ff83c253644941c3d74fb5b2750d4e7 Mon Sep 17 00:00:00 2001 From: venko Date: Sat, 8 May 2021 12:09:25 -0700 Subject: [PATCH 11/15] Disambiguates scopes where ordering matters vs ones where it doesn't --- src/identcheck.c | 19 +++++++++++-------- src/identcheck.h | 6 ++++-- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/identcheck.c b/src/identcheck.c index 9bb8f09..88d8112 100644 --- a/src/identcheck.c +++ b/src/identcheck.c @@ -43,7 +43,7 @@ IdNode* MakeIdTree(Node *astNode, IdNode *parent) { case IfStatement: { Node *stmtSeq = astNode->children[1]; - IdNode *ifNode = MakeIdNode(LexicalScope, "if", parent); + IdNode *ifNode = MakeIdNode(OrderedScope, "if", parent); for (i = 0; i < stmtSeq->childCount; i++) { AddChildToNode(ifNode, MakeIdTree(stmtSeq->children[i], ifNode)); } @@ -53,9 +53,9 @@ IdNode* MakeIdTree(Node *astNode, IdNode *parent) { case IfElseStatement: { Node *ifNode = astNode->children[0]; Node *elseStmts = astNode->children[1]; - IdNode *ifElseNode = MakeIdNode(LexicalScope, "if-else", parent); + IdNode *ifElseNode = MakeIdNode(OrderedScope, "if-else", parent); IdNode *ifBranch = MakeIdTree(ifNode, ifElseNode); - IdNode *elseBranch = MakeIdNode(LexicalScope, "else", ifElseNode); + IdNode *elseBranch = MakeIdNode(OrderedScope, "else", ifElseNode); AddChildToNode(ifElseNode, ifBranch); AddChildToNode(ifElseNode, elseBranch); @@ -69,7 +69,7 @@ IdNode* MakeIdTree(Node *astNode, IdNode *parent) { case ForLoop: { Node *loopDecl = astNode->children[0]; Node *loopBody = astNode->children[3]; - IdNode *loopNode = MakeIdNode(LexicalScope, "for-loop", parent); + IdNode *loopNode = MakeIdNode(OrderedScope, "for-loop", parent); AddChildToNode(loopNode, MakeIdTree(loopDecl, loopNode)); for (i = 0; i < loopBody->childCount; i++) { AddChildToNode(loopNode, MakeIdTree(loopBody->children[i], loopNode)); @@ -111,7 +111,7 @@ IdNode* MakeIdTree(Node *astNode, IdNode *parent) { } case DeclarationSequence: { - IdNode *declSeqNode = MakeIdNode(LexicalScope, "", parent); + IdNode *declSeqNode = MakeIdNode(UnorderedScope, "", parent); for (i = 0; i < astNode->childCount; i++) { AddChildToNode(declSeqNode, MakeIdTree(astNode->children[i], declSeqNode)); } @@ -130,8 +130,11 @@ void PrintIdNode(IdNode *node) { } switch(node->type) { - case LexicalScope: - printf("Scope (%s)\n", node->name); + 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)); @@ -177,7 +180,7 @@ int PrintAncestors(IdNode *node) { return indent; } -IdNode* FindId(IdNode *root, NodeType targetType, char *targetName) { +IdNode* LookdownId(IdNode *root, NodeType targetType, char *targetName) { if (root == NULL) { fprintf(stderr, "wraith: Attempted to call FindId on a null value.\n"); return NULL; diff --git a/src/identcheck.h b/src/identcheck.h index 78feed9..7a71bf0 100644 --- a/src/identcheck.h +++ b/src/identcheck.h @@ -7,7 +7,8 @@ #include "ast.h" typedef enum NodeType { - LexicalScope, + UnorderedScope, + OrderedScope, Struct, Function, Variable @@ -30,10 +31,11 @@ typedef struct IdStatus { } IdStatus; -IdNode* FindId(IdNode *root, NodeType targetType, char *targetName); IdNode* MakeIdTree(Node *astNode, IdNode *parent); 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); //IdStatus CheckIds(Node *root); -- 2.25.1 From aa2449f7dfaa503fb7f7b04c52e52aa65e90a098 Mon Sep 17 00:00:00 2001 From: venko Date: Sat, 8 May 2021 14:51:15 -0700 Subject: [PATCH 12/15] Implements identifier lookup. --- iftest.w | 18 ++++++++++++++- src/ast.c | 1 + src/identcheck.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++-- src/identcheck.h | 1 + src/main.c | 42 ++++++++++++++++++++++++++++++++- 5 files changed, 118 insertions(+), 4 deletions(-) diff --git a/iftest.w b/iftest.w index 73df20c..efa5bfa 100644 --- a/iftest.w +++ b/iftest.w @@ -1,4 +1,15 @@ +struct MyStruct { + static MyFunc(): int { + myStructInt: int = 595959959; + return myStructInt; + } +} + struct Program { + static Foo(): int { + return 0; + } + static Main(): int { myInt: int = 54; if (myInt < 0) { @@ -9,7 +20,6 @@ struct Program { signTag: int = 1; } - lol: int = 420; myBool: bool; if (myBool) { if (myBool) { @@ -23,6 +33,12 @@ struct Program { } } + someInt: int = 9585858; + + return 0; + } + + static Bar(): int { return 0; } } diff --git a/src/ast.c b/src/ast.c index 3fb4869..130f094 100644 --- a/src/ast.c +++ b/src/ast.c @@ -593,6 +593,7 @@ char* TypeTagToString(TypeTag *tag) { size_t innerStrLen = strlen(inner); char *result = malloc(sizeof(char) * (innerStrLen + 5)); sprintf(result, "Ref<%s>", inner); + free(inner); return result; } case Custom: diff --git a/src/identcheck.c b/src/identcheck.c index 88d8112..e8a51c1 100644 --- a/src/identcheck.c +++ b/src/identcheck.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -58,10 +59,10 @@ IdNode* MakeIdTree(Node *astNode, IdNode *parent) { IdNode *elseBranch = MakeIdNode(OrderedScope, "else", ifElseNode); AddChildToNode(ifElseNode, ifBranch); - AddChildToNode(ifElseNode, elseBranch); for (i = 0; i < elseStmts->childCount; i++) { AddChildToNode(elseBranch, MakeIdTree(elseStmts->children[i], elseBranch)); } + AddChildToNode(ifElseNode, elseBranch); return ifElseNode; } @@ -182,7 +183,7 @@ int PrintAncestors(IdNode *node) { IdNode* LookdownId(IdNode *root, NodeType targetType, char *targetName) { if (root == NULL) { - fprintf(stderr, "wraith: Attempted to call FindId on a null value.\n"); + fprintf(stderr, "wraith: Attempted to call LookdownId on a null value.\n"); return NULL; } @@ -216,3 +217,58 @@ IdNode* LookdownId(IdNode *root, NodeType targetType, char *targetName) { 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) { + return node; + } + + // 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 (prev == NULL || !ScopeHasOrdering(node)) { + idxLimit = node->childCount; + } else { + uint32_t i; + for (i = 0, idxLimit = 0; i < node->childCount; i++, idxLimit++) { + if (node->children[i] == prev) { + break; + } + } + } + + uint32_t i; + for (i = 0; i < idxLimit; i++) { + IdNode *child = node->children[i]; + 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); +} \ No newline at end of file diff --git a/src/identcheck.h b/src/identcheck.h index 7a71bf0..b41576b 100644 --- a/src/identcheck.h +++ b/src/identcheck.h @@ -32,6 +32,7 @@ typedef struct IdStatus { IdNode* MakeIdTree(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); diff --git a/src/main.c b/src/main.c index 691c1db..d50aeb5 100644 --- a/src/main.c +++ b/src/main.c @@ -65,9 +65,49 @@ int main(int argc, char *argv[]) } else { - if (parseVerbose) { + { // This shit only works if you're using iftest.w IdNode *idTree = MakeIdTree(rootNode, NULL); PrintIdTree(idTree, /*tabCount=*/0); + + printf("\nSeeking to variable 'myStructInt'\n"); + IdNode *node = LookdownId(idTree, Variable, "myStructInt"); + if (node == NULL) printf("Failed.\n"); + + printf("\n[attempting to look up MyStruct]: \n"); + PrintIdNode(LookupId(node, /*prev=*/NULL, "MyStruct")); + + printf("\n[attempting to look up MyFunc]: \n"); + PrintIdNode(LookupId(node, /*prev=*/NULL, "MyFunc")); + + printf("\n[attempting to look up myStructInt]: \n"); + PrintIdNode(LookupId(node, /*prev=*/NULL, "myStructInt")); + + printf("\n[attempting to look up Program]: \n"); + PrintIdNode(LookupId(node, /*prev=*/NULL, "Program")); + + printf("\n[attempting to look up Foo]: \n"); + PrintIdNode(LookupId(node, /*prev=*/NULL, "Foo")); + + printf("\n[attempting to look up Main]: \n"); + PrintIdNode(LookupId(node, /*prev=*/NULL, "Main")); + + printf("\n[attempting to look up myInt]: \n"); + PrintIdNode(LookupId(node, /*prev=*/NULL, "myInt")); + + printf("\n[attempting to look up signTag]: \n"); + PrintIdNode(LookupId(node, /*prev=*/NULL, "signTag")); + + printf("\n[attempting to look up myBool]: \n"); + PrintIdNode(LookupId(node, /*prev=*/NULL, "myBool")); + + printf("\n[attempting to look up lol]: \n"); + PrintIdNode(LookupId(node, /*prev=*/NULL, "lol")); + + printf("\n[attempting to look up someInt]: \n"); + PrintIdNode(LookupId(node, /*prev=*/NULL, "someInt")); + + printf("\n[attempting to look up Bar]: \n"); + PrintIdNode(LookupId(node, /*prev=*/NULL, "Bar")); } exitCode = Codegen(rootNode, optimizationLevel); } -- 2.25.1 From 32541d47946478b6fd784a10cba495dd83b696a3 Mon Sep 17 00:00:00 2001 From: venko Date: Sat, 8 May 2021 15:12:53 -0700 Subject: [PATCH 13/15] Fixes bugs in LookupId --- src/identcheck.c | 26 +++++++++++++++++++++----- src/main.c | 4 ++-- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/identcheck.c b/src/identcheck.c index e8a51c1..c1c56e9 100644 --- a/src/identcheck.c +++ b/src/identcheck.c @@ -238,23 +238,39 @@ IdNode* LookupId(IdNode *node, IdNode *prev, char *target) { return node; } - // 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. + // 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); + } + uint32_t idxLimit; - if (prev == NULL || !ScopeHasOrdering(node)) { - idxLimit = node->childCount; - } else { + // 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. + 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) { + // Do not inspect the node we just came from. + continue; + } + if (strcmp(child->name, target) == 0) { return child; } diff --git a/src/main.c b/src/main.c index d50aeb5..cd1fbbb 100644 --- a/src/main.c +++ b/src/main.c @@ -69,8 +69,8 @@ int main(int argc, char *argv[]) IdNode *idTree = MakeIdTree(rootNode, NULL); PrintIdTree(idTree, /*tabCount=*/0); - printf("\nSeeking to variable 'myStructInt'\n"); - IdNode *node = LookdownId(idTree, Variable, "myStructInt"); + printf("\nSeeking to struct 'Program'\n"); + IdNode *node = LookdownId(idTree, Struct, "Program"); if (node == NULL) printf("Failed.\n"); printf("\n[attempting to look up MyStruct]: \n"); -- 2.25.1 From f441e5bede8ceda18b97c14da4e2b2b888823cfb Mon Sep 17 00:00:00 2001 From: venko Date: Wed, 12 May 2021 21:54:09 -0700 Subject: [PATCH 14/15] Possibly implements full type annotation of the AST --- reftest.w | 11 +++++ src/ast.c | 15 ++++--- src/ast.h | 4 +- src/identcheck.c | 114 +++++++++++++++++++++++++++++++---------------- src/identcheck.h | 8 +++- src/main.c | 44 ++---------------- 6 files changed, 106 insertions(+), 90 deletions(-) create mode 100644 reftest.w diff --git a/reftest.w b/reftest.w new file mode 100644 index 0000000..ece6a0c --- /dev/null +++ b/reftest.w @@ -0,0 +1,11 @@ +struct MyStruct { + foo: int; +} + +struct Program { + static Main(): int { + myStruct: Reference; + myStruct = alloc MyStruct; + return 0; + } +} \ No newline at end of file diff --git a/src/ast.c b/src/ast.c index 130f094..273739a 100644 --- a/src/ast.c +++ b/src/ast.c @@ -97,6 +97,7 @@ Node* MakeIdentifierNode( node->syntaxKind = Identifier; node->value.string = strdup(id); node->childCount = 0; + node->typeTag = NULL; return node; } @@ -506,7 +507,12 @@ static void PrintNode(Node *node, int tabCount) break; case Identifier: - printf("%s", node->value.string); + if (node->typeTag == NULL) { + printf("%s", node->value.string); + } else { + char *type = TypeTagToString(node->typeTag); + printf("%s<%s>", node->value.string, type); + } break; case Number: @@ -561,6 +567,7 @@ TypeTag* MakeTypeTag(Node *node) { case StructDeclaration: tag->type = Custom; tag->value.customType = strdup(node->children[0]->value.string); + printf("Struct tag: %s\n", TypeTagToString(tag)); break; case FunctionDeclaration: @@ -593,15 +600,9 @@ char* TypeTagToString(TypeTag *tag) { size_t innerStrLen = strlen(inner); char *result = malloc(sizeof(char) * (innerStrLen + 5)); sprintf(result, "Ref<%s>", inner); - free(inner); return result; } case Custom: return tag->value.customType; } -} - -void AddTypeTags(Node *ast) -{ - fprintf(stderr, "wraith: AddTypeTags not implemented yet.\n"); } \ No newline at end of file diff --git a/src/ast.h b/src/ast.h index 9c5d4fc..4da2d11 100644 --- a/src/ast.h +++ b/src/ast.h @@ -2,6 +2,7 @@ #define WRAITH_AST_H #include +#include "identcheck.h" typedef enum { @@ -108,6 +109,7 @@ typedef struct Node } value; PrimitiveType primitiveType; TypeTag *typeTag; + IdNode *idLink; } Node; const char* SyntaxKindString(SyntaxKind syntaxKind); @@ -231,9 +233,9 @@ Node* MakeForLoopNode( ); void PrintTree(Node *node, uint32_t tabCount); +const char* SyntaxKindString(SyntaxKind syntaxKind); TypeTag* MakeTypeTag(Node *node); char* TypeTagToString(TypeTag *tag); -void AddTypeTags(Node *ast); #endif /* WRAITH_AST_H */ diff --git a/src/identcheck.c b/src/identcheck.c index c1c56e9..ced9e0a 100644 --- a/src/identcheck.c +++ b/src/identcheck.c @@ -36,63 +36,74 @@ void AddChildToNode(IdNode *node, IdNode *child) { IdNode* MakeIdTree(Node *astNode, IdNode *parent) { uint32_t i; + IdNode *mainNode; switch (astNode->syntaxKind) { - case Assignment: - return (astNode->children[0]->syntaxKind == Declaration) - ? MakeIdTree(astNode->children[0], parent) - : NULL; + case Assignment: { + if (astNode->children[0]->syntaxKind == Declaration) { + return MakeIdTree(astNode->children[0], parent); + } else { + for (i = 0; i < astNode->childCount; i++) { + AddChildToNode(parent, MakeIdTree(astNode->children[i], parent)); + } + return NULL; + } + } case IfStatement: { + mainNode = MakeIdNode(OrderedScope, "if", parent); + Node *clause = astNode->children[0]; Node *stmtSeq = astNode->children[1]; - IdNode *ifNode = MakeIdNode(OrderedScope, "if", parent); - for (i = 0; i < stmtSeq->childCount; i++) { - AddChildToNode(ifNode, MakeIdTree(stmtSeq->children[i], ifNode)); + for (i = 0; i < clause->childCount; i++) { + AddChildToNode(mainNode, MakeIdTree(clause->children[i], mainNode)); } - return ifNode; + for (i = 0; i < stmtSeq->childCount; i++) { + AddChildToNode(mainNode, MakeIdTree(stmtSeq->children[i], mainNode)); + } + break; } case IfElseStatement: { Node *ifNode = astNode->children[0]; Node *elseStmts = astNode->children[1]; - IdNode *ifElseNode = MakeIdNode(OrderedScope, "if-else", parent); - IdNode *ifBranch = MakeIdTree(ifNode, ifElseNode); - IdNode *elseBranch = MakeIdNode(OrderedScope, "else", ifElseNode); + mainNode = MakeIdNode(OrderedScope, "if-else", parent); + IdNode *ifBranch = MakeIdTree(ifNode, mainNode); + IdNode *elseBranch = MakeIdNode(OrderedScope, "else", mainNode); - AddChildToNode(ifElseNode, ifBranch); + AddChildToNode(mainNode, ifBranch); for (i = 0; i < elseStmts->childCount; i++) { AddChildToNode(elseBranch, MakeIdTree(elseStmts->children[i], elseBranch)); } - AddChildToNode(ifElseNode, elseBranch); - - return ifElseNode; + AddChildToNode(mainNode, elseBranch); + break; } case ForLoop: { Node *loopDecl = astNode->children[0]; Node *loopBody = astNode->children[3]; - IdNode *loopNode = MakeIdNode(OrderedScope, "for-loop", parent); - AddChildToNode(loopNode, MakeIdTree(loopDecl, loopNode)); + mainNode = MakeIdNode(OrderedScope, "for-loop", parent); + AddChildToNode(mainNode, MakeIdTree(loopDecl, mainNode)); for (i = 0; i < loopBody->childCount; i++) { - AddChildToNode(loopNode, MakeIdTree(loopBody->children[i], loopNode)); + AddChildToNode(mainNode, MakeIdTree(loopBody->children[i], mainNode)); } - return loopNode; + break; } case Declaration: { - IdNode *declNode = MakeIdNode(Variable, astNode->children[1]->value.string, parent); - declNode->typeTag = MakeTypeTag(astNode); - return declNode; + mainNode = MakeIdNode(Variable, astNode->children[1]->value.string, parent); + mainNode->typeTag = MakeTypeTag(astNode); + astNode->children[1]->typeTag = mainNode->typeTag; + break; } case StructDeclaration: { Node *idNode = astNode->children[0]; Node *declsNode = astNode->children[1]; - IdNode *structNode = MakeIdNode(Struct, idNode->value.string, parent); - structNode->typeTag = MakeTypeTag(astNode); + mainNode = MakeIdNode(Struct, idNode->value.string, parent); + mainNode->typeTag = MakeTypeTag(astNode); for (i = 0; i < declsNode->childCount; i++) { - AddChildToNode(structNode, MakeIdTree(declsNode->children[i], structNode)); + AddChildToNode(mainNode, MakeIdTree(declsNode->children[i], mainNode)); } - return structNode; + break; } case FunctionDeclaration: { @@ -100,28 +111,50 @@ IdNode* MakeIdTree(Node *astNode, IdNode *parent) { Node *funcNameNode = sigNode->children[0]; Node *funcArgsNode = sigNode->children[2]; Node *bodyStatementsNode = astNode->children[1]; - IdNode *funcNode = MakeIdNode(Function, funcNameNode->value.string, parent); - funcNode->typeTag = MakeTypeTag(astNode); + mainNode = MakeIdNode(Function, funcNameNode->value.string, parent); + mainNode->typeTag = MakeTypeTag(astNode); + astNode->children[0]->children[0]->typeTag = mainNode->typeTag; for (i = 0; i < funcArgsNode->childCount; i++) { - AddChildToNode(funcNode, MakeIdTree(funcArgsNode->children[i], funcNode)); + AddChildToNode(mainNode, MakeIdTree(funcArgsNode->children[i], mainNode)); } for (i = 0; i < bodyStatementsNode->childCount; i++) { - AddChildToNode(funcNode, MakeIdTree(bodyStatementsNode->children[i], funcNode)); + AddChildToNode(mainNode, MakeIdTree(bodyStatementsNode->children[i], mainNode)); } - return funcNode; + break; } case DeclarationSequence: { - IdNode *declSeqNode = MakeIdNode(UnorderedScope, "", parent); + mainNode = MakeIdNode(UnorderedScope, "", parent); for (i = 0; i < astNode->childCount; i++) { - AddChildToNode(declSeqNode, MakeIdTree(astNode->children[i], declSeqNode)); + AddChildToNode(mainNode, MakeIdTree(astNode->children[i], mainNode)); } - return declSeqNode; + break; } - default: + case Identifier: { + mainNode = MakeIdNode(Placeholder, astNode->value.string, parent); + IdNode *lookupNode = LookupId(mainNode, NULL, astNode->value.string); + if (lookupNode == NULL) { + fprintf(stderr, "wraith: Could not find IdNode for id %s\n", astNode->value.string); + TypeTag *tag = (TypeTag*)malloc(sizeof(TypeTag)); + tag->type = Unknown; + astNode->typeTag = tag; + } else { + astNode->typeTag = lookupNode->typeTag; + } + break; + } + + default: { + for (i = 0; i < astNode->childCount; i++) { + AddChildToNode(parent, MakeIdTree(astNode->children[i], parent)); + } return NULL; + } } + + astNode->idLink = mainNode; + return mainNode; } void PrintIdNode(IdNode *node) { @@ -131,6 +164,9 @@ void PrintIdNode(IdNode *node) { } switch(node->type) { + case Placeholder: + printf("Placeholder (%s)\n", node->name); + break; case OrderedScope: printf("OrderedScope (%s)\n", node->name); break; @@ -234,7 +270,7 @@ IdNode* LookupId(IdNode *node, IdNode *prev, char *target) { return NULL; } - if (strcmp(node->name, target) == 0) { + if (strcmp(node->name, target) == 0 && node->type != Placeholder) { return node; } @@ -266,8 +302,8 @@ IdNode* LookupId(IdNode *node, IdNode *prev, char *target) { uint32_t i; for (i = 0; i < idxLimit; i++) { IdNode *child = node->children[i]; - if (child == prev) { - // Do not inspect the node we just came from. + if (child == prev || child->type == Placeholder) { + // Do not inspect the node we just came from or placeholders. continue; } @@ -287,4 +323,4 @@ IdNode* LookupId(IdNode *node, IdNode *prev, char *target) { } return LookupId(node->parent, node, target); -} \ No newline at end of file +} diff --git a/src/identcheck.h b/src/identcheck.h index b41576b..9b57858 100644 --- a/src/identcheck.h +++ b/src/identcheck.h @@ -6,7 +6,11 @@ #include "ast.h" +struct TypeTag; +struct Node; + typedef enum NodeType { + Placeholder, UnorderedScope, OrderedScope, Struct, @@ -17,7 +21,7 @@ typedef enum NodeType { typedef struct IdNode { NodeType type; char *name; - TypeTag *typeTag; + struct TypeTag *typeTag; struct IdNode *parent; struct IdNode **children; uint32_t childCount; @@ -31,7 +35,7 @@ typedef struct IdStatus { } IdStatus; -IdNode* MakeIdTree(Node *astNode, IdNode *parent); +IdNode* MakeIdTree(struct Node *astNode, IdNode *parent); void PrintIdNode(IdNode *node); void PrintIdTree(IdNode *tree, uint32_t tabCount); int PrintAncestors(IdNode *node); diff --git a/src/main.c b/src/main.c index cd1fbbb..f58f618 100644 --- a/src/main.c +++ b/src/main.c @@ -65,49 +65,11 @@ int main(int argc, char *argv[]) } else { - { // This shit only works if you're using iftest.w + { IdNode *idTree = MakeIdTree(rootNode, NULL); PrintIdTree(idTree, /*tabCount=*/0); - - printf("\nSeeking to struct 'Program'\n"); - IdNode *node = LookdownId(idTree, Struct, "Program"); - if (node == NULL) printf("Failed.\n"); - - printf("\n[attempting to look up MyStruct]: \n"); - PrintIdNode(LookupId(node, /*prev=*/NULL, "MyStruct")); - - printf("\n[attempting to look up MyFunc]: \n"); - PrintIdNode(LookupId(node, /*prev=*/NULL, "MyFunc")); - - printf("\n[attempting to look up myStructInt]: \n"); - PrintIdNode(LookupId(node, /*prev=*/NULL, "myStructInt")); - - printf("\n[attempting to look up Program]: \n"); - PrintIdNode(LookupId(node, /*prev=*/NULL, "Program")); - - printf("\n[attempting to look up Foo]: \n"); - PrintIdNode(LookupId(node, /*prev=*/NULL, "Foo")); - - printf("\n[attempting to look up Main]: \n"); - PrintIdNode(LookupId(node, /*prev=*/NULL, "Main")); - - printf("\n[attempting to look up myInt]: \n"); - PrintIdNode(LookupId(node, /*prev=*/NULL, "myInt")); - - printf("\n[attempting to look up signTag]: \n"); - PrintIdNode(LookupId(node, /*prev=*/NULL, "signTag")); - - printf("\n[attempting to look up myBool]: \n"); - PrintIdNode(LookupId(node, /*prev=*/NULL, "myBool")); - - printf("\n[attempting to look up lol]: \n"); - PrintIdNode(LookupId(node, /*prev=*/NULL, "lol")); - - printf("\n[attempting to look up someInt]: \n"); - PrintIdNode(LookupId(node, /*prev=*/NULL, "someInt")); - - printf("\n[attempting to look up Bar]: \n"); - PrintIdNode(LookupId(node, /*prev=*/NULL, "Bar")); + printf("\n"); + PrintTree(rootNode, /*tabCount=*/0); } exitCode = Codegen(rootNode, optimizationLevel); } -- 2.25.1 From 41bf2bece8c89040aa0b01df2ad436b55443eda9 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Fri, 14 May 2021 11:53:09 -0700 Subject: [PATCH 15/15] some minor style revisions --- src/ast.h | 12 ++++++------ src/identcheck.c | 48 +++++++++++++++++++++++++----------------------- src/identcheck.h | 5 ++--- 3 files changed, 33 insertions(+), 32 deletions(-) diff --git a/src/ast.h b/src/ast.h index 4da2d11..9c1312f 100644 --- a/src/ast.h +++ b/src/ast.h @@ -74,20 +74,20 @@ typedef union typedef struct TypeTag { - enum Type + enum Type { Unknown, Primitive, Reference, Custom } type; - union + union { - // Valid when type = Primitive. + /* Valid when type = Primitive. */ PrimitiveType primitiveType; - // Valid when type = Reference. + /* Valid when type = Reference. */ struct TypeTag *referenceType; - // Valid when type = Custom. + /* Valid when type = Custom. */ char *customType; } value; } TypeTag; @@ -108,7 +108,7 @@ typedef struct Node uint64_t number; } value; PrimitiveType primitiveType; - TypeTag *typeTag; + TypeTag *typeTag; IdNode *idLink; } Node; diff --git a/src/identcheck.c b/src/identcheck.c index ced9e0a..6fe0ec4 100644 --- a/src/identcheck.c +++ b/src/identcheck.c @@ -24,10 +24,10 @@ void AddChildToNode(IdNode *node, IdNode *child) { if (node->children == NULL) { node->childCapacity = 2; - node->children = (IdNode**)malloc(sizeof(IdNode*) * node->childCapacity); + node->children = (IdNode**) malloc(sizeof(IdNode*) * node->childCapacity); } else if (node->childCount == node->childCapacity) { node->childCapacity *= 2; - node->children = realloc(node->children, sizeof(IdNode*) * node->childCapacity); + node->children = (IdNode**) realloc(node->children, sizeof(IdNode*) * node->childCapacity); } node->children[node->childCount] = child; @@ -167,20 +167,20 @@ void PrintIdNode(IdNode *node) { case Placeholder: printf("Placeholder (%s)\n", node->name); break; - case OrderedScope: - printf("OrderedScope (%s)\n", node->name); + case OrderedScope: + printf("OrderedScope (%s)\n", node->name); break; - case UnorderedScope: - printf("UnorderedScope (%s)\n", node->name); + case UnorderedScope: + printf("UnorderedScope (%s)\n", node->name); break; case Struct: - printf("%s : %s\n", node->name, TypeTagToString(node->typeTag)); + 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)); + case Variable: + printf("%s : %s\n", node->name, TypeTagToString(node->typeTag)); break; } } @@ -242,7 +242,7 @@ IdNode* LookdownId(IdNode *root, NodeType targetType, char *targetName) { } size_t newSize = frontierCount + current->childCount - 1; if (frontierCount != newSize) { - frontier = realloc(frontier, sizeof(IdNode*) * newSize); + frontier = (IdNode**) realloc(frontier, sizeof(IdNode*) * newSize); } for (i = 0; i < current->childCount; i++) { frontier[frontierCount + i - 1] = current->children[i]; @@ -258,7 +258,7 @@ bool ScopeHasOrdering(IdNode *node) { switch (node->type) { case OrderedScope: case Function: - case Variable: // this is only technically true + case Variable: /* this is only technically true */ return true; default: return false; @@ -274,20 +274,22 @@ IdNode* LookupId(IdNode *node, IdNode *prev, char *target) { 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 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 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. if (ScopeHasOrdering(node)) { uint32_t i; for (i = 0, idxLimit = 0; i < node->childCount; i++, idxLimit++) { @@ -303,13 +305,13 @@ IdNode* LookupId(IdNode *node, IdNode *prev, char *target) { 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. + /* 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; @@ -317,7 +319,7 @@ IdNode* LookupId(IdNode *node, IdNode *prev, char *target) { IdNode *grandchild = child->children[j]; if (strcmp(grandchild->name, target) == 0) { return grandchild; - } + } } } } diff --git a/src/identcheck.h b/src/identcheck.h index 9b57858..2c75262 100644 --- a/src/identcheck.h +++ b/src/identcheck.h @@ -1,4 +1,5 @@ -// Validates identifier usage in an AST. +/* Validates identifier usage in an AST. */ + #ifndef WRAITH_IDENTCHECK_H #define WRAITH_IDENTCHECK_H @@ -42,6 +43,4 @@ int PrintAncestors(IdNode *node); IdNode* LookdownId(IdNode *root, NodeType targetType, char *targetName); IdNode* LookupId(IdNode *node, IdNode *prev, char* target); -//IdStatus CheckIds(Node *root); - #endif /* WRAITH_IDENTCHECK_H */ -- 2.25.1