X-Git-Url: https://code.kerkeslager.com/?a=blobdiff_plain;f=templates%2Fprogram.c;h=73d9334c8b9176907aeee46ca7868bc65e9a7295;hb=6e7ba75736ca8b463a263e7d58aa8f6bff62faaf;hp=3b65e02bedb7c64d95164e19696721159b907209;hpb=1131ab0f3fb9ebec5c42d7fcb7f4bc8088386900;p=fur diff --git a/templates/program.c b/templates/program.c index 3b65e02..73d9334 100644 --- a/templates/program.c +++ b/templates/program.c @@ -8,18 +8,20 @@ #include <{{standard_library}}> {% endfor %} -struct String; -typedef struct String String; enum Type; typedef enum Type Type; union Instance; typedef union Instance Instance; struct Object; typedef struct Object Object; -struct Runtime; -typedef struct Runtime Runtime; -const char * const SYMBOL_LIST[] = { +const char* const STRING_LITERAL_LIST[] = { +{% for string_literal in string_literal_list %} + "{{ string_literal }}", +{% endfor %} +}; + +const char* const SYMBOL_LIST[] = { {% for symbol in symbol_list %} "{{ symbol }}", {% endfor %} @@ -28,6 +30,7 @@ const char * const SYMBOL_LIST[] = { enum Type { BOOLEAN, + CLOSURE, INTEGER, STRING }; @@ -35,8 +38,9 @@ enum Type union Instance { bool boolean; + Object (*closure)(size_t, Object*); int32_t integer; - char* string; + const char* string; }; struct Object @@ -84,8 +88,7 @@ void Environment_destruct(Environment* self) EnvironmentNode* next; for(EnvironmentNode* node = self->root; node != NULL; node = next) { - // We don't need to destruct the permanent strings, because those will be destructed at the end when the Runtime is destructed - // The above comment represents all heap-allocated objects currently, so we don't need to destruct Objects (yet) + // No objects are allocated on the heap (yet!) so we don't need to free anything else next = node->next; free(node); } @@ -105,7 +108,7 @@ Object Environment_get(Environment* self, const char* const symbol) { for(EnvironmentNode* node = self->root; node != NULL; node = node->next) { - // We can compare pointers because pointers are unique in the SYMBOLS_LIST + // We can compare pointers because pointers are unique in the SYMBOL_LIST if(node->key == symbol) { return node->value; @@ -116,55 +119,6 @@ Object Environment_get(Environment* self, const char* const symbol) assert(false); } - -struct Runtime -{ - size_t permanentStringsLength; - size_t permanentStringsAllocated; - char** permanentStrings; -}; - -Runtime* Runtime_construct() -{ - Runtime* result = malloc(sizeof(Runtime)); - result->permanentStringsLength = 0; - result->permanentStringsAllocated = 0; - result->permanentStrings = NULL; - return result; -} - -void Runtime_destruct(Runtime* self) -{ - free(self->permanentStrings); - free(self); -} - -void Runtime_addPermanentString(Runtime* self, char* const string) -{ - // TODO Make this function thread-safe - if(self->permanentStringsLength == self->permanentStringsAllocated) - { - if(self->permanentStringsAllocated == 0) - { - self->permanentStringsAllocated = 8; - } - else - { - self->permanentStringsAllocated = self->permanentStringsAllocated * 2; - } - - self->permanentStrings = realloc( - self->permanentStrings, - sizeof(char* const) * self->permanentStringsAllocated - ); - - // TODO Handle realloc returning NULL - } - - self->permanentStrings[self->permanentStringsLength] = string; - self->permanentStringsLength++; -} - Object integerLiteral(int32_t literal) { Object result; @@ -173,10 +127,8 @@ Object integerLiteral(int32_t literal) return result; } -Object stringLiteral(Runtime* runtime, char* literal) +Object stringLiteral(const char* literal) { - Runtime_addPermanentString(runtime, literal); - Object result; result.type = STRING; result.instance.string = literal; @@ -184,7 +136,7 @@ Object stringLiteral(Runtime* runtime, char* literal) } // TODO Make this conditionally added -Object builtin$negate(Object input) +Object operator$negate(Object input) { assert(input.type == INTEGER); @@ -194,7 +146,7 @@ Object builtin$negate(Object input) return result; } -Object builtin$add(Object left, Object right) +Object operator$add(Object left, Object right) { assert(left.type == INTEGER); assert(right.type == INTEGER); @@ -205,7 +157,7 @@ Object builtin$add(Object left, Object right) return result; } -Object builtin$subtract(Object left, Object right) +Object operator$subtract(Object left, Object right) { assert(left.type == INTEGER); assert(right.type == INTEGER); @@ -216,7 +168,7 @@ Object builtin$subtract(Object left, Object right) return result; } -Object builtin$multiply(Object left, Object right) +Object operator$multiply(Object left, Object right) { assert(left.type == INTEGER); assert(right.type == INTEGER); @@ -227,7 +179,7 @@ Object builtin$multiply(Object left, Object right) return result; } -Object builtin$integerDivide(Object left, Object right) +Object operator$integerDivide(Object left, Object right) { assert(left.type == INTEGER); assert(right.type == INTEGER); @@ -238,7 +190,7 @@ Object builtin$integerDivide(Object left, Object right) return result; } -Object builtin$modularDivide(Object left, Object right) +Object operator$modularDivide(Object left, Object right) { assert(left.type == INTEGER); assert(right.type == INTEGER); @@ -249,7 +201,7 @@ Object builtin$modularDivide(Object left, Object right) return result; } -Object builtin$equals(Object left, Object right) +Object operator$equals(Object left, Object right) { assert(left.type == INTEGER); assert(right.type == INTEGER); @@ -258,7 +210,7 @@ Object builtin$equals(Object left, Object right) return result; } -Object builtin$notEquals(Object left, Object right) +Object operator$notEquals(Object left, Object right) { assert(left.type == INTEGER); assert(right.type == INTEGER); @@ -267,7 +219,7 @@ Object builtin$notEquals(Object left, Object right) return result; } -Object builtin$greaterThan(Object left, Object right) +Object operator$greaterThan(Object left, Object right) { assert(left.type == INTEGER); assert(right.type == INTEGER); @@ -276,7 +228,7 @@ Object builtin$greaterThan(Object left, Object right) return result; } -Object builtin$lessThan(Object left, Object right) +Object operator$lessThan(Object left, Object right) { assert(left.type == INTEGER); assert(right.type == INTEGER); @@ -285,7 +237,7 @@ Object builtin$lessThan(Object left, Object right) return result; } -Object builtin$greaterThanOrEqual(Object left, Object right) +Object operator$greaterThanOrEqual(Object left, Object right) { assert(left.type == INTEGER); assert(right.type == INTEGER); @@ -294,7 +246,7 @@ Object builtin$greaterThanOrEqual(Object left, Object right) return result; } -Object builtin$lessThanOrEqual(Object left, Object right) +Object operator$lessThanOrEqual(Object left, Object right) { assert(left.type == INTEGER); assert(right.type == INTEGER); @@ -303,7 +255,7 @@ Object builtin$lessThanOrEqual(Object left, Object right) return result; } -Object builtin$and(Object left, Object right) +Object operator$and(Object left, Object right) { assert(left.type == BOOLEAN); assert(right.type == BOOLEAN); @@ -312,7 +264,7 @@ Object builtin$and(Object left, Object right) return result; } -Object builtin$or(Object left, Object right) +Object operator$or(Object left, Object right) { assert(left.type == BOOLEAN); assert(right.type == BOOLEAN); @@ -322,8 +274,13 @@ Object builtin$or(Object left, Object right) } {% if 'pow' in builtins %} -Object builtin$pow(Object base, Object exponent) +Object builtin$pow$implementation(size_t argc, Object* args) { + assert(argc == 2); + + Object base = args[0]; + Object exponent = args[1]; + assert(base.type == INTEGER); assert(exponent.type == INTEGER); @@ -332,43 +289,74 @@ Object builtin$pow(Object base, Object exponent) result.instance.integer = pow(base.instance.integer, exponent.instance.integer); return result; } + +Object builtin$pow = { CLOSURE, (Instance)builtin$pow$implementation }; {% endif %} {% if 'print' in builtins %} -void builtin$print(Object output) +Object builtin$print$implementation(size_t argc, Object* args) { - switch(output.type) + for(size_t i = 0; i < argc; i++) { - case BOOLEAN: - fputs(output.instance.boolean ? "true" : "false", stdout); - break; + Object output = args[i]; + switch(output.type) + { + case BOOLEAN: + fputs(output.instance.boolean ? "true" : "false", stdout); + break; - case INTEGER: - printf("%" PRId32, output.instance.integer); - break; + case INTEGER: + printf("%" PRId32, output.instance.integer); + break; - case STRING: - // Using fwrite instead of printf to handle size_t length - printf("%s", output.instance.string); - break; + case STRING: + // Using fwrite instead of printf to handle size_t length + printf("%s", output.instance.string); + break; - default: - assert(false); + default: + assert(false); + } } + + // TODO Return something better + return FALSE; } + +Object builtin$print = { CLOSURE, (Instance)builtin$print$implementation }; {% endif %} +{% for function_definition in function_definition_list %} +Object user${{function_definition.name}}$implementation(size_t argc, Object* args) +{ + Environment* environment = Environment_construct(); + + {% for statement in function_definition.statement_list %} + {{ generate_statement(statement) }} + {% endfor %} + + Object result = {{ generate_statement(function_definition.statement_list[-1]) }} + Environment_destruct(environment); + return result; +} + +Object user${{function_definition.name}} = { CLOSURE, (Instance)user${{function_definition.name}}$implementation }; +{% endfor %} + int main(int argc, char** argv) { - Runtime* runtime = Runtime_construct(); Environment* environment = Environment_construct(); + // TODO Use the symbol from SYMBOL_LIST + {% for builtin in builtins %} + Environment_set(environment, "{{ builtin }}", builtin${{ builtin }}); + {% endfor %} + {% for statement in statements %} - {{ statement }} + {{ generate_statement(statement) }} {% endfor %} Environment_destruct(environment); - Runtime_destruct(runtime); return 0; }