ecabb1758c1c5971b78265890884d5992a7964ad
[fur] / templates / program.c
1 #include <assert.h>
2 #include <inttypes.h>
3 #include <stdbool.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 {% for standard_library in standard_libraries %}
8 #include <{{standard_library}}>
9 {% endfor %}
10
11 struct String;
12 typedef struct String String;
13 enum Type;
14 typedef enum Type Type;
15 union Instance;
16 typedef union Instance Instance;
17 struct Object;
18 typedef struct Object Object;
19 struct Runtime;
20 typedef struct Runtime Runtime;
21
22 struct String
23 {
24   size_t length;
25   char* characters;
26 };
27
28 enum Type
29 {
30   INTEGER,
31   STRING
32 };
33
34 union Instance
35 {
36   int32_t integer;
37   String* string;
38 };
39
40 struct Object
41 {
42   Type type;
43   Instance instance;
44 };
45
46 struct Runtime
47 {
48   size_t permanentStringsLength;
49   size_t permanentStringsAllocated;
50   String** permanentStrings;
51 };
52
53 Runtime* Runtime_construct()
54 {
55   Runtime* result = malloc(sizeof(Runtime));
56   result->permanentStringsLength = 0;
57   result->permanentStringsAllocated = 0;
58   result->permanentStrings = NULL;
59   return result;
60 }
61
62 void Runtime_destruct(Runtime* self)
63 {
64   free(self->permanentStrings);
65   free(self);
66 }
67
68 void Runtime_addPermanentString(Runtime* self, String* string)
69 {
70   // TODO Make this function thread-safe
71   if(self->permanentStringsLength == self->permanentStringsAllocated)
72   {
73     if(self->permanentStringsAllocated == 0)
74     {
75       self->permanentStringsAllocated = 8;
76     }
77     else
78     {
79       self->permanentStringsAllocated = self->permanentStringsAllocated * 2;
80     }
81
82     self->permanentStrings = realloc(
83       self->permanentStrings,
84       sizeof(String*) * self->permanentStringsAllocated
85     );
86
87     // TODO Handle realloc returning NULL
88   }
89
90   self->permanentStrings[self->permanentStringsLength] = string;
91   self->permanentStringsLength++;
92 }
93
94 Object integerLiteral(int32_t literal)
95 {
96   Object result;
97   result.type = INTEGER;
98   result.instance.integer = literal;
99   return result;
100 }
101
102 Object stringLiteral(Runtime* runtime, const char* literal)
103 {
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);
109
110   Object result;
111   result.type = STRING;
112   result.instance.string = resultString;
113   return result;
114 }
115
116 {% if 'print' in builtins %}
117 void builtin$print(Object output)
118 {
119   switch(output.type)
120   {
121     case INTEGER:
122       printf("%" PRId32, output.instance.integer);
123       break;
124
125     case STRING:
126       // Using fwrite instead of printf to handle size_t length
127       fwrite(output.instance.string->characters, 1, output.instance.string->length, stdout);
128       break;
129
130     default:
131       assert(false);
132   }
133 }
134 {% endif %}
135
136 int main(int argc, char** argv)
137 {
138   Runtime* runtime = Runtime_construct();
139
140   {% for statement in statements %}
141   {{ statement }}
142   {% endfor %}
143
144   Runtime_destruct(runtime);
145
146   return 0;
147 }