diff --git a/src/lexer/lex.l b/src/lexer/lex.l index 5c1c944..261e976 100644 --- a/src/lexer/lex.l +++ b/src/lexer/lex.l @@ -97,7 +97,7 @@ int yywrap(void * unused_param) { return TOKEN_STRING; } -((([0-9]+(\.[0-9]+)?)|(\.[0-9]+))(e((\-|\+)?([0-9]+)))?) { +((([0-9]+(\.[0-9]+)?)|(\.[0-9]+))((e|E)((\-|\+)?([0-9]+)))?) { return TOKEN_NUMBER; } @@ -113,7 +113,7 @@ int yywrap(void * unused_param) { #[^\n]* { /* skip comment */ } -.|((([0-9]+(\.[0-9]+)?)|(\.[0-9]+))(e((\-|\+)?([0-9]+(\.[0-9]+)?)))?) { +.|((([0-9]+(\.[0-9]+)?)|(\.[0-9]+))((e|E)((\-|\+)?([0-9]+(\.[0-9]+)?)))?) { return TOKEN_INVALID; } %% \ No newline at end of file diff --git a/src/parser/number/number.c b/src/parser/number/number.c index 9e0fba9..cb96bd5 100644 --- a/src/parser/number/number.c +++ b/src/parser/number/number.c @@ -24,7 +24,7 @@ int parse_exponent(const char *exp_str, long *exp_val) { return 0; } -int mpq_set_decimal_str_exp(mpq_t r, const char *str) { +int mpq_set_decimal_str_exp(mpq_t r, const char *str, size_t len) { // Skip leading whitespace while (isspace(*str)) str++; @@ -39,11 +39,11 @@ int mpq_set_decimal_str_exp(mpq_t r, const char *str) { } // Copy input to a buffer for manipulation - size_t len = strlen(str); char *buf = malloc(len + 1); if (!buf) return -1; - strcpy(buf, str); + memcpy(buf, str, len); + buf[len] = '\0'; // Find 'e' or 'E' char *e_ptr = strchr(buf, 'e'); @@ -178,7 +178,7 @@ ParsedValueReturn parse_number(Token *token, char *path) { parsedValue->type = AST_NUMBER; mpq_t *r_ptr = malloc(sizeof(mpq_t)); mpq_init(*r_ptr); - int err = mpq_set_decimal_str_exp(*r_ptr, token->value); + int err = mpq_set_decimal_str_exp(*r_ptr, token->value, token->length); if (err) { free_parsed(parsedValue); free(parsedValue); diff --git a/src/parser/number/number.h b/src/parser/number/number.h index 49fe708..1b18a86 100644 --- a/src/parser/number/number.h +++ b/src/parser/number/number.h @@ -12,4 +12,6 @@ // Function declaration for parsing an identifier ParsedValueReturn parse_number(Token *token, char*path); +int mpq_set_decimal_str_exp(mpq_t r, const char *str, size_t len); + #endif // NUMBER_H \ No newline at end of file diff --git a/src/parser/operations/operations.c b/src/parser/operations/operations.c index 80c0f1d..43b8782 100644 --- a/src/parser/operations/operations.c +++ b/src/parser/operations/operations.c @@ -12,18 +12,22 @@ #include #include +struct operation {}; + ParsedValue convert_to_operation(DArray *to_operate_on, DArray *operations) { if (to_operate_on->size == 1) { return *((ParsedValue *)darray_get(to_operate_on, 0)); } - ArTokenType operation = 0; + ArTokenType operation_type = 0; + Token operation = {}; DArray positions; for (size_t i = 0; i < operations->size; i++) { - ArTokenType *current_operation = darray_get(operations, i); - if (operation < *current_operation) { - if (operation != 0) { + Token *current_operation = darray_get(operations, i); + if (operation_type < current_operation->type) { + if (operation_type != 0) { darray_free(&positions, NULL); } + operation_type = current_operation->type; operation = *current_operation; darray_init(&positions, sizeof(size_t)); } @@ -33,7 +37,10 @@ ParsedValue convert_to_operation(DArray *to_operate_on, DArray *operations) { parsedValue.type = AST_OPERATION; ParsedOperation *operationStruct = checked_malloc(sizeof(ParsedOperation)); parsedValue.data = operationStruct; - operationStruct->operation = operation; + operationStruct->operation = operation_type; + operationStruct->line = operation.line; + operationStruct->column = operation.column; + operationStruct->length = operation.length; darray_init(&operationStruct->to_operate_on, sizeof(ParsedValue)); size_t last_position = 0; size_t to_operate_on_last_position = 0; @@ -68,7 +75,7 @@ ParsedValueReturn parse_operations(char *file, DArray *tokens, size_t *index, free(first_parsed_value); DArray operations; - darray_init(&operations, sizeof(ArTokenType)); + darray_init(&operations, sizeof(Token)); while (tokens->size > *index) { bool to_break = false; @@ -81,7 +88,7 @@ ParsedValueReturn parse_operations(char *file, DArray *tokens, size_t *index, } if (to_break) break; - darray_push(&operations, &token->type); + darray_push(&operations, token); (*index)++; ArErr err = error_if_finished(file, tokens, index); if (err.exists) { diff --git a/src/parser/operations/operations.h b/src/parser/operations/operations.h index 856c5e5..f38bcd9 100644 --- a/src/parser/operations/operations.h +++ b/src/parser/operations/operations.h @@ -12,6 +12,9 @@ typedef struct { ArTokenType operation; DArray to_operate_on; // ParsedValue[] + size_t line; + size_t column; + size_t length; } ParsedOperation; ParsedValueReturn parse_operations(char *file, DArray *tokens, size_t *index, diff --git a/src/runtime/objects/number/number.c b/src/runtime/objects/number/number.c index 5e0160e..e4c3acb 100644 --- a/src/runtime/objects/number/number.c +++ b/src/runtime/objects/number/number.c @@ -14,6 +14,8 @@ ArgonObject *ARGON_NUMBER_TYPE; +#include "../../call/call.h" +#include "../literals/literals.h" #include #include #include @@ -23,6 +25,82 @@ ArgonObject *ARGON_NUMBER_TYPE; /* change SIGNIFICANT_DIGITS to taste (15 mimics double-ish behaviour) */ #define SIGNIFICANT_DIGITS 15 +ArgonObject *ARGON_NUMBER_TYPE___new__(size_t argc, ArgonObject **argv, + ArErr *err, RuntimeState *state) { + if (argc != 2) { + *err = create_err(0, 0, 0, "", "Runtime Error", + "__new__ expects 2 arguments, got %" PRIu64, argc); + return ARGON_NULL; + } + ArgonObject *self = argv[0]; + ArgonObject *object = argv[1]; + + self->type = TYPE_STRING; + ArgonObject *boolean_convert_method = get_field_for_class( + get_field(object, "__class__", false, false), "__number__", object); + if (boolean_convert_method) { + ArgonObject *boolean_object = + argon_call(boolean_convert_method, 0, NULL, err, state); + if (err->exists) + return ARGON_NULL; + return boolean_object; + } + ArgonObject *type_name = get_field_for_class( + get_field(object, "__class__", false, false), "__name__", object); + *err = create_err( + 0, 0, 0, "", "Runtime Error", "cannot convert type '%.*s' to number", + type_name->value.as_str.length, type_name->value.as_str.data); + return ARGON_NULL; +} + +ArgonObject *ARGON_NUMBER_TYPE___number__(size_t argc, ArgonObject **argv, + ArErr *err, RuntimeState *state) { + (void)state; + if (argc != 1) { + *err = create_err(0, 0, 0, "", "Runtime Error", + "__number__ expects 1 arguments, got %" PRIu64, argc); + return ARGON_NULL; + } + return argv[0]; +} + +ArgonObject *ARGON_NUMBER_TYPE___boolean__(size_t argc, ArgonObject **argv, + ArErr *err, RuntimeState *state) { + (void)state; + if (argc != 1) { + *err = create_err(0, 0, 0, "", "Runtime Error", + "__boolean__ expects 1 arguments, got %" PRIu64, argc); + return ARGON_NULL; + } + return mpq_cmp_si(*argv[0]->value.as_number, 0, 1) == 0 ? ARGON_FALSE + : ARGON_TRUE; +} + +ArgonObject *ARGON_NUMBER_TYPE___add__(size_t argc, ArgonObject **argv, + ArErr *err, RuntimeState *state) { + (void)state; + if (argc != 2) { + *err = create_err(0, 0, 0, "", "Runtime Error", + "__add__ expects 2 arguments, got %" PRIu64, argc); + return ARGON_NULL; + } + mpq_t r; + mpq_init(r); + if (argv[1]->type != TYPE_NUMBER) { + ArgonObject *type_name = get_field_for_class( + get_field(argv[1], "__class__", false, false), "__name__", argv[1]); + *err = create_err(0, 0, 0, "", "Runtime Error", + "__add__ cannot perform addition between number and %.*s", + type_name->value.as_str.length, + type_name->value.as_str.data); + return ARGON_NULL; + } + mpq_add(r, *argv[0]->value.as_number, *argv[1]->value.as_number); + ArgonObject *result = new_number_object(r); + mpq_clear(r); + return result; +} + ArgonObject *ARGON_NUMBER_TYPE___string__(size_t argc, ArgonObject **argv, ArErr *err, RuntimeState *state) { (void)state; @@ -181,6 +259,17 @@ void create_ARGON_NUMBER_TYPE() { add_field( ARGON_NUMBER_TYPE, "__string__", create_argon_native_function("__string__", ARGON_NUMBER_TYPE___string__)); + add_field(ARGON_NUMBER_TYPE, "__new__", + create_argon_native_function("__new__", ARGON_NUMBER_TYPE___new__)); + add_field( + ARGON_NUMBER_TYPE, "__number__", + create_argon_native_function("__number__", ARGON_NUMBER_TYPE___number__)); + add_field(ARGON_NUMBER_TYPE, "__boolean__", + create_argon_native_function("__boolean__", + ARGON_NUMBER_TYPE___boolean__)); + add_field(ARGON_NUMBER_TYPE, "__add__", + create_argon_native_function("__add__", + ARGON_NUMBER_TYPE___add__)); } void mpz_init_gc_managed(mpz_t z, size_t limbs_count) { @@ -228,12 +317,34 @@ ArgonObject *new_number_object(mpq_t number) { return object; } +ArgonObject *new_number_object_from_long(long n, unsigned long d) { + ArgonObject *object = new_object(); + add_field(object, "__class__", ARGON_NUMBER_TYPE); + mpq_t r; + mpq_init(r); + mpq_set_si(r, n, d); + object->type = TYPE_NUMBER; + object->value.as_number = mpq_new_gc_from(r); + mpq_clear(r); + return object; +} + +ArgonObject *new_number_object_from_double(double d) { + ArgonObject *object = new_object(); + add_field(object, "__class__", ARGON_NUMBER_TYPE); + mpq_t r; + mpq_init(r); + mpq_set_d(r, d); + object->type = TYPE_NUMBER; + object->value.as_number = mpq_new_gc_from(r); + mpq_clear(r); + return object; +} + void load_number(Translated *translated, RuntimeState *state) { uint8_t to_register = pop_byte(translated, state); size_t num_size = pop_bytecode(translated, state); size_t num_pos = pop_bytecode(translated, state); - size_t den_size = pop_bytecode(translated, state); - size_t den_pos = pop_bytecode(translated, state); mpq_t r; mpq_init(r); mpz_t num; @@ -242,13 +353,22 @@ void load_number(Translated *translated, RuntimeState *state) { arena_get(&translated->constants, num_pos)); mpq_set_num(r, num); mpz_clear(num); - mpz_t den; - mpz_init(den); - mpz_import(den, den_size, 1, 1, 0, 0, - arena_get(&translated->constants, den_pos)); - mpq_set_den(r, den); - mpz_clear(den); + + bool is_int = pop_byte(translated, state); + + if (!is_int) { + size_t den_size = pop_bytecode(translated, state); + size_t den_pos = pop_bytecode(translated, state); + mpz_t den; + mpz_init(den); + mpz_import(den, den_size, 1, 1, 0, 0, + arena_get(&translated->constants, den_pos)); + mpq_set_den(r, den); + mpz_clear(den); + } else { + mpz_set_si(mpq_denref(r), 1); + } state->registers[to_register] = new_number_object(r); mpq_clear(r); -} +} \ No newline at end of file diff --git a/src/runtime/objects/number/number.h b/src/runtime/objects/number/number.h index 4864749..62f5d03 100644 --- a/src/runtime/objects/number/number.h +++ b/src/runtime/objects/number/number.h @@ -16,4 +16,8 @@ ArgonObject *new_number_object(mpq_t number); void load_number(Translated *translated, RuntimeState *state); +ArgonObject *new_number_object_from_double(double d); + +ArgonObject *new_number_object_from_long(long n, unsigned long d); + #endif // RUNTIME_NUMBER_H \ No newline at end of file diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index 5f47fce..708495f 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -7,6 +7,7 @@ #include "runtime.h" #include "../err.h" #include "../hash_data/hash_data.h" +#include "../parser/number/number.h" #include "../translator/translator.h" #include "access/access.h" #include "call/call.h" @@ -21,6 +22,7 @@ #include "objects/type/type.h" #include #include +#include #include #include #include @@ -32,13 +34,39 @@ ArgonObject *ARGON_METHOD_TYPE; Stack *Global_Scope = NULL; ArgonObject *ACCESS_FUNCTION; +ArgonObject *ADDITION_FUNCTION; + +ArgonObject *ARGON_ADDITION_FUNCTION(size_t argc, ArgonObject **argv, + ArErr *err, RuntimeState *state) { + if (argc < 1) { + *err = create_err(0, 0, 0, "", "Runtime Error", + "add expects at least 1 argument, got %" PRIu64, argc); + return ARGON_NULL; + } + ArgonObject *output = argv[0]; + for (size_t i = 1; i < argc; i++) { + ArgonObject *__add__ = get_field_for_class( + get_field(output, "__class__", false, false), "__add__", output); + if (!__add__) { + ArgonObject *cls___name__ = get_field(output, "__name__", true, false); + *err = create_err(0, 0, 0, "", "Runtime Error", + "Object '%.*s' is missing __add__ method", + (int)cls___name__->value.as_str.length, + cls___name__->value.as_str.data); + return ARGON_NULL; + } + output = argon_call(__add__, 1, (ArgonObject *[]){argv[i]}, err, state); + } + return output; +} ArgonObject *ARGON_TYPE_TYPE___call__(size_t argc, ArgonObject **argv, ArErr *err, RuntimeState *state) { (void)state; if (argc < 1) { - *err = create_err(0, 0, 0, "", "Runtime Error", - "__call__ expects at least 1 argument, got 0"); + *err = + create_err(0, 0, 0, "", "Runtime Error", + "__call__ expects at least 1 argument, got %" PRIu64, argc); return ARGON_NULL; } ArgonObject *cls = argv[0]; @@ -85,6 +113,20 @@ ArgonObject *ARGON_TYPE_TYPE___call__(size_t argc, ArgonObject **argv, return new_object; } +ArgonObject *BASE_CLASS_address(size_t argc, ArgonObject **argv, ArErr *err, + RuntimeState *state) { + (void)state; + if (argc < 1) { + *err = + create_err(0, 0, 0, "", "Runtime Error", + "__new__ expects at least 1 argument, got %" PRIu64, argc); + return ARGON_NULL; + } + char buffer[32]; + snprintf(buffer, sizeof(buffer), "%p", argv[0]); + return new_string_object_null_terminated(buffer); +} + ArgonObject *BASE_CLASS___new__(size_t argc, ArgonObject **argv, ArErr *err, RuntimeState *state) { (void)state; @@ -134,6 +176,17 @@ ArgonObject *BASE_CLASS___string__(size_t argc, ArgonObject **argv, ArErr *err, return new_string_object_null_terminated(buffer); } +ArgonObject *BASE_CLASS___boolean__(size_t argc, ArgonObject **argv, ArErr *err, + RuntimeState *state) { + (void)argv; + (void)state; + if (argc != 1) { + *err = create_err(0, 0, 0, "", "Runtime Error", + "__boolean__ expects 1 arguments, got %" PRIu64, argc); + } + return ARGON_TRUE; +} + ArgonObject *ARGON_STRING_TYPE___init__(size_t argc, ArgonObject **argv, ArErr *err, RuntimeState *state) { if (argc != 2) { @@ -167,7 +220,7 @@ ArgonObject *ARGON_BOOL_TYPE___new__(size_t argc, ArgonObject **argv, ArErr *err, RuntimeState *state) { if (argc != 2) { *err = create_err(0, 0, 0, "", "Runtime Error", - "__init__ expects 2 arguments, got %" PRIu64, argc); + "__new__ expects 2 arguments, got %" PRIu64, argc); return ARGON_NULL; } ArgonObject *self = argv[0]; @@ -183,7 +236,12 @@ ArgonObject *ARGON_BOOL_TYPE___new__(size_t argc, ArgonObject **argv, return ARGON_NULL; return boolean_object; } - return ARGON_TRUE; + ArgonObject *type_name = get_field_for_class( + get_field(object, "__class__", false, false), "__name__", object); + *err = create_err( + 0, 0, 0, "", "Runtime Error", "cannot convert type '%.*s' to bool", + type_name->value.as_str.length, type_name->value.as_str.data); + return ARGON_NULL; } ArgonObject *ARGON_STRING_TYPE___string__(size_t argc, ArgonObject **argv, @@ -196,6 +254,30 @@ ArgonObject *ARGON_STRING_TYPE___string__(size_t argc, ArgonObject **argv, return argv[0]; } +ArgonObject *ARGON_STRING_TYPE___number__(size_t argc, ArgonObject **argv, + ArErr *err, RuntimeState *state) { + (void)state; + if (argc != 1) { + *err = create_err(0, 0, 0, "", "Runtime Error", + "__number__ expects 1 arguments, got %" PRIu64, argc); + return ARGON_NULL; + } + + mpq_t r; + mpq_init(r); + int result = mpq_set_decimal_str_exp(r, argv[0]->value.as_str.data, + argv[0]->value.as_str.length); + if (result != 0) { + mpq_clear(r); + *err = create_err(0, 0, 0, "", "Runtime Error", "Unable to parse number", + argc); + return ARGON_NULL; + } + ArgonObject *object = new_number_object(r); + mpq_clear(r); + return object; +} + ArgonObject *ARGON_STRING_TYPE___boolean__(size_t argc, ArgonObject **argv, ArErr *err, RuntimeState *state) { (void)state; @@ -216,6 +298,37 @@ ArgonObject *ARGON_BOOL_TYPE___boolean__(size_t argc, ArgonObject **argv, return argv[0]; } +ArgonObject *ARGON_NULL_TYPE___boolean__(size_t argc, ArgonObject **argv, + ArErr *err, RuntimeState *state) { + (void)argv; + (void)state; + if (argc != 1) { + *err = create_err(0, 0, 0, "", "Runtime Error", + "__boolean__ expects 1 arguments, got %" PRIu64, argc); + } + return ARGON_FALSE; +} +ArgonObject *ARGON_NULL_TYPE___number__(size_t argc, ArgonObject **argv, + ArErr *err, RuntimeState *state) { + (void)argv; + (void)state; + if (argc != 1) { + *err = create_err(0, 0, 0, "", "Runtime Error", + "__boolean__ expects 1 arguments, got %" PRIu64, argc); + } + return new_number_object_from_long(0, 1); +} +ArgonObject *ARGON_NULL_TYPE___string__(size_t argc, ArgonObject **argv, + ArErr *err, RuntimeState *state) { + (void)argv; + (void)state; + if (argc != 1) { + *err = create_err(0, 0, 0, "", "Runtime Error", + "__boolean__ expects 1 arguments, got %" PRIu64, argc); + } + return new_string_object_null_terminated("null"); +} + void bootstrap_types() { BASE_CLASS = new_object(); ARGON_TYPE_TYPE = new_object(); @@ -264,6 +377,8 @@ void bootstrap_types() { add_field(BASE_CLASS, "__new__", create_argon_native_function("__new__", BASE_CLASS___new__)); + add_field(BASE_CLASS, "address", + create_argon_native_function("address", BASE_CLASS_address)); add_field(BASE_CLASS, "__init__", create_argon_native_function("__init__", BASE_CLASS___new__)); add_field(BASE_CLASS, "__string__", @@ -273,6 +388,18 @@ void bootstrap_types() { add_field( ARGON_STRING_TYPE, "__init__", create_argon_native_function("__init__", ARGON_STRING_TYPE___init__)); + add_field( + ARGON_STRING_TYPE, "__number__", + create_argon_native_function("__number__", ARGON_STRING_TYPE___number__)); + add_field( + ARGON_NULL_TYPE, "__boolean__", + create_argon_native_function("__boolean__", ARGON_NULL_TYPE___boolean__)); + add_field( + ARGON_NULL_TYPE, "__string__", + create_argon_native_function("__string__", ARGON_NULL_TYPE___string__)); + add_field( + ARGON_NULL_TYPE, "__number__", + create_argon_native_function("__number__", ARGON_NULL_TYPE___number__)); add_field( ARGON_STRING_TYPE, "__string__", create_argon_native_function("__string__", ARGON_STRING_TYPE___string__)); @@ -284,8 +411,14 @@ void bootstrap_types() { add_field(ARGON_STRING_TYPE, "__boolean__", create_argon_native_function("__boolean__", ARGON_STRING_TYPE___boolean__)); - ACCESS_FUNCTION = create_argon_native_function("ACCESS_FUNCTION", + add_field( + BASE_CLASS, "__boolean__", + create_argon_native_function("__boolean__", BASE_CLASS___boolean__)); + ACCESS_FUNCTION = create_argon_native_function("__get_attr__", ARGON_TYPE_TYPE___get_attr__); + ADDITION_FUNCTION = + create_argon_native_function("add", ARGON_ADDITION_FUNCTION); + add_field(BASE_CLASS, "__get_attr__", ACCESS_FUNCTION); } void add_to_scope(Stack *stack, char *name, ArgonObject *value) { @@ -300,6 +433,8 @@ void bootstrap_globals() { add_to_scope(Global_Scope, "string", ARGON_STRING_TYPE); add_to_scope(Global_Scope, "type", ARGON_TYPE_TYPE); add_to_scope(Global_Scope, "boolean", ARGON_BOOL_TYPE); + add_to_scope(Global_Scope, "number", ARGON_NUMBER_TYPE); + add_to_scope(Global_Scope, "add", ADDITION_FUNCTION); ArgonObject *argon_term = new_object(); add_field(argon_term, "__init__", ARGON_NULL); @@ -387,7 +522,7 @@ ArErr run_instruction(Translated *translated, RuntimeState *state, load_const(translated, state); break; case OP_LOAD_NUMBER: - load_number(translated,state); + load_number(translated, state); break; case OP_LOAD_FUNCTION: load_argon_function(translated, state, *stack); @@ -489,6 +624,9 @@ ArErr run_instruction(Translated *translated, RuntimeState *state, case OP_LOAD_ACCESS_FUNCTION: state->registers[0] = ACCESS_FUNCTION; break; + case OP_LOAD_ADDITION_FUNCTION: + state->registers[0] = ADDITION_FUNCTION; + break; default: return create_err(0, 0, 0, NULL, "Runtime Error", "Invalid Opcode %#x", opcode); diff --git a/src/translator/bytecode_spec.md b/src/translator/bytecode_spec.md index 77a0102..61c7292 100644 --- a/src/translator/bytecode_spec.md +++ b/src/translator/bytecode_spec.md @@ -98,7 +98,7 @@ initialises a call instance struct and arguments buffer. ## OP_CALL -call a function with args +call the function at the head of the call instance stack, then pops it off the stack. ## OP_SOURCE_LOCATION @@ -125,12 +125,10 @@ loads a mpq_t number into memory 1. the register to write to. (*) 3. the size of the numerator in the constant buffer. 4. the offset in the constant buffer of the numerator. +5. is integer. (*) 3. the size of the denominator in the constant buffer. 4. the offset in the constant buffer of the denominator. -## OP_SWAP_REGISTERS +## OP_LOAD_ADDITION_FUNCTION -swap the contents in two registers - -1. register a (*) -2. register b (*) \ No newline at end of file +loads the addition function into register 1 \ No newline at end of file diff --git a/src/translator/number/number.c b/src/translator/number/number.c index 31fdf03..2355c18 100644 --- a/src/translator/number/number.c +++ b/src/translator/number/number.c @@ -13,30 +13,27 @@ size_t translate_parsed_number(Translated *translated, mpq_t *number, size_t to_register) { - mpz_t num, den; - mpz_init(num); - mpz_init(den); - mpz_set(num, mpq_numref(*number)); - mpz_set(den, mpq_denref(*number)); - size_t num_size; - void *num_data = mpz_export(NULL, &num_size, 1, 1, 0, 0, num); - size_t numerator_pos = arena_push(&translated->constants, num_data, num_size); - free(num_data); - mpz_clear(num); - // Export denominator - size_t den_size; - void *den_data = mpz_export(NULL, &den_size, 1, 1, 0, 0, den); - size_t denominator_pos = - arena_push(&translated->constants, den_data, den_size); - free(den_data); - mpz_clear(den); set_registers(translated, to_register + 1); - size_t start = push_instruction_byte(translated, OP_LOAD_NUMBER); push_instruction_byte(translated, to_register); + size_t num_size; + void *num_data = mpz_export(NULL, &num_size, 1, 1, 0, 0, mpq_numref(*number)); + size_t numerator_pos = arena_push(&translated->constants, num_data, num_size); + free(num_data); push_instruction_code(translated, num_size); push_instruction_code(translated, numerator_pos); - push_instruction_code(translated, den_size); - push_instruction_code(translated, denominator_pos); + bool is_int = mpz_cmp_ui(mpq_denref(*number), 1) == 0; + push_instruction_byte(translated, is_int); + if (!is_int) { + // Export denominator + size_t den_size; + void *den_data = + mpz_export(NULL, &den_size, 1, 1, 0, 0, mpq_denref(*number)); + size_t denominator_pos = + arena_push(&translated->constants, den_data, den_size); + free(den_data); + push_instruction_code(translated, den_size); + push_instruction_code(translated, denominator_pos); + } return start; } \ No newline at end of file diff --git a/src/translator/operation/operation.c b/src/translator/operation/operation.c new file mode 100644 index 0000000..847d26a --- /dev/null +++ b/src/translator/operation/operation.c @@ -0,0 +1,29 @@ +/* + * SPDX-FileCopyrightText: 2025 William Bell + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#include "operation.h" +#include + +size_t translate_operation(Translated *translated, ParsedOperation *operation, + ArErr *err) { + set_registers(translated, 1); + uint64_t first = push_instruction_byte(translated, OP_LOAD_ADDITION_FUNCTION); + push_instruction_byte(translated, OP_INIT_CALL); + push_instruction_code(translated, operation->to_operate_on.size); + + for (size_t i = 0; i < operation->to_operate_on.size; i++) { + translate_parsed(translated, darray_get(&operation->to_operate_on, i), err); + push_instruction_byte(translated, OP_INSERT_ARG); + push_instruction_code(translated, i); + } + + push_instruction_byte(translated, OP_SOURCE_LOCATION); + push_instruction_code(translated, operation->line); + push_instruction_code(translated, operation->column); + push_instruction_code(translated, operation->length); + push_instruction_byte(translated, OP_CALL); + return first; +} \ No newline at end of file diff --git a/src/translator/operation/operation.h b/src/translator/operation/operation.h new file mode 100644 index 0000000..c34f2b6 --- /dev/null +++ b/src/translator/operation/operation.h @@ -0,0 +1,15 @@ +/* + * SPDX-FileCopyrightText: 2025 William Bell + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#ifndef BYTECODE_OPERATION_H +#define BYTECODE_OPERATION_H +#include "../translator.h" +#include "../../parser/operations/operations.h" + +size_t translate_operation(Translated *translated, ParsedOperation *operation, + ArErr *err); + +#endif \ No newline at end of file diff --git a/src/translator/translator.c b/src/translator/translator.c index 9328d1b..0e76a3c 100644 --- a/src/translator/translator.c +++ b/src/translator/translator.c @@ -6,16 +6,17 @@ #include "translator.h" #include "../hash_data/hash_data.h" -#include "declaration/declaration.h" +#include "access/access.h" #include "call/call.h" +#include "declaration/declaration.h" #include "dowrap/dowrap.h" #include "function/function.h" #include "identifier/identifier.h" #include "if/if.h" #include "number/number.h" -#include "string/string.h" +#include "operation/operation.h" #include "return/return.h" -#include "access/access.h" +#include "string/string.h" #include #include #include @@ -79,11 +80,11 @@ size_t arena_push(ConstantArena *arena, const void *data, size_t length) { return offset; } -Translated init_translator(char* path) { +Translated init_translator(char *path) { Translated translated; translated.path = path; translated.registerCount = 1; - translated.return_jumps=NULL; + translated.return_jumps = NULL; darray_init(&translated.bytecode, sizeof(uint8_t)); arena_init(&translated.constants); return translated; @@ -118,7 +119,8 @@ void set_registers(Translated *translator, uint8_t count) { translator->registerCount = count; } -size_t translate_parsed(Translated *translated, ParsedValue *parsedValue, ArErr*err) { +size_t translate_parsed(Translated *translated, ParsedValue *parsedValue, + ArErr *err) { switch (parsedValue->type) { case AST_STRING: return translate_parsed_string(translated, @@ -127,7 +129,7 @@ size_t translate_parsed(Translated *translated, ParsedValue *parsedValue, ArErr* return translate_parsed_declaration(translated, *((DArray *)parsedValue->data), err); case AST_NUMBER: - return translate_parsed_number(translated, (mpq_t*)parsedValue->data, 0); + return translate_parsed_number(translated, (mpq_t *)parsedValue->data, 0); case AST_NULL: set_registers(translated, 1); size_t output = push_instruction_byte(translated, OP_LOAD_NULL); @@ -142,13 +144,19 @@ size_t translate_parsed(Translated *translated, ParsedValue *parsedValue, ArErr* case AST_IF: return translate_parsed_if(translated, (DArray *)parsedValue->data, err); case AST_DOWRAP: - return translate_parsed_dowrap(translated, (DArray *)parsedValue->data, err); + return translate_parsed_dowrap(translated, (DArray *)parsedValue->data, + err); case AST_RETURN: - return translate_parsed_return(translated, (ParsedReturn *)parsedValue->data, err); + return translate_parsed_return(translated, + (ParsedReturn *)parsedValue->data, err); case AST_CALL: - return translate_parsed_call(translated, (ParsedCall*)parsedValue->data, err); + return translate_parsed_call(translated, (ParsedCall *)parsedValue->data, + err); case AST_ACCESS: - return translate_access(translated,(ParsedAccess*)parsedValue->data, err); + return translate_access(translated, (ParsedAccess *)parsedValue->data, err); + case AST_OPERATION: + return translate_operation(translated, (ParsedOperation *)parsedValue->data, + err); } return 0; } diff --git a/src/translator/translator.h b/src/translator/translator.h index d2af800..cd58639 100644 --- a/src/translator/translator.h +++ b/src/translator/translator.h @@ -31,7 +31,8 @@ typedef enum { OP_SOURCE_LOCATION, OP_LOAD_ACCESS_FUNCTION, OP_LOAD_BOOL, - OP_LOAD_NUMBER + OP_LOAD_NUMBER, + OP_LOAD_ADDITION_FUNCTION } OperationType; void arena_resize(ConstantArena *arena, size_t new_size); diff --git a/testing.ar b/testing.ar index 6047817..35b4e2f 100644 --- a/testing.ar +++ b/testing.ar @@ -1,2 +1,6 @@ -let x = 1e10000 +let f(x) = do + return x + +let x = 10 + term.log(x) \ No newline at end of file