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$negate(Object input)
119 assert(input.type == INTEGER);
122 result.type = INTEGER;
123 result.instance.integer = -input.instance.integer;
127 Object builtin$add(Object left, Object right)
129 assert(left.type == INTEGER);
130 assert(right.type == INTEGER);
133 result.type = INTEGER;
134 result.instance.integer = left.instance.integer + right.instance.integer;
138 Object builtin$subtract(Object left, Object right)
140 assert(left.type == INTEGER);
141 assert(right.type == INTEGER);
144 result.type = INTEGER;
145 result.instance.integer = left.instance.integer - right.instance.integer;
149 Object builtin$multiply(Object left, Object right)
151 assert(left.type == INTEGER);
152 assert(right.type == INTEGER);
155 result.type = INTEGER;
156 result.instance.integer = left.instance.integer * right.instance.integer;
160 Object builtin$integerDivide(Object left, Object right)
162 assert(left.type == INTEGER);
163 assert(right.type == INTEGER);
166 result.type = INTEGER;
167 result.instance.integer = left.instance.integer / right.instance.integer;
171 Object builtin$modularDivide(Object left, Object right)
173 assert(left.type == INTEGER);
174 assert(right.type == INTEGER);
177 result.type = INTEGER;
178 result.instance.integer = left.instance.integer % right.instance.integer;
182 {% if 'pow' in builtins %}
183 Object builtin$pow(Object base, Object exponent)
185 assert(base.type == INTEGER);
186 assert(exponent.type == INTEGER);
189 result.type = INTEGER;
190 result.instance.integer = pow(base.instance.integer, exponent.instance.integer);
195 {% if 'print' in builtins %}
196 void builtin$print(Object output)
201 printf("%" PRId32, output.instance.integer);
205 // Using fwrite instead of printf to handle size_t length
206 fwrite(output.instance.string->characters, 1, output.instance.string->length, stdout);
215 int main(int argc, char** argv)
217 Runtime* runtime = Runtime_construct();
219 {% for statement in statements %}
223 Runtime_destruct(runtime);