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;
18 const char* const STRING_LITERAL_LIST[] = {
19 {% for string_literal in string_literal_list %}
20 "{{ string_literal }}",
24 const char* const SYMBOL_LIST[] = {
25 {% for symbol in symbol_list %}
55 const Object FALSE = {
60 struct EnvironmentNode;
61 typedef struct EnvironmentNode EnvironmentNode;
62 struct EnvironmentNode
66 EnvironmentNode* next;
70 typedef struct Environment Environment;
73 EnvironmentNode* root;
76 Environment* Environment_construct()
78 // TODO Handle malloc returning NULL
79 Environment* result = malloc(sizeof(Environment));
84 void Environment_destruct(Environment* self)
86 EnvironmentNode* next;
87 for(EnvironmentNode* node = self->root; node != NULL; node = next)
89 // No objects are allocated on the heap (yet!) so we don't need to free anything else
95 // This need not be thread safe because environments exist on one thread only
96 void Environment_set(Environment* self, const char* const key, Object value)
98 EnvironmentNode* node = malloc(sizeof(EnvironmentNode));
101 node->next = self->root;
105 Object Environment_get(Environment* self, const char* const symbol)
107 for(EnvironmentNode* node = self->root; node != NULL; node = node->next)
109 // We can compare pointers because pointers are unique in the SYMBOL_LIST
110 if(node->key == symbol)
116 // TODO Handle symbol errors
120 Object integerLiteral(int32_t literal)
123 result.type = INTEGER;
124 result.instance.integer = literal;
128 Object stringLiteral(const char* literal)
131 result.type = STRING;
132 result.instance.string = literal;
136 // TODO Make this conditionally added
137 Object builtin$negate(Object input)
139 assert(input.type == INTEGER);
142 result.type = INTEGER;
143 result.instance.integer = -input.instance.integer;
147 Object builtin$add(Object left, Object right)
149 assert(left.type == INTEGER);
150 assert(right.type == INTEGER);
153 result.type = INTEGER;
154 result.instance.integer = left.instance.integer + right.instance.integer;
158 Object builtin$subtract(Object left, Object right)
160 assert(left.type == INTEGER);
161 assert(right.type == INTEGER);
164 result.type = INTEGER;
165 result.instance.integer = left.instance.integer - right.instance.integer;
169 Object builtin$multiply(Object left, Object right)
171 assert(left.type == INTEGER);
172 assert(right.type == INTEGER);
175 result.type = INTEGER;
176 result.instance.integer = left.instance.integer * right.instance.integer;
180 Object builtin$integerDivide(Object left, Object right)
182 assert(left.type == INTEGER);
183 assert(right.type == INTEGER);
186 result.type = INTEGER;
187 result.instance.integer = left.instance.integer / right.instance.integer;
191 Object builtin$modularDivide(Object left, Object right)
193 assert(left.type == INTEGER);
194 assert(right.type == INTEGER);
197 result.type = INTEGER;
198 result.instance.integer = left.instance.integer % right.instance.integer;
202 Object builtin$equals(Object left, Object right)
204 assert(left.type == INTEGER);
205 assert(right.type == INTEGER);
207 Object result = { BOOLEAN, left.instance.integer == right.instance.integer };
211 Object builtin$notEquals(Object left, Object right)
213 assert(left.type == INTEGER);
214 assert(right.type == INTEGER);
216 Object result = { BOOLEAN, left.instance.integer != right.instance.integer };
220 Object builtin$greaterThan(Object left, Object right)
222 assert(left.type == INTEGER);
223 assert(right.type == INTEGER);
225 Object result = { BOOLEAN, left.instance.integer > right.instance.integer };
229 Object builtin$lessThan(Object left, Object right)
231 assert(left.type == INTEGER);
232 assert(right.type == INTEGER);
234 Object result = { BOOLEAN, left.instance.integer < right.instance.integer };
238 Object builtin$greaterThanOrEqual(Object left, Object right)
240 assert(left.type == INTEGER);
241 assert(right.type == INTEGER);
243 Object result = { BOOLEAN, left.instance.integer >= right.instance.integer };
247 Object builtin$lessThanOrEqual(Object left, Object right)
249 assert(left.type == INTEGER);
250 assert(right.type == INTEGER);
252 Object result = { BOOLEAN, left.instance.integer <= right.instance.integer };
256 Object builtin$and(Object left, Object right)
258 assert(left.type == BOOLEAN);
259 assert(right.type == BOOLEAN);
261 Object result = { BOOLEAN, left.instance.boolean && right.instance.boolean };
265 Object builtin$or(Object left, Object right)
267 assert(left.type == BOOLEAN);
268 assert(right.type == BOOLEAN);
270 Object result = { BOOLEAN, left.instance.boolean || right.instance.boolean };
274 {% if 'pow' in builtins %}
275 Object builtin$pow(size_t argc, Object args[])
279 Object base = args[0];
280 Object exponent = args[1];
282 assert(base.type == INTEGER);
283 assert(exponent.type == INTEGER);
286 result.type = INTEGER;
287 result.instance.integer = pow(base.instance.integer, exponent.instance.integer);
292 {% if 'print' in builtins %}
293 void builtin$print(size_t argc, Object args[])
295 for(size_t i = 0; i < argc; i++)
297 Object output = args[i];
301 fputs(output.instance.boolean ? "true" : "false", stdout);
305 printf("%" PRId32, output.instance.integer);
309 // Using fwrite instead of printf to handle size_t length
310 printf("%s", output.instance.string);
320 int main(int argc, char** argv)
322 Environment* environment = Environment_construct();
324 {% for statement in statements %}
328 Environment_destruct(environment);