X-Git-Url: https://code.kerkeslager.com/?p=fur;a=blobdiff_plain;f=templates%2Fprogram.c;h=f8095bf838a3934733e628d67976060c69109054;hp=25f9acbf4820f7b3b392c458751460668033dff5;hb=3a076cfd2c46c9f3b51815facd613445722a340b;hpb=61733d6070859e6a639ae4b34faec9aacca52a29 diff --git a/templates/program.c b/templates/program.c index 25f9acb..f8095bf 100644 --- a/templates/program.c +++ b/templates/program.c @@ -67,7 +67,7 @@ typedef struct Closure Closure; struct Closure { Environment* closed; - Object (*call)(EnvironmentPool*, Environment*, size_t, Stack*, jmp_buf); + Object (*call)(EnvironmentPool*, Environment*, size_t, Stack*, const unsigned long, jmp_buf); }; struct List; @@ -573,20 +573,105 @@ Object stringLiteral(const char* literal) return result; } -// TODO Make this conditionally added -Object operator$negate(Object input) +{% if 'pow' in builtins %} +Object builtin$pow$implementation( + EnvironmentPool* environmentPool, + Environment* parent, + size_t argc, + Stack* stack, + const unsigned long line, + jmp_buf parentJump) { - assert(input.type == INTEGER); + // Must unload items in reverse order + Object exponent = Stack_pop(stack); + Object base = Stack_pop(stack); + + assert(base.type == INTEGER); + assert(exponent.type == INTEGER); Object result; result.type = INTEGER; - result.instance.integer = -input.instance.integer; + result.instance.integer = pow(base.instance.integer, exponent.instance.integer); return result; } -// TODO Make this conditionally added -Object operator$concatenate(Stack* stack, jmp_buf parentJump, size_t line) +Object builtin$pow = { CLOSURE, (Instance)(Closure){ NULL, builtin$pow$implementation } }; +{% endif %} + +Object builtin$negate$implementation( + EnvironmentPool* environmentPool, + Environment* parent, + size_t argc, + Stack* stack, + const unsigned long line, + jmp_buf parentJump) +{ + assert(argc == 1); + + Object argument = Stack_pop(stack); + + assert(argument.type == INTEGER); + + Object result = (Object){ + INTEGER, + (Instance)(int32_t) (-argument.instance.integer) + }; + + return result; +} +Object builtin$negate = { CLOSURE, (Instance)(Closure){ NULL, builtin$negate$implementation } }; + +{% for op in ['lt', 'gt', 'lte', 'gte', 'eq', 'neq'] %} +Object builtin${{ op }}$implementation( + EnvironmentPool* environmentPool, + Environment* parent, + size_t argc, + Stack* stack, + const unsigned long line, + jmp_buf parentJump) +{ + assert(argc == 2); + + Object right = Stack_pop(stack); + Object left = Stack_pop(stack); + + assert(left.type == INTEGER); + assert(right.type == INTEGER); + + {% if op == 'lt' %} + if(left.instance.integer < right.instance.integer) + {% elif op == 'gt' %} + if(left.instance.integer > right.instance.integer) + {% elif op == 'lte' %} + if(left.instance.integer <= right.instance.integer) + {% elif op == 'gte' %} + if(left.instance.integer >= right.instance.integer) + {% elif op == 'eq' %} + if(left.instance.integer == right.instance.integer) + {% elif op == 'neq' %} + if(left.instance.integer != right.instance.integer) + {% endif %} + { + return builtin$true; + } + else + { + return builtin$false; + } +} +Object builtin${{ op }} = { CLOSURE, (Instance)(Closure){ NULL, builtin${{ op }}$implementation } }; +{% endfor %} + +Object builtin$concat$implementation( + EnvironmentPool* environmentPool, + Environment* parent, + size_t argc, + Stack* stack, + const unsigned long line, + jmp_buf parentJump) { + assert(argc == 2); + Object right = Stack_pop(stack); Object left = Stack_pop(stack); @@ -616,52 +701,195 @@ Object operator$concatenate(Stack* stack, jmp_buf parentJump, size_t line) Object result = { STRING_CONCATENATION, (Instance)concatenation }; return result; } +Object builtin$concat = { CLOSURE, (Instance)(Closure){ NULL, builtin$concat$implementation } }; -{% for id in infix_declarations %} -Object operator${{ id.name }}(Stack* stack, jmp_buf parentJump, size_t line) +Object builtin$add$implementation( + EnvironmentPool* environmentPool, + Environment* parent, + size_t argc, + Stack* stack, + const unsigned long line, + jmp_buf parentJump) { + assert(argc == 2); + + Object right = Stack_pop(stack); + Object left = Stack_pop(stack); + + assert(left.type == INTEGER); + assert(right.type == INTEGER); + + Object result = (Object){ + INTEGER, + (Instance)(int32_t) (left.instance.integer + right.instance.integer) + }; + + return result; +} +Object builtin$add = { CLOSURE, (Instance)(Closure){ NULL, builtin$add$implementation } }; + +Object builtin$subtract$implementation( + EnvironmentPool* environmentPool, + Environment* parent, + size_t argc, + Stack* stack, + const unsigned long line, + jmp_buf parentJump) +{ + assert(argc == 2); + + Object right = Stack_pop(stack); + Object left = Stack_pop(stack); + + assert(left.type == INTEGER); + assert(right.type == INTEGER); + + Object result = (Object){ + INTEGER, + (Instance)(int32_t) (left.instance.integer - right.instance.integer) + }; + + return result; +} +Object builtin$subtract = { CLOSURE, (Instance)(Closure){ NULL, builtin$subtract$implementation } }; + +Object builtin$multiply$implementation( + EnvironmentPool* environmentPool, + Environment* parent, + size_t argc, + Stack* stack, + const unsigned long line, + jmp_buf parentJump) +{ + assert(argc == 2); + Object right = Stack_pop(stack); Object left = Stack_pop(stack); - assert(left.type == {{ id.in_type.upper() }}); - assert(right.type == {{ id.in_type.upper() }}); + assert(left.type == INTEGER); + assert(right.type == INTEGER); + + Object result = (Object){ + INTEGER, + (Instance)(int32_t) (left.instance.integer * right.instance.integer) + }; + + return result; +} +Object builtin$multiply = { CLOSURE, (Instance)(Closure){ NULL, builtin$multiply$implementation } }; + +Object builtin$integer_divide$implementation( + EnvironmentPool* environmentPool, + Environment* parent, + size_t argc, + Stack* stack, + const unsigned long line, + jmp_buf parentJump) +{ + assert(argc == 2); + + Object right = Stack_pop(stack); + Object left = Stack_pop(stack); + + assert(left.type == INTEGER); + assert(right.type == INTEGER); - {% if id.name == 'integerDivide' or id.name == 'modularDivide' %} if(right.instance.integer == 0) { fprintf(stderr, "DivisionByZeroError on line %zu\n", line); longjmp(parentJump, 1); } - {% endif %} - Object result; - result.type = {{ id.out_type.upper() }}; - result.instance.{{ id.out_type.lower() }} = left.instance.{{ id.in_type.lower() }} {{ id.operator }} right.instance.{{ id.in_type.lower() }}; + Object result = (Object){ + INTEGER, + (Instance)(int32_t) (left.instance.integer / right.instance.integer) + }; + return result; } -{% endfor %} +Object builtin$integer_divide = { CLOSURE, (Instance)(Closure){ NULL, builtin$integer_divide$implementation } }; -{% if 'pow' in builtins %} -Object builtin$pow$implementation(EnvironmentPool* environmentPool, Environment* parent, size_t argc, Stack* stack, jmp_buf parentJump) +Object builtin$modular_divide$implementation( + EnvironmentPool* environmentPool, + Environment* parent, + size_t argc, + Stack* stack, + const unsigned long line, + jmp_buf parentJump) { - // Must unload items in reverse order - Object exponent = Stack_pop(stack); - Object base = Stack_pop(stack); + assert(argc == 2); - assert(base.type == INTEGER); - assert(exponent.type == INTEGER); + Object right = Stack_pop(stack); + Object left = Stack_pop(stack); + + assert(left.type == INTEGER); + assert(right.type == INTEGER); + + if(right.instance.integer == 0) + { + fprintf(stderr, "DivisionByZeroError on line %zu\n", line); + longjmp(parentJump, 1); + } + + Object result = (Object){ + INTEGER, + (Instance)(int32_t) (left.instance.integer % right.instance.integer) + }; - Object result; - result.type = INTEGER; - result.instance.integer = pow(base.instance.integer, exponent.instance.integer); return result; } +Object builtin$modular_divide = { CLOSURE, (Instance)(Closure){ NULL, builtin$modular_divide$implementation } }; -Object builtin$pow = { CLOSURE, (Instance)(Closure){ NULL, builtin$pow$implementation } }; -{% endif %} +Object builtin$field$implementation( + EnvironmentPool* environmentPool, + Environment* parent, + size_t argc, + Stack* stack, + const unsigned long line, + jmp_buf parentJump) +{ + assert(argc == 2); + + Object right = Stack_pop(stack); + Object left = Stack_pop(stack); + + assert(left.type == STRUCTURE); + assert(right.type == STRING_LITERAL); + + Object result = (Object){ + INTEGER, + (Instance)(int32_t) (left.instance.integer % right.instance.integer) + }; + + return result; +} +Object builtin$field = { CLOSURE, (Instance)(Closure){ NULL, builtin$field$implementation } }; + +Object builtin$get$implementation( + EnvironmentPool* environmentPool, + Environment* parent, + size_t argc, + Stack* stack, + const unsigned long line, + jmp_buf parentJump) +{ + assert(argc == 2); + + Object right = Stack_pop(stack); + Object left = Stack_pop(stack); + + return List_get(&left, right); +} +Object builtin$get = { CLOSURE, (Instance)(Closure){ NULL, builtin$get$implementation } }; {% if 'print' in builtins %} -Object builtin$print$implementation(EnvironmentPool* environmentPool, Environment* parent, size_t argc, Stack* stack, jmp_buf parentJump) +Object builtin$print$implementation( + EnvironmentPool* environmentPool, + Environment* parent, + size_t argc, + Stack* stack, + const unsigned long line, + jmp_buf parentJump) { Stack reverse_stack; Stack_initialize(&reverse_stack); @@ -691,9 +919,9 @@ Object builtin$print$implementation(EnvironmentPool* environmentPool, Environmen case STRING_CONCATENATION: Stack_push(stack, output.instance.string_concatenation->left); - builtin$print$implementation(NULL, NULL, 1, stack, parentJump); + builtin$print$implementation(NULL, NULL, 1, stack, line, parentJump); Stack_push(stack, output.instance.string_concatenation->right); - builtin$print$implementation(NULL, NULL, 1, stack, parentJump); + builtin$print$implementation(NULL, NULL, 1, stack, line, parentJump); break; case STRING_LITERAL: @@ -753,6 +981,22 @@ int main(int argc, char** argv) Environment_set(environment, "{{ builtin }}", builtin${{ builtin }}); {% endfor %} + Environment_set(environment, "true", builtin$true); + Environment_set(environment, "false", builtin$false); + Environment_set(environment, "__add__", builtin$add); + Environment_set(environment, "__subtract__", builtin$subtract); + Environment_set(environment, "__multiply__", builtin$multiply); + Environment_set(environment, "__integer_divide__", builtin$integer_divide); + Environment_set(environment, "__modular_divide__", builtin$modular_divide); + Environment_set(environment, "__negate__", builtin$negate); + Environment_set(environment, "__concat__", builtin$concat); + Environment_set(environment, "__field__", builtin$field); + Environment_set(environment, "__get__", builtin$get); + + {% for op in ['lt', 'gt', 'lte', 'gte', 'eq', 'neq'] %} + Environment_set(environment, "__{{ op }}__", builtin${{ op }}); + {% endfor %} + {% for statement in statements %} {{ statement }} {% endfor %}