scope.c (3189B)
1 #include <assert.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include "expr.h" 5 #include "identifier.h" 6 #include "scope.h" 7 #include "util.h" 8 9 static uint32_t 10 name_hash(uint32_t init, const struct identifier *ident) 11 { 12 return fnv1a_s(init, ident->name); 13 } 14 15 struct scope * 16 scope_push(struct scope **stack, enum scope_class class) 17 { 18 struct scope *new = xcalloc(1, sizeof(struct scope)); 19 new->class = class; 20 new->next = &new->objects; 21 new->parent = *stack; 22 *stack = new; 23 return new; 24 } 25 26 struct scope * 27 scope_pop(struct scope **stack) 28 { 29 struct scope *prev = *stack; 30 assert(prev); 31 *stack = prev->parent; 32 return prev; 33 } 34 35 struct scope * 36 scope_lookup_ancestor(struct scope *scope, 37 enum scope_class class, const char *label) 38 { 39 // Implements the algorithm described by "Control statements" item 2, or 40 // 6.6.48.2 at the time of writing 41 while (scope) { 42 if (label && scope->label && strcmp(scope->label, label) == 0) { 43 break; 44 } else if (!label && scope->class == class) { 45 break; 46 } 47 scope = scope->parent; 48 } 49 50 if (scope && class != scope->class) { 51 assert(scope->class == SCOPE_COMPOUND); 52 scope = scope->parent; 53 if (scope->class != class) { 54 return NULL; 55 } 56 } 57 58 return scope; 59 } 60 61 void 62 scope_free(struct scope *scope) 63 { 64 if (!scope) { 65 return; 66 } 67 68 struct scope_object *obj = scope->objects; 69 while (obj) { 70 struct scope_object *next = obj->lnext; 71 free(obj); 72 obj = next; 73 } 74 75 free(scope); 76 } 77 78 void 79 scope_free_all(struct scopes *scopes) 80 { 81 while (scopes) { 82 struct scopes *next = scopes->next; 83 scope_free(scopes->scope); 84 free(scopes); 85 scopes = next; 86 } 87 } 88 89 void 90 scope_object_init(struct scope_object *object, enum object_type otype, 91 const struct identifier *ident, const struct identifier *name, 92 const struct type *type, struct expression *value) 93 { 94 identifier_dup(&object->ident, ident); 95 identifier_dup(&object->name, name); 96 object->otype = otype; 97 object->type = type; 98 object->value = value; 99 if (value) { 100 assert(otype == O_CONST); 101 assert(value->type == EXPR_CONSTANT); 102 } 103 const_refer(type, &object->type); 104 } 105 106 void 107 scope_insert_from_object(struct scope *scope, struct scope_object *object) 108 { 109 // Linked list 110 *scope->next = object; 111 scope->next = &object->lnext; 112 113 // Hash map 114 uint32_t hash = name_hash(FNV1A_INIT, &object->name); 115 struct scope_object **bucket = &scope->buckets[hash % SCOPE_BUCKETS]; 116 if (*bucket) { 117 object->mnext = *bucket; 118 } 119 *bucket = object; 120 } 121 122 struct scope_object * 123 scope_insert(struct scope *scope, enum object_type otype, 124 const struct identifier *ident, const struct identifier *name, 125 const struct type *type, struct expression *value) 126 { 127 struct scope_object *o = xcalloc(1, sizeof(struct scope_object)); 128 scope_object_init(o, otype, ident, name, type, value); 129 scope_insert_from_object(scope, o); 130 return o; 131 } 132 133 struct scope_object * 134 scope_lookup(struct scope *scope, const struct identifier *ident) 135 { 136 uint32_t hash = name_hash(FNV1A_INIT, ident); 137 struct scope_object *bucket = scope->buckets[hash % SCOPE_BUCKETS]; 138 while (bucket) { 139 if (identifier_eq(&bucket->name, ident)) { 140 return bucket; 141 } 142 bucket = bucket->mnext; 143 } 144 if (scope->parent) { 145 return scope_lookup(scope->parent, ident); 146 } 147 return NULL; 148 }