1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
#include "scope.h"
#include <stdlib.h>
#include <string.h>
#define DEFAULT_SIZE 16
static integral_t hash_name(const char* name, integral_t cap) {
integral_t hash = 0, i = 0;
while (name[i] != 0) ADVANCE_HASH(hash, name[i++], cap);
return hash;
}
static integral_t hash_type(const struct type_alias* type, integral_t cap) {
return hash_name(type->name, cap);
}
static bool type_eq(const struct type_alias* a, const struct type_alias* b) {
return strcmp(a->name, b->name) == 0;
}
static integral_t hash_var(const struct var_def* var, integral_t cap) {
return hash_name(var->name, cap);
}
static bool var_eq(const struct var_def* a, const struct var_def* b) {
return strcmp(a->name, b->name) == 0;
}
static void var_destroy(struct var_def* var) {
free(var->name);
}
static void scope_init(struct scope* scope) {
hm_init(
&scope->types,
(hm_hash_fn) hash_type,
(hm_eq_fn) type_eq,
NULL);
hm_init(
&scope->vars,
(hm_hash_fn) hash_var,
(hm_eq_fn) var_eq,
(hm_destroy_fn) var_destroy);
}
void scope_destroy(struct scope* scope) {
hm_destroy(&scope->types);
hm_destroy(&scope->vars);
}
void scope_push(struct scope** p_scope) {
struct scope* inner_scope = ccc_alloc(sizeof(struct scope));
scope_init(inner_scope);
inner_scope->next_out = *p_scope;
*p_scope = inner_scope;
}
void scope_pop(struct scope** p_scope) {
*p_scope = (*p_scope)->next_out;
}
bool scope_get_type(
const struct scope* scope,
const struct type_alias** p_entry,
const char* name
) {
for (; scope != NULL; scope = scope->next_out) {
const struct type_alias** cell = (const struct type_alias**) hm_cell_r(
&scope->types,
&(struct type_alias) { .name = name });
if (cell == NULL || *cell == NULL) continue;
if (p_entry != NULL) *p_entry = *cell;
return true;
}
return false;
}
const struct type_alias* scope_define_type(
struct scope* scope,
struct type_alias type
) {
struct type_alias** cell =
(struct type_alias**) hm_cell_w(&scope->types, &type);
/* redefinition leaks memory, so refuse */
if (*cell != NULL) return NULL;
*cell = ccc_alloc(sizeof(struct type_alias));
**cell = type;
return *cell;
}
bool scope_get_var(
const struct scope* scope,
struct var_def** p_entry,
const char* name
) {
for (; scope != NULL; scope = scope->next_out) {
struct var_def** cell = (struct var_def**) hm_cell_r(
&scope->vars,
&(struct var_def) {.name = (char*) name});
if (cell == NULL || *cell == NULL) continue;
if (p_entry != NULL) *p_entry = *cell;
return true;
}
return false;
}
struct var_def* scope_define_var(struct scope* scope, struct var_def var) {
struct var_def** cell = (struct var_def**) hm_cell_w(&scope->vars, &var);
/* redefinition leaks memory, so refuse */
if (*cell != NULL) return NULL;
if (*cell == NULL) *cell = ccc_alloc(sizeof(struct var_def));
**cell = var;
return *cell;
}
|