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;
48 size_t permanentStringsLength;
49 size_t permanentStringsAllocated;
50 String** permanentStrings;
53 Runtime* Runtime_construct()
55 Runtime* result = malloc(sizeof(Runtime));
56 result->permanentStringsLength = 0;
57 result->permanentStringsAllocated = 0;
58 result->permanentStrings = NULL;
62 void Runtime_destruct(Runtime* self)
64 free(self->permanentStrings);
68 void Runtime_addPermanentString(Runtime* self, String* string)
70 // TODO Make this function thread-safe
71 if(self->permanentStringsLength == self->permanentStringsAllocated)
73 if(self->permanentStringsAllocated == 0)
75 self->permanentStringsAllocated = 8;
79 self->permanentStringsAllocated = self->permanentStringsAllocated * 2;
82 self->permanentStrings = realloc(
83 self->permanentStrings,
84 sizeof(String*) * self->permanentStringsAllocated
87 // TODO Handle realloc returning NULL
90 self->permanentStrings[self->permanentStringsLength] = string;
91 self->permanentStringsLength++;
94 Object integerLiteral(int32_t literal)
97 result.type = INTEGER;
98 result.instance.integer = literal;
102 Object stringLiteral(Runtime* runtime, const char* literal)
104 String* resultString = malloc(sizeof(String));
105 resultString->length = strlen(literal);
106 resultString->characters = malloc(resultString->length);
107 memcpy(resultString->characters, literal, resultString->length);
108 Runtime_addPermanentString(runtime, resultString);
111 result.type = STRING;
112 result.instance.string = resultString;
116 // TODO Make this conditionally added
117 Object builtin$add(Object left, Object right)
119 assert(left.type == INTEGER);
120 assert(right.type == INTEGER);
123 result.type = INTEGER;
124 result.instance.integer = left.instance.integer + right.instance.integer;
128 Object builtin$subtract(Object left, Object right)
130 assert(left.type == INTEGER);
131 assert(right.type == INTEGER);
134 result.type = INTEGER;
135 result.instance.integer = left.instance.integer - right.instance.integer;
139 Object builtin$multiply(Object left, Object right)
141 assert(left.type == INTEGER);
142 assert(right.type == INTEGER);
145 result.type = INTEGER;
146 result.instance.integer = left.instance.integer * right.instance.integer;
150 Object builtin$integerDivide(Object left, Object right)
152 assert(left.type == INTEGER);
153 assert(right.type == INTEGER);
156 result.type = INTEGER;
157 result.instance.integer = left.instance.integer / right.instance.integer;
161 Object builtin$modularDivide(Object left, Object right)
163 assert(left.type == INTEGER);
164 assert(right.type == INTEGER);
167 result.type = INTEGER;
168 result.instance.integer = left.instance.integer % right.instance.integer;
172 {% if 'print' in builtins %}
173 void builtin$print(Object output)
178 printf("%" PRId32, output.instance.integer);
182 // Using fwrite instead of printf to handle size_t length
183 fwrite(output.instance.string->characters, 1, output.instance.string->length, stdout);
192 int main(int argc, char** argv)
194 Runtime* runtime = Runtime_construct();
196 {% for statement in statements %}
200 Runtime_destruct(runtime);