diff --git a/null_test.ar b/null_test.ar index b2e4d55..051364a 100644 --- a/null_test.ar +++ b/null_test.ar @@ -1,2 +1 @@ -null -"hello\u0000world" \ No newline at end of file +let x(hello,lol,world, WORLD,HELLOOOO,LOLLLLLL, WORLD)="HELLOOOO WORLD" \ No newline at end of file diff --git a/src/parser/declaration/declaration.c b/src/parser/declaration/declaration.c index d21abc1..e9469f5 100644 --- a/src/parser/declaration/declaration.c +++ b/src/parser/declaration/declaration.c @@ -3,6 +3,7 @@ #include "../../memory.h" #include "../literals/literals.h" #include "../parser.h" +#include "../function/function.h" #include #include #include @@ -22,7 +23,8 @@ ParsedValue *parse_declaration(char *file, DArray *tokens, size_t *index) { darray_push(declarations, &_declaration); ParsedSingleDeclaration *declaration = darray_get(declarations, declarations->size - 1); - declaration->is_function = false; + bool isFunction = false; + DArray parameters; declaration->from = parse_null(); if (token->type != TOKEN_IDENTIFIER) { @@ -38,8 +40,8 @@ ParsedValue *parse_declaration(char *file, DArray *tokens, size_t *index) { return parsedValue; token = darray_get(tokens, *index); if (token->type == TOKEN_LPAREN) { - declaration->is_function = true; - darray_init(&declaration->parameters, sizeof(char *)); + isFunction = true; + darray_init(¶meters, sizeof(char *)); (*index)++; error_if_finished(file, tokens, index); token = darray_get(tokens, *index); @@ -63,7 +65,7 @@ ParsedValue *parse_declaration(char *file, DArray *tokens, size_t *index) { } char *parameter_name = strcpy(checked_malloc(strlen(token->value) + 1), token->value); - darray_push(&declaration->parameters, ¶meter_name); + darray_push(¶meters, ¶meter_name); (*index)++; error_if_finished(file, tokens, index); skip_newlines_and_indents(tokens, index); @@ -97,6 +99,9 @@ ParsedValue *parse_declaration(char *file, DArray *tokens, size_t *index) { token->column); exit(EXIT_FAILURE); } + if (isFunction) { + declaration->from = create_parsed_function(declaration->name, parameters, declaration->from); + } if ((*index) >= tokens->size) break; token = darray_get(tokens, *index); @@ -127,8 +132,6 @@ void free_string(void *ptr) { void free_single_declaration(void *ptr) { ParsedSingleDeclaration *declaration = ptr; free(declaration->name); - if (declaration->is_function) - darray_free(&declaration->parameters, free_string); free_parsed(declaration->from); free(declaration->from); } diff --git a/src/parser/declaration/declaration.h b/src/parser/declaration/declaration.h index 7a7c9e1..a8eb9dc 100644 --- a/src/parser/declaration/declaration.h +++ b/src/parser/declaration/declaration.h @@ -5,8 +5,6 @@ typedef struct { char * name; - bool is_function; - DArray parameters; // string[] ParsedValue * from; } ParsedSingleDeclaration; diff --git a/src/parser/dictionary/dictionary.c b/src/parser/dictionary/dictionary.c index 7257147..0d2e862 100644 --- a/src/parser/dictionary/dictionary.c +++ b/src/parser/dictionary/dictionary.c @@ -88,5 +88,5 @@ void free_parsed_dictionary(void *ptr) { ParsedValue *parsedValue = ptr; DArray *parsed_dictionary = parsedValue->data; darray_free(parsed_dictionary, free_dictionary_entry); - free(parsedValue->data); + free(parsed_dictionary); } \ No newline at end of file diff --git a/src/parser/function/function.c b/src/parser/function/function.c new file mode 100644 index 0000000..fe93111 --- /dev/null +++ b/src/parser/function/function.c @@ -0,0 +1,25 @@ +#include "function.h" +#include "../../memory.h" +#include +#include + +ParsedValue *create_parsed_function(char *name, DArray parameters, + ParsedValue *body) { + ParsedValue *parsedValue = checked_malloc(sizeof(ParsedValue)); + parsedValue->type=AST_FUNCTION; + ParsedFunction *parsedFunction = checked_malloc(sizeof(ParsedFunction)); + parsedValue->data=parsedFunction; + parsedFunction->name=strcpy(checked_malloc(strlen(name) + 1), name); + parsedFunction->body = body; + parsedFunction->parameters=parameters; + return parsedValue; +} + +void free_function(void *ptr) { + ParsedValue *parsedValue = ptr; + ParsedFunction *parsed = parsedValue->data; + free_parsed(parsed->body); + free(parsed->name); + darray_free(&parsed->parameters, NULL); + free(parsed); +} \ No newline at end of file diff --git a/src/parser/function/function.h b/src/parser/function/function.h new file mode 100644 index 0000000..8c18ec7 --- /dev/null +++ b/src/parser/function/function.h @@ -0,0 +1,17 @@ +#ifndef FUNCTION_H +#define FUNCTION_H +#include "../../lexer/token.h" // for Token +#include "../parser.h" + +typedef struct { + char * name; + DArray parameters; + ParsedValue *body; +} ParsedFunction; + +ParsedValue *create_parsed_function(char *name, DArray parameters, + ParsedValue *body); + +void free_function(void *ptr); + +#endif // FUNCTION_H \ No newline at end of file diff --git a/src/parser/if/if.c b/src/parser/if/if.c index 76aa075..48b5093 100644 --- a/src/parser/if/if.c +++ b/src/parser/if/if.c @@ -115,5 +115,5 @@ void free_parsed_if(void *ptr) { ParsedValue *parsedValue = ptr; DArray *parsed_if = parsedValue->data; darray_free(parsed_if, free_conditional); - free(parsedValue->data); + free(parsed_if); } \ No newline at end of file diff --git a/src/parser/list/list.c b/src/parser/list/list.c index d025c99..9dc0617 100644 --- a/src/parser/list/list.c +++ b/src/parser/list/list.c @@ -45,5 +45,5 @@ void free_parsed_list(void *ptr) { ParsedValue *parsedValue = ptr; DArray *parsed_list = parsedValue->data; darray_free(parsed_list, free_parsed); - free(parsedValue->data); + free(parsed_list); } \ No newline at end of file diff --git a/src/parser/parser.c b/src/parser/parser.c index ee1f809..79a3cc3 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -8,6 +8,7 @@ #include "declaration/declaration.h" #include "dictionary/dictionary.h" #include "dowrap/dowrap.h" +#include "function/function.h" #include "if/if.h" #include "list/list.h" #include "literals/literals.h" @@ -24,7 +25,7 @@ const char *ValueTypeNames[] = { "string", "assign", "identifier", "number", "if statement", "access", "call", "declaration", "null", "boolean", - "do wrap", "operations", "list", "dictionary"}; + "do wrap", "operations", "list", "dictionary", "function"}; void error_if_finished(char *file, DArray *tokens, size_t *index) { if ((*index) >= tokens->size) { @@ -232,5 +233,7 @@ void free_parsed(void *ptr) { case AST_DICTIONARY: free_parsed_dictionary(parsed); break; + case AST_FUNCTION: + free_function(parsed); } } \ No newline at end of file diff --git a/src/parser/parser.h b/src/parser/parser.h index 2685a73..551273a 100644 --- a/src/parser/parser.h +++ b/src/parser/parser.h @@ -39,7 +39,8 @@ typedef enum { AST_DOWRAP, AST_OPERATION, AST_LIST, - AST_DICTIONARY + AST_DICTIONARY, + AST_FUNCTION } ValueType; extern const char* ValueTypeNames[]; diff --git a/src/runtime/objects/function/functions.c b/src/runtime/objects/function/functions.c new file mode 100644 index 0000000..e69de29 diff --git a/src/runtime/objects/function/functions.h b/src/runtime/objects/function/functions.h new file mode 100644 index 0000000..fe94518 --- /dev/null +++ b/src/runtime/objects/function/functions.h @@ -0,0 +1,6 @@ +#ifndef FUNCTION_H +#define FUNCTION_H +#include "../object.h" + + +#endif // FUNCTION_H \ No newline at end of file diff --git a/src/runtime/objects/null/null.c b/src/runtime/objects/null/null.c index dd963f2..ce3b7d9 100644 --- a/src/runtime/objects/null/null.c +++ b/src/runtime/objects/null/null.c @@ -3,8 +3,12 @@ #include #include "null.h" +ArgonObject *ARGON_NULL_TYPE = NULL; ArgonObject *ARGON_NULL = NULL; void init_null() { - ARGON_NULL = init_argon_object(); + ARGON_NULL_TYPE = init_argon_class("NULL_TYPE"); + + ARGON_NULL = init_child_argon_object(ARGON_NULL_TYPE); + ARGON_NULL->type=TYPE_NULL; } \ No newline at end of file diff --git a/src/runtime/objects/object.c b/src/runtime/objects/object.c index 80b1ea2..115b15e 100644 --- a/src/runtime/objects/object.c +++ b/src/runtime/objects/object.c @@ -1,19 +1,30 @@ #include "object.h" #include "../../memory.h" #include "../runtime.h" +#include #include -ArgonObject *BASE_OBJECT = NULL; +ArgonObject *BASE_CLASS = NULL; void init_base_field() { - add_field(BASE_OBJECT, "test", BASE_OBJECT); + // add_field(BASE_CLASS, "test", BASE_CLASS); } -ArgonObject* init_argon_object() { +ArgonObject* init_child_argon_object(ArgonObject *cls) { + ArgonObject *object = init_argon_class(NULL); + object->self = object; + object->baseObject = cls; + add_field(object, "__call__", NULL); + return object; +} + + +ArgonObject* init_argon_class(char*name) { ArgonObject *object = ar_alloc(sizeof(ArgonObject)); + object->name = name; object->type = TYPE_OBJECT; - object->typeObject = NULL; - object->baseObject = BASE_OBJECT; + object->self = NULL; + object->baseObject = BASE_CLASS; object->fields = createHashmap(); memset(&object->value, 0, sizeof(object->value)); return object; diff --git a/src/runtime/objects/object.h b/src/runtime/objects/object.h index 0248867..05b18dc 100644 --- a/src/runtime/objects/object.h +++ b/src/runtime/objects/object.h @@ -4,7 +4,7 @@ #include #include -extern ArgonObject *BASE_OBJECT; +extern ArgonObject *BASE_CLASS; struct string_struct { char *data; @@ -17,14 +17,14 @@ typedef enum { TYPE_NUMBER, TYPE_STRING, TYPE_FUNCTION, - TYPE_NATIVE_FUNCTION, TYPE_OBJECT, // generic user object } ArgonType; struct ArgonObject { ArgonType type; + char* name; + ArgonObject *self; ArgonObject *baseObject; - ArgonObject *typeObject; struct hashmap *fields; // dynamic fields/methods union { mpq_t as_number; @@ -36,8 +36,8 @@ struct ArgonObject { }; typedef struct ArgonObject ArgonObject; void init_base_field(); - -ArgonObject *init_argon_object(); +ArgonObject* init_child_argon_object(ArgonObject *cls); +ArgonObject* init_argon_class(char*name); void add_field(ArgonObject*target, char* name, ArgonObject *object); #endif // OBJECT_H \ No newline at end of file diff --git a/src/runtime/objects/string/string.c b/src/runtime/objects/string/string.c index 3a50288..98f438b 100644 --- a/src/runtime/objects/string/string.c +++ b/src/runtime/objects/string/string.c @@ -4,21 +4,15 @@ #include ArgonObject *ARGON_STRING_TYPE = NULL; -ArgonObject *ARGON_STRING_BASE = NULL; void init_string_type() { - ARGON_STRING_TYPE = init_argon_object(); - - ARGON_STRING_BASE = init_argon_object(); + ARGON_STRING_TYPE = init_argon_class("String"); } ArgonObject *init_string_object(char*data, size_t length) { - fwrite(data, 1, length, stdout); - printf("\n"); - ArgonObject * object = init_argon_object(); - object->typeObject = ARGON_STRING_TYPE; - object->baseObject = ARGON_STRING_BASE; + ArgonObject * object = init_child_argon_object(ARGON_STRING_TYPE); + object->type = TYPE_STRING; object->value.as_str.data = data; object->value.as_str.length = length; return object; diff --git a/src/runtime/objects/type/type.c b/src/runtime/objects/type/type.c index 78ea960..b32a735 100644 --- a/src/runtime/objects/type/type.c +++ b/src/runtime/objects/type/type.c @@ -6,5 +6,5 @@ ArgonObject *ARGON_TYPE = NULL; void init_type() { - ARGON_TYPE = init_argon_object(); + ARGON_TYPE = init_argon_class("function"); } \ No newline at end of file diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index de8e3fc..32a4413 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -13,7 +13,7 @@ #include void init_types() { - BASE_OBJECT = init_argon_object(); + BASE_CLASS = init_argon_class("BASE_CLASS"); init_type(); init_null(); @@ -33,7 +33,7 @@ void load_const(Translated *translated, RuntimeState *state) { size_t length = pop_bytecode(translated, state); uint64_t offset = pop_bytecode(translated, state); - void*data = ar_alloc(length); + void*data = ar_alloc_atomic(length); memcpy(data, arena_get(&translated->constants,offset), length); ArgonObject *object = ARGON_NULL; switch (type) { @@ -44,7 +44,7 @@ void load_const(Translated *translated, RuntimeState *state) { state->registers[to_register] = object; } -void run_instruction(Translated *translated, RuntimeState *state) { +void run_instruction(Translated *translated, RuntimeState *state, struct Stack stack) { OperationType opcode = pop_bytecode(translated, state); switch (opcode) { case OP_LOAD_NULL: @@ -59,9 +59,10 @@ void run_instruction(Translated *translated, RuntimeState *state) { void runtime(Translated translated) { RuntimeState state = { checked_malloc(translated.registerCount * sizeof(ArgonObject *)), 0}; + struct Stack stack = {}; while (state.head < translated.bytecode.size) - run_instruction(&translated, &state); + run_instruction(&translated, &state,stack); free(state.registers); } diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index 5410cd2..fe53bae 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -8,9 +8,14 @@ typedef struct { size_t head; } RuntimeState; +typedef struct Stack { + ArgonObject *scope; + struct Stack *prev; +} Stack; + void init_types(); -void run_instruction(Translated *translated, RuntimeState *state); +void run_instruction(Translated *translated, RuntimeState *state, struct Stack stack); void runtime(Translated translated); diff --git a/src/translator/bytecode_spec.md b/src/translator/bytecode_spec.md index 4b23034..93503a3 100644 --- a/src/translator/bytecode_spec.md +++ b/src/translator/bytecode_spec.md @@ -28,3 +28,16 @@ sets a given register to null. this operation takes 1 operand. 1. the register to set to null. + +## OP_LOAD_FUNCTION + +initilises a function to a given register. + +1. the offset of the name of the function. +2. the length of the name of the function. +3. the number of arguments. +4. the offset of the name of the argument. +5. the length of the name of the argument. +6. instruction 4 and 5 loop for each argument. +7. the offset of the bytecode of the function. +8. the length of the bytecode of the function. diff --git a/src/translator/declaration/declaration.c b/src/translator/declaration/declaration.c index 5ac8f9f..ed73cc5 100644 --- a/src/translator/declaration/declaration.c +++ b/src/translator/declaration/declaration.c @@ -9,7 +9,6 @@ size_t translate_parsed_declaration(Translated *translated, set_registers(translated, 1); size_t first = 0; for (size_t i = 0; i < delcarations.size; i++) { - // TODO: add function delclaration ParsedSingleDeclaration *singleDeclaration = darray_get(&delcarations, i); size_t temp = translate_parsed(translated, singleDeclaration->from); if (i == 0) diff --git a/src/translator/function/function.c b/src/translator/function/function.c index 4e88492..a2357b0 100644 --- a/src/translator/function/function.c +++ b/src/translator/function/function.c @@ -4,6 +4,32 @@ #include #include size_t translate_parsed_function(Translated *translated, - ParsedValue *parsedValue) { - return 0; + ParsedFunction *parsedFunction) { + DArray temp_bytecode; + darray_init(&temp_bytecode, sizeof(uint64_t)); + DArray main_bytecode = translated->bytecode; + translated->bytecode = temp_bytecode; + translate_parsed(translated, parsedFunction->body); + size_t function_bytecode_offset = + arena_push(&translated->constants, translated->bytecode.data, + translated->bytecode.size); + size_t function_bytecode_length = translated->bytecode.size; + translated->bytecode = main_bytecode; + darray_free(&temp_bytecode, NULL); + size_t start = push_instruction_code(translated, OP_LOAD_FUNCTION); + size_t offset = arena_push(&translated->constants, parsedFunction->name, + strlen(parsedFunction->name)); + push_instruction_code(translated, offset); + push_instruction_code(translated, strlen(parsedFunction->name)); + push_instruction_code(translated, parsedFunction->parameters.size); + for (size_t i = 0; i < parsedFunction->parameters.size; i++) { + char **parameter_name = darray_get(&parsedFunction->parameters, i); + offset = arena_push(&translated->constants, *parameter_name, + strlen(*parameter_name)); + push_instruction_code(translated, offset); + push_instruction_code(translated, strlen(*parameter_name)); + } + push_instruction_code(translated, function_bytecode_offset); + push_instruction_code(translated, function_bytecode_length); + return start; } \ No newline at end of file diff --git a/src/translator/function/function.h b/src/translator/function/function.h index 80002c5..1cbc051 100644 --- a/src/translator/function/function.h +++ b/src/translator/function/function.h @@ -1,8 +1,9 @@ #ifndef BYTECODE_FUNCTION_H #define BYTECODE_FUNCTION_H #include "../translator.h" +#include "../../parser/function/function.h" size_t translate_parsed_function(Translated *translated, - ParsedValue *parsedValue); + ParsedFunction *parsedFunction); #endif \ No newline at end of file diff --git a/src/translator/translator.c b/src/translator/translator.c index a5bddc7..fd2b0f1 100644 --- a/src/translator/translator.c +++ b/src/translator/translator.c @@ -1,5 +1,6 @@ #include "translator.h" #include "declaration/declaration.h" +#include "function/function.h" #include "number/number.h" #include "string/string.h" #include @@ -81,16 +82,21 @@ void set_registers(Translated *translator, size_t count) { size_t translate_parsed(Translated *translated, ParsedValue *parsedValue) { switch (parsedValue->type) { case AST_STRING: - return translate_parsed_string(translated, *((ParsedString*)parsedValue->data)); + return translate_parsed_string(translated, + *((ParsedString *)parsedValue->data)); case AST_DECLARATION: - return translate_parsed_declaration(translated, *((DArray*)parsedValue->data)); + return translate_parsed_declaration(translated, + *((DArray *)parsedValue->data)); case AST_NUMBER: - return translate_parsed_number(translated, (char*)parsedValue->data, 0); + return translate_parsed_number(translated, (char *)parsedValue->data, 0); case AST_NULL: set_registers(translated, 1); size_t output = push_instruction_code(translated, OP_LOAD_NULL); push_instruction_code(translated, 0); return output; + case AST_FUNCTION: + return translate_parsed_function(translated, + (ParsedFunction *)parsedValue->data); } return 0; } diff --git a/src/translator/translator.h b/src/translator/translator.h index 6136376..00959f2 100644 --- a/src/translator/translator.h +++ b/src/translator/translator.h @@ -7,7 +7,7 @@ #include #include -typedef enum { OP_LOAD_CONST = 255, OP_DECLARE, OP_LOAD_NULL } OperationType; +typedef enum { OP_LOAD_CONST = 255, OP_DECLARE, OP_LOAD_NULL, OP_LOAD_FUNCTION } OperationType; typedef enum { TYPE_OP_STRING = 255, TYPE_OP_NUMBER } types; typedef struct {