7 {% for standard_library in standard_libraries %}
8 #include <{{standard_library}}>
12 typedef enum Type Type;
14 typedef union Instance Instance;
16 typedef struct Object Object;
17 struct EnvironmentNode;
18 typedef struct EnvironmentNode EnvironmentNode;
20 typedef struct Environment Environment;
22 const char* const STRING_LITERAL_LIST[] = {
23 {% for string_literal in string_literal_list %}
24 "{{ string_literal }}",
28 const char* const SYMBOL_LIST[] = {
29 {% for symbol in symbol_list %}
45 Object (*closure)(Environment*, size_t, Object*);
61 const Object FALSE = {
66 struct EnvironmentNode
70 EnvironmentNode* next;
75 size_t referenceCount;
77 EnvironmentNode* root;
80 Environment* Environment_construct(Environment* parent)
82 Environment* result = malloc(sizeof(Environment));
83 result->referenceCount = 1;
84 result->parent = parent;
89 void Environment_destruct(Environment* self)
91 self->referenceCount--;
93 if(self->referenceCount == 0)
95 EnvironmentNode* next;
96 for(EnvironmentNode* node = self->root; node != NULL; node = next)
98 // No objects are allocated on the heap (yet!) so we don't need to free anything else
106 // This need not be thread safe because environments exist on one thread only
107 void Environment_set(Environment* self, const char* const key, Object value)
109 EnvironmentNode* node = malloc(sizeof(EnvironmentNode));
112 node->next = self->root;
116 Object Environment_get(Environment* self, const char* const symbol)
118 for(EnvironmentNode* node = self->root; node != NULL; node = node->next)
120 // We can compare pointers because pointers are unique in the SYMBOL_LIST
121 if(node->key == symbol)
127 if(self->parent != NULL)
129 return Environment_get(self->parent, symbol);
132 // TODO Handle symbol errors
136 Object integerLiteral(int32_t literal)
139 result.type = INTEGER;
140 result.instance.integer = literal;
144 Object stringLiteral(const char* literal)
147 result.type = STRING;
148 result.instance.string = literal;
152 // TODO Make this conditionally added
153 Object operator$negate(Object input)
155 assert(input.type == INTEGER);
158 result.type = INTEGER;
159 result.instance.integer = -input.instance.integer;
163 {% for id in infix_declarations %}
164 Object operator${{ id.name }}(Object left, Object right)
166 assert(left.type == {{ id.in_type.upper() }});
167 assert(right.type == {{ id.in_type.upper() }});
170 result.type = {{ id.out_type.upper() }};
171 result.instance.{{ id.out_type.lower() }} = left.instance.{{ id.in_type.lower() }} {{ id.operator }} right.instance.{{ id.in_type.lower() }};
176 {% if 'pow' in builtins %}
177 Object builtin$pow$implementation(Environment* parent, size_t argc, Object* args)
181 Object base = args[0];
182 Object exponent = args[1];
184 assert(base.type == INTEGER);
185 assert(exponent.type == INTEGER);
188 result.type = INTEGER;
189 result.instance.integer = pow(base.instance.integer, exponent.instance.integer);
193 Object builtin$pow = { CLOSURE, (Instance)builtin$pow$implementation };
196 {% if 'print' in builtins %}
197 Object builtin$print$implementation(Environment* parent, size_t argc, Object* args)
199 for(size_t i = 0; i < argc; i++)
201 Object output = args[i];
205 fputs(output.instance.boolean ? "true" : "false", stdout);
209 printf("%" PRId32, output.instance.integer);
213 // Using fwrite instead of printf to handle size_t length
214 printf("%s", output.instance.string);
222 // TODO Return something better
226 Object builtin$print = { CLOSURE, (Instance)builtin$print$implementation };
229 {% for function_definition in function_definition_list %}
230 Object user${{function_definition.name}}$implementation(Environment* parent, size_t argc, Object* args)
232 Environment* environment = Environment_construct(parent);
234 {% for statement in function_definition.statement_list[:-1] %}
235 {{ generate_statement(statement) }}
238 Object result = {{ generate_statement(function_definition.statement_list[-1]) }}
239 Environment_destruct(environment);
243 Object user${{function_definition.name}} = { CLOSURE, (Instance)user${{function_definition.name}}$implementation };
246 int main(int argc, char** argv)
248 Environment* environment = Environment_construct(NULL);
250 // TODO Use the symbol from SYMBOL_LIST
251 {% for builtin in builtins %}
252 Environment_set(environment, "{{ builtin }}", builtin${{ builtin }});
255 {% for statement in statements %}
256 {{ generate_statement(statement) }}
259 Environment_destruct(environment);