diff --git a/src/arobject.h b/src/arobject.h index 07aab60..fe27e69 100644 --- a/src/arobject.h +++ b/src/arobject.h @@ -25,7 +25,7 @@ typedef enum { __string__, __subtract__, __multiply__, - __division__, + __divide__, __new__, __init__, __boolean__, diff --git a/src/parser/assignable/access/access.c b/src/parser/assignable/access/access.c index b6d2dbb..5f2a561 100644 --- a/src/parser/assignable/access/access.c +++ b/src/parser/assignable/access/access.c @@ -21,6 +21,7 @@ ParsedValueReturn parse_access(char *file, DArray *tokens, size_t *index, if (first_token->type == TOKEN_DOT) { ParsedAccess *parsedAccess = checked_malloc(sizeof(ParsedAccess)); parsedAccess->to_access = to_access; + parsedAccess->access = NULL; parsedValue->type = AST_ACCESS; parsedValue->data = parsedAccess; ArErr err = error_if_finished(file, tokens, index); @@ -30,6 +31,14 @@ ParsedValueReturn parse_access(char *file, DArray *tokens, size_t *index, return (ParsedValueReturn){err, NULL}; } Token *token = darray_get(tokens, *index); + if (token->type != TOKEN_IDENTIFIER) { + free_parsed(parsedValue); + free(parsedValue); + return (ParsedValueReturn){create_err(token->line, token->column, + token->length, file, "Syntax Error", + "expected identifier after dot"), + NULL}; + } parsedAccess->line = token->line; parsedAccess->column = token->column; parsedAccess->length = token->length; @@ -50,7 +59,9 @@ void free_parse_access(void *ptr) { ParsedAccess *parsedAccess = parsedValue->data; free_parsed(parsedAccess->to_access); free(parsedAccess->to_access); - free_parsed(parsedAccess->access); - free(parsedAccess->access); + if (parsedAccess->access) { + free_parsed(parsedAccess->access); + free(parsedAccess->access); + } free(parsedAccess); } \ No newline at end of file diff --git a/src/parser/assignable/assign/assign.c b/src/parser/assignable/assign/assign.c index cf52a60..2fbe491 100644 --- a/src/parser/assignable/assign/assign.c +++ b/src/parser/assignable/assign/assign.c @@ -47,6 +47,7 @@ ParsedValueReturn parse_assign(char *file, DArray *tokens, ParsedAssign *assign = checked_malloc(sizeof(ParsedAssign)); assign->to = assign_to; assign->type = token->type; + assign->from = NULL; ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); parsedValue->type = AST_ASSIGN; parsedValue->data = assign; diff --git a/src/runtime/objects/dictionary/dictionary.c b/src/runtime/objects/dictionary/dictionary.c index c19688e..930fcef 100644 --- a/src/runtime/objects/dictionary/dictionary.c +++ b/src/runtime/objects/dictionary/dictionary.c @@ -139,7 +139,7 @@ ArgonObject *create_ARGON_DICTIONARY_TYPE___get_attr__(size_t argc, ArgonObject *result = hashmap_lookup_GC(object->value.as_hashmap, hash); if (!result) { *err = create_err(0, 0, 0, NULL, "Attribute Error", - "Dictionary has no attribute ''"); + "Dictionary has no attribute '%.*s'", key->value.as_str->length, key->value.as_str->data); return ARGON_NULL; } return result; diff --git a/src/runtime/objects/number/number.c b/src/runtime/objects/number/number.c index fee2990..fa3b647 100644 --- a/src/runtime/objects/number/number.c +++ b/src/runtime/objects/number/number.c @@ -532,7 +532,7 @@ void create_ARGON_NUMBER_TYPE() { add_builtin_field(ARGON_NUMBER_TYPE, __multiply__, create_argon_native_function( "__multiply__", ARGON_NUMBER_TYPE___multiply__)); - add_builtin_field(ARGON_NUMBER_TYPE, __division__, + add_builtin_field(ARGON_NUMBER_TYPE, __divide__, create_argon_native_function( "__division__", ARGON_NUMBER_TYPE___division__)); init_small_ints(); diff --git a/src/runtime/objects/object.c b/src/runtime/objects/object.c index f58c871..e58e609 100644 --- a/src/runtime/objects/object.c +++ b/src/runtime/objects/object.c @@ -39,7 +39,7 @@ const char *built_in_field_names[BUILT_IN_FIELDS_COUNT] = { "__string__", "__subtract__", "__multiply__", - "__division__", + "__divide__", "__new__", "__init__", "__boolean__", diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index 8d39d4f..b5d9d21 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -34,14 +34,13 @@ ArgonObject *ARGON_METHOD_TYPE; Stack *Global_Scope = NULL; -ArgonObject *GETATTRIBUTE_FUNCTION; ArgonObject *ADDITION_FUNCTION; ArgonObject *SUBTRACTION_FUNCTION; ArgonObject *MULTIPLY_FUNCTION; -ArgonObject *DIVISION_FUNCTION; +ArgonObject *DIVIDE_FUNCTION; ArgonObject *POWER_FUNCTION; ArgonObject *MODULO_FUNCTION; -ArgonObject *FLOORDIVISION_FUNCTION; +ArgonObject *FLOORDIVIDE_FUNCTION; ArgonObject *BASE_CLASS___getattribute__(size_t argc, ArgonObject **argv, ArErr *err, RuntimeState *state) { @@ -164,28 +163,27 @@ ArgonObject *ARGON_MULTIPLY_FUNCTION(size_t argc, ArgonObject **argv, return output; } -ArgonObject *ARGON_DIVISION_FUNCTION(size_t argc, ArgonObject **argv, - ArErr *err, RuntimeState *state) { +ArgonObject *ARGON_DIVIDE_FUNCTION(size_t argc, ArgonObject **argv, ArErr *err, + RuntimeState *state) { if (argc < 1) { - *err = - create_err(0, 0, 0, "", "Runtime Error", - "division expects at least 1 argument, got %" PRIu64, argc); + *err = create_err(0, 0, 0, "", "Runtime Error", + "divide expects at least 1 argument, got %" PRIu64, argc); return ARGON_NULL; } ArgonObject *output = argv[0]; for (size_t i = 1; i < argc; i++) { - ArgonObject *function__division__ = get_builtin_field_for_class( - get_builtin_field(output, __class__), __division__, output); - if (!function__division__) { + ArgonObject *function___divide__ = get_builtin_field_for_class( + get_builtin_field(output, __class__), __divide__, output); + if (!function___divide__) { ArgonObject *cls___name__ = get_builtin_field(output, __name__); *err = create_err(0, 0, 0, "", "Runtime Error", - "Object '%.*s' is missing __division__ method", + "Object '%.*s' is missing __divide__ method", (int)cls___name__->value.as_str->length, cls___name__->value.as_str->data); return ARGON_NULL; } - output = argon_call(function__division__, 1, (ArgonObject *[]){argv[i]}, - err, state); + output = argon_call(function___divide__, 1, (ArgonObject *[]){argv[i]}, err, + state); } return output; } @@ -282,6 +280,22 @@ ArgonObject *BASE_CLASS___init__(size_t argc, ArgonObject **argv, ArErr *err, return ARGON_NULL; } +ArgonObject *BASE_CLASS___setattr__(size_t argc, ArgonObject **argv, ArErr *err, + RuntimeState *state) { + (void)state; + if (argc != 3) { + *err = create_err(0, 0, 0, "", "Runtime Error", + "__setattr__ expects 3 argument, got %" PRIu64, argc); + } + if (!argv[1]->value.as_str->hash) + argv[1]->value.as_str->hash = + runtime_hash(argv[1]->value.as_str->data, argv[1]->value.as_str->length, + argv[1]->value.as_str->prehash); + add_field_l(argv[0], argv[1]->value.as_str->data, argv[1]->value.as_str->hash, + argv[1]->value.as_str->length, argv[2]); + return argv[2]; +} + ArgonObject *BASE_CLASS___string__(size_t argc, ArgonObject **argv, ArErr *err, RuntimeState *state) { (void)state; @@ -661,17 +675,20 @@ void bootstrap_types() { add_builtin_field( ARGON_BOOL_TYPE, __number__, create_argon_native_function("__number__", ARGON_BOOL_TYPE___number__)); - GETATTRIBUTE_FUNCTION = - create_argon_native_function("__get_attr__", BASE_CLASS___getattribute__); ADDITION_FUNCTION = create_argon_native_function("add", ARGON_ADDITION_FUNCTION); SUBTRACTION_FUNCTION = create_argon_native_function("subtract", ARGON_SUBTRACTION_FUNCTION); MULTIPLY_FUNCTION = create_argon_native_function("multiply", ARGON_MULTIPLY_FUNCTION); - DIVISION_FUNCTION = - create_argon_native_function("division", ARGON_DIVISION_FUNCTION); - add_builtin_field(BASE_CLASS, __getattribute__, GETATTRIBUTE_FUNCTION); + DIVIDE_FUNCTION = + create_argon_native_function("divide", ARGON_DIVIDE_FUNCTION); + add_builtin_field(BASE_CLASS, __getattribute__, + create_argon_native_function("__getattribute__", + BASE_CLASS___getattribute__)); + add_builtin_field( + BASE_CLASS, __setattr__, + create_argon_native_function("__setattr__", BASE_CLASS___setattr__)); create_ARGON_DICTIONARY_TYPE(); } @@ -692,7 +709,7 @@ void bootstrap_globals() { add_to_scope(Global_Scope, "add", ADDITION_FUNCTION); add_to_scope(Global_Scope, "subtract", SUBTRACTION_FUNCTION); add_to_scope(Global_Scope, "multiply", MULTIPLY_FUNCTION); - add_to_scope(Global_Scope, "division", DIVISION_FUNCTION); + add_to_scope(Global_Scope, "divide", DIVIDE_FUNCTION); add_to_scope(Global_Scope, "dictionary", ARGON_DICTIONARY_TYPE); ArgonObject *argon_term = new_class(); @@ -709,7 +726,7 @@ int compare_by_order(const void *a, const void *b) { } static inline void load_const(Translated *translated, RuntimeState *state) { - uint64_t to_register = pop_byte(translated, state); + uint8_t to_register = pop_byte(translated, state); size_t length = pop_bytecode(translated, state); uint64_t offset = pop_bytecode(translated, state); ArgonObject *object = new_string_object( @@ -824,6 +841,13 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack, Translated *translated = ¤tStackFrame->translated; RuntimeState *state = ¤tStackFrame->state; uint8_t instruction = pop_byte(translated, state); + // printf("instruction: %d\n", instruction); + // for (size_t i = 0; i < translated->bytecode.size; i++) { + // if (i == state->head) + // printf("\n"); + // printf("%d ", ((uint8_t *)translated->bytecode.data)[i]); + // } + // printf("\n"); goto *dispatch_table[instruction]; DO_LOAD_NULL: state->registers[pop_byte(translated, state)] = ARGON_NULL; @@ -1171,8 +1195,7 @@ void runtime(Translated _translated, RuntimeState _state, Stack *stack, } ArgonObject *args[] = {valueA, valueB}; - state->registers[registerC] = - ARGON_DIVISION_FUNCTION(2, args, err, state); + state->registers[registerC] = ARGON_DIVIDE_FUNCTION(2, args, err, state); continue; } DO_LOAD_SETATTR_METHOD: { diff --git a/src/translator/access/access.c b/src/translator/access/access.c index 993f39d..3da4e0b 100644 --- a/src/translator/access/access.c +++ b/src/translator/access/access.c @@ -14,7 +14,7 @@ size_t translate_access(Translated *translated, ParsedAccess *access, push_instruction_byte(translated, OP_LOAD_GETATTRIBUTE_METHOD); push_instruction_byte(translated, OP_INIT_CALL); push_instruction_code(translated, 1); - + translate_parsed(translated, access->access, err); if (err->exists) return 0; diff --git a/src/translator/assignment/assignment.c b/src/translator/assignment/assignment.c index 1833893..2bfebdb 100644 --- a/src/translator/assignment/assignment.c +++ b/src/translator/assignment/assignment.c @@ -6,8 +6,9 @@ #include "assignment.h" #include "../../hash_data/hash_data.h" -#include "../../parser/assignable/identifier/identifier.h" #include "../../parser/assignable/access/access.h" +#include "../../parser/assignable/identifier/identifier.h" +#include "../../parser/string/string.h" #include "../translator.h" #include #include @@ -21,14 +22,14 @@ size_t translate_parsed_assignment(Translated *translated, translated->return_jumps = NULL; size_t first = translate_parsed(translated, assignment->from, err); if (err->exists) - return first; + return 0; switch (assignment->to->type) { case AST_IDENTIFIER:; ParsedIdentifier *identifier = assignment->to->data; size_t length = strlen(identifier->name); size_t offset = arena_push(&translated->constants, identifier->name, length); - + push_instruction_byte(translated, OP_SOURCE_LOCATION); push_instruction_code(translated, identifier->line); push_instruction_code(translated, identifier->column); @@ -44,6 +45,31 @@ size_t translate_parsed_assignment(Translated *translated, break; case AST_ACCESS:; ParsedAccess *access = assignment->to->data; + uint8_t registerA = translated->registerAssignment++; + set_registers(translated, registerA); + push_instruction_byte(translated, OP_COPY_TO_REGISTER); + push_instruction_byte(translated, 0); + push_instruction_byte(translated, registerA); + translate_parsed(translated, access->to_access, err); + if (err->exists) + return 0; + push_instruction_byte(translated, OP_LOAD_SETATTR_METHOD); + push_instruction_byte(translated, OP_INIT_CALL); + push_instruction_code(translated, 2); + translate_parsed(translated, access->access, err); + if (err->exists) + return 0; + push_instruction_byte(translated, OP_INSERT_ARG); + push_instruction_code(translated, 0); + + push_instruction_byte(translated, OP_COPY_TO_REGISTER); + push_instruction_byte(translated, registerA); + push_instruction_byte(translated, 0); + push_instruction_byte(translated, OP_INSERT_ARG); + push_instruction_code(translated, 1); + + push_instruction_byte(translated, OP_CALL); + translated->registerAssignment--; break; default: fprintf(stderr, "panic: unsupported assignment\n"); diff --git a/tests/iteration-test.ar b/tests/iteration-test.ar index 0f7853b..82abded 100644 --- a/tests/iteration-test.ar +++ b/tests/iteration-test.ar @@ -1,3 +1,4 @@ -let i = 1e6 +term.log(global."hello world") +let i = 1e8 while (i) do i=i-1 \ No newline at end of file