Implemented closures
[fur] / templates / environment.c
1 struct _EnvironmentNode;
2 typedef struct _EnvironmentNode _EnvironmentNode;
3 struct _EnvironmentNode {
4   const char* symbol;
5   Object value;
6   _EnvironmentNode* next;
7 };
8
9 struct Environment {
10   size_t referenceCount;
11   Environment* shadowed;
12   _EnvironmentNode* top;
13 };
14
15 struct Environment_get_Result;
16 typedef struct Environment_get_Result Environment_get_Result;
17 struct Environment_get_Result {
18   bool found;
19   Object result;
20 };
21
22 void Environment_initialize(Environment* self, Environment* shadowed) {
23   self->referenceCount = 1;
24   self->shadowed = shadowed;
25   self->top = NULL;
26 }
27
28 void Environment_deinitialize(Environment* self) {
29   assert(self->referenceCount == 0);
30
31   while(self->top != NULL) {
32     _EnvironmentNode* en = self->top;
33     self->top = en->next;
34     Object_deinitialize(&(en->value));
35     free(en);
36   }
37 }
38
39 Environment* Environment_construct(Environment* shadowed) {
40   Environment* result = malloc(sizeof(Environment));
41   Environment_initialize(result, shadowed);
42   return result;
43 }
44
45 Environment* Environment_reference(Environment* self) {
46   self->referenceCount++; // TODO Do we need to make this thread safe?
47   return self;
48 }
49
50 void Environment_destruct(Environment* self) {
51   self->referenceCount--; // TODO Do we need to make this thread safe?
52   if(self->referenceCount == 0) {
53     Environment_deinitialize(self);
54     free(self);
55   }
56 }
57
58 Environment_get_Result Environment_getShallow(Environment* self, char* symbol) {
59   for(_EnvironmentNode* current = self->top; current != NULL; current = current->next) {
60     if(strcmp(current->symbol, symbol) == 0) {
61       return (Environment_get_Result) { true, current->value };
62     }
63   }
64   return (Environment_get_Result) { false, BUILTIN_NIL };
65 }
66
67 Environment_get_Result Environment_get(Environment* self, char* symbol) {
68   for(; self != NULL; self = self->shadowed) {
69     Environment_get_Result result = Environment_getShallow(self, symbol);
70     if(result.found) return result;
71   }
72   return (Environment_get_Result) { false, BUILTIN_NIL };
73 }
74
75 void Environment_set(Environment* self, char* symbol, Object value) {
76   assert(!(Environment_getShallow(self, symbol).found));
77
78   _EnvironmentNode* en = malloc(sizeof(_EnvironmentNode));
79   en->symbol = symbol;
80   en->value = value;
81   en->next = self->top;
82   self->top = en;
83 }