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
118
119
120
121
122
123
124
125
126
127
128
129
|
#include "scope.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define DEFAULT_SIZE 16
static void scope_init(struct scope* scope) {
scope->types = calloc(DEFAULT_SIZE, sizeof(struct type_def*));
scope->type_cap = DEFAULT_SIZE;
scope->vars = calloc(DEFAULT_SIZE, sizeof(struct var_def*));
scope->var_cap = DEFAULT_SIZE;
}
static void scope_destroy(struct scope* scope) {
for (unsigned long long i = 0; i < scope->type_cap; i++) {
if (scope->types[i] != NULL) free(scope->types[i]);
}
free(scope->types);
for (unsigned long long i = 0; i < scope->var_cap; i++) {
if (scope->vars[i] != NULL) free(scope->vars[i]);
}
free(scope->vars);
}
unsigned long long hash_name(const char* name) {
unsigned long long hash = 0, i = 0;
while (name[i] != 0) hash = (hash << 5) - hash + name[i++];
return hash;
}
static struct type_def** type_cell(
const struct scope* scope,
const char* name
) {
unsigned long long orig_idx = hash_name(name) % scope->type_cap;
unsigned long long idx = orig_idx;
do {
if (scope->types[idx] == NULL
|| strcmp(name, scope->types[idx]->name) == 0)
return &scope->types[idx];
} while ((idx = (idx + 1) % scope->type_cap) != orig_idx);
/* TODO: rehashing :'( */
fprintf(stderr, "ccc: would have to rehash and I don't wanna\n");
exit(1);
}
static struct var_def** var_cell(
const struct scope* scope,
const char* name
) {
unsigned long long orig_idx = hash_name(name) % scope->var_cap;
unsigned long long idx = orig_idx;
do {
if (scope->vars[idx] == NULL
|| strcmp(name, scope->vars[idx]->name) == 0)
return &scope->vars[idx];
} while ((idx = (idx + 1) % scope->var_cap) != orig_idx);
/* TODO: rehashing :'( */
fprintf(stderr, "ccc: would have to rehash and I don't wanna\n");
exit(1);
}
void scope_push(struct scope** p_scope) {
struct scope* inner_scope = calloc(1, sizeof(struct scope));
scope_init(inner_scope);
inner_scope->next_out = *p_scope;
*p_scope = inner_scope;
}
void scope_pop(struct scope** p_scope) {
struct scope* discarded_scope = *p_scope;
*p_scope = (*p_scope)->next_out;
scope_destroy(discarded_scope);
free(discarded_scope);
}
bool scope_get_type(
const struct scope* scope,
struct type_def* p_entry,
const char* name
) {
struct type_def* type_def = *type_cell(scope, name);
if (type_def == NULL) return false;
*p_entry = *type_def;
return true;
}
void scope_define_type(struct scope* scope, struct type_def type) {
struct type_def** cell = type_cell(scope, type.name);
if (*cell != NULL) {
fprintf(stderr, "ccc: error: redefined type %s\n", type.name);
exit(1);
}
*cell = calloc(1, sizeof(struct type_def));
if (*cell == NULL) {
fprintf(stderr, "ccc: out of memory\n");
exit(1);
}
**cell = type;
}
bool scope_get_var(
const struct scope* scope,
struct var_def* p_entry,
const char* name
) {
struct var_def* var_def = *var_cell(scope, name);
if (var_def == NULL) return false;
*p_entry = *var_def;
return true;
}
void scope_define_var(struct scope* scope, struct var_def var) {
struct var_def** cell = var_cell(scope, var.name);
if (*cell == NULL) {
*cell = calloc(1, sizeof(struct var_def));
if (*cell == NULL) {
fprintf(stderr, "ccc: out of memory\n");
exit(1);
}
}
/* technically C allows redefinition :/ */
**cell = var;
}
|