7 {% for standard_library in standard_libraries %}
8 #include <{{standard_library}}>
12 typedef struct String String;
14 typedef enum Type Type;
16 typedef union Instance Instance;
18 typedef struct Object Object;
20 typedef struct Runtime Runtime;
22 const char * const SYMBOL_LIST[] = {
23 {% for symbol in symbol_list %}
53 const Object FALSE = {
58 struct EnvironmentNode;
59 typedef struct EnvironmentNode EnvironmentNode;
60 struct EnvironmentNode
64 EnvironmentNode* next;
68 typedef struct Environment Environment;
71 EnvironmentNode* root;
74 Environment* Environment_construct()
76 // TODO Handle malloc returning NULL
77 Environment* result = malloc(sizeof(Environment));
82 void Environment_destruct(Environment* self)
84 EnvironmentNode* next;
85 for(EnvironmentNode* node = self->root; node != NULL; node = next)
87 // We don't need to destruct the permanent strings, because those will be destructed at the end when the Runtime is destructed
88 // The above comment represents all heap-allocated objects currently, so we don't need to destruct Objects (yet)
94 // This need not be thread safe because environments exist on one thread only
95 void Environment_set(Environment* self, const char* const key, Object value)
97 EnvironmentNode* node = malloc(sizeof(EnvironmentNode));
100 node->next = self->root;
104 Object Environment_get(Environment* self, const char* const symbol)
106 for(EnvironmentNode* node = self->root; node != NULL; node = node->next)
108 // We can compare pointers because pointers are unique in the SYMBOLS_LIST
109 if(node->key == symbol)
115 // TODO Handle symbol errors
119 Object integerLiteral(int32_t literal)
122 result.type = INTEGER;
123 result.instance.integer = literal;
127 Object stringLiteral(char* literal)
130 result.type = STRING;
131 result.instance.string = literal;
135 // TODO Make this conditionally added
136 Object builtin$negate(Object input)
138 assert(input.type == INTEGER);
141 result.type = INTEGER;
142 result.instance.integer = -input.instance.integer;
146 Object builtin$add(Object left, Object right)
148 assert(left.type == INTEGER);
149 assert(right.type == INTEGER);
152 result.type = INTEGER;
153 result.instance.integer = left.instance.integer + right.instance.integer;
157 Object builtin$subtract(Object left, Object right)
159 assert(left.type == INTEGER);
160 assert(right.type == INTEGER);
163 result.type = INTEGER;
164 result.instance.integer = left.instance.integer - right.instance.integer;
168 Object builtin$multiply(Object left, Object right)
170 assert(left.type == INTEGER);
171 assert(right.type == INTEGER);
174 result.type = INTEGER;
175 result.instance.integer = left.instance.integer * right.instance.integer;
179 Object builtin$integerDivide(Object left, Object right)
181 assert(left.type == INTEGER);
182 assert(right.type == INTEGER);
185 result.type = INTEGER;
186 result.instance.integer = left.instance.integer / right.instance.integer;
190 Object builtin$modularDivide(Object left, Object right)
192 assert(left.type == INTEGER);
193 assert(right.type == INTEGER);
196 result.type = INTEGER;
197 result.instance.integer = left.instance.integer % right.instance.integer;
201 Object builtin$equals(Object left, Object right)
203 assert(left.type == INTEGER);
204 assert(right.type == INTEGER);
206 Object result = { BOOLEAN, left.instance.integer == right.instance.integer };
210 Object builtin$notEquals(Object left, Object right)
212 assert(left.type == INTEGER);
213 assert(right.type == INTEGER);
215 Object result = { BOOLEAN, left.instance.integer != right.instance.integer };
219 Object builtin$greaterThan(Object left, Object right)
221 assert(left.type == INTEGER);
222 assert(right.type == INTEGER);
224 Object result = { BOOLEAN, left.instance.integer > right.instance.integer };
228 Object builtin$lessThan(Object left, Object right)
230 assert(left.type == INTEGER);
231 assert(right.type == INTEGER);
233 Object result = { BOOLEAN, left.instance.integer < right.instance.integer };
237 Object builtin$greaterThanOrEqual(Object left, Object right)
239 assert(left.type == INTEGER);
240 assert(right.type == INTEGER);
242 Object result = { BOOLEAN, left.instance.integer >= right.instance.integer };
246 Object builtin$lessThanOrEqual(Object left, Object right)
248 assert(left.type == INTEGER);
249 assert(right.type == INTEGER);
251 Object result = { BOOLEAN, left.instance.integer <= right.instance.integer };
255 Object builtin$and(Object left, Object right)
257 assert(left.type == BOOLEAN);
258 assert(right.type == BOOLEAN);
260 Object result = { BOOLEAN, left.instance.boolean && right.instance.boolean };
264 Object builtin$or(Object left, Object right)
266 assert(left.type == BOOLEAN);
267 assert(right.type == BOOLEAN);
269 Object result = { BOOLEAN, left.instance.boolean || right.instance.boolean };
273 {% if 'pow' in builtins %}
274 Object builtin$pow(Object base, Object exponent)
276 assert(base.type == INTEGER);
277 assert(exponent.type == INTEGER);
280 result.type = INTEGER;
281 result.instance.integer = pow(base.instance.integer, exponent.instance.integer);
286 {% if 'print' in builtins %}
287 void builtin$print(Object output)
292 fputs(output.instance.boolean ? "true" : "false", stdout);
296 printf("%" PRId32, output.instance.integer);
300 // Using fwrite instead of printf to handle size_t length
301 printf("%s", output.instance.string);
310 int main(int argc, char** argv)
312 Environment* environment = Environment_construct();
314 {% for statement in statements %}
318 Environment_destruct(environment);