Reimplements identifier lookup to work over the AST
							parent
							
								
									ece20a99b5
								
							
						
					
					
						commit
						e3fc2826ea
					
				
							
								
								
									
										207
									
								
								src/ast.c
								
								
								
								
							
							
						
						
									
										207
									
								
								src/ast.c
								
								
								
								
							|  | @ -1,5 +1,6 @@ | ||||||
| #include "ast.h" | #include "ast.h" | ||||||
| 
 | 
 | ||||||
|  | #include <stdbool.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| 
 | 
 | ||||||
|  | @ -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); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -373,7 +373,10 @@ const char *SyntaxKindString(SyntaxKind syntaxKind); | ||||||
|  * function in all other cases. */ |  * function in all other cases. */ | ||||||
| void Recurse(Node *node, void (*func)(Node*)); | void Recurse(Node *node, void (*func)(Node*)); | ||||||
| 
 | 
 | ||||||
|  | void LinkParentPointers(Node *node); | ||||||
|  | 
 | ||||||
| TypeTag *MakeTypeTag(Node *node); | TypeTag *MakeTypeTag(Node *node); | ||||||
| char *TypeTagToString(TypeTag *tag); | char *TypeTagToString(TypeTag *tag); | ||||||
| 
 | 
 | ||||||
|  | Node *LookupIdNode(Node *current, Node *prev, char *target); | ||||||
| #endif /* WRAITH_AST_H */ | #endif /* WRAITH_AST_H */ | ||||||
|  |  | ||||||
|  | @ -187,7 +187,7 @@ IdNode *MakeIdTree(Node *astNode, IdNode *parent) | ||||||
|     { |     { | ||||||
|         char *name = astNode->identifier.name; |         char *name = astNode->identifier.name; | ||||||
|         mainNode = MakeIdNode(Placeholder, name, parent); |         mainNode = MakeIdNode(Placeholder, name, parent); | ||||||
|         IdNode *lookupNode = LookupId(mainNode, NULL, name); |         Node *lookupNode = LookupIdNode(astNode, NULL, name); | ||||||
|         if (lookupNode == NULL) |         if (lookupNode == NULL) | ||||||
|         { |         { | ||||||
|             fprintf(stderr, "wraith: Could not find IdNode for id %s\n", name); |             fprintf(stderr, "wraith: Could not find IdNode for id %s\n", name); | ||||||
|  |  | ||||||
|  | @ -86,6 +86,7 @@ int main(int argc, char *argv[]) | ||||||
|                 } |                 } | ||||||
|                 else |                 else | ||||||
|                 { |                 { | ||||||
|  |                     LinkParentPointers(rootNode); | ||||||
|                     { |                     { | ||||||
|                         IdNode *idTree = MakeIdTree(rootNode, NULL); |                         IdNode *idTree = MakeIdTree(rootNode, NULL); | ||||||
|                         printf("\n"); |                         printf("\n"); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue