From b7f11d1fc295234023ca53797c20f07a797ccf4c Mon Sep 17 00:00:00 2001 From: VegOwOtenks Date: Tue, 8 Oct 2024 13:57:46 +0200 Subject: [PATCH] Implements binding variables (including name shadowing) --- src/interpreter.c | 138 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 134 insertions(+), 4 deletions(-) diff --git a/src/interpreter.c b/src/interpreter.c index e5e4e95..747389d 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -207,8 +207,12 @@ FlupFunction* Interpreter_FindFunction(Interpreter* self, StringView name) bool _are_types_compatible(enum ValueType type, StringView type_name) { - const enum ValueType type_mapping[] = {VALUETYPE_INT64, VALUETYPE_DOUBLE}; - const char* name_mapping[] = {"int", "double"}; + if (StringView_Equal(type_name, StringView_FromString("any"))) { + return true; + } + + const enum ValueType type_mapping[] = {VALUETYPE_INT64, VALUETYPE_DOUBLE, VALUETYPE_BOOLEAN, VALUETYPE_BOOLEAN}; + const char* name_mapping[] = {"int", "double", "bool", "boolean"}; for (size_t i = 0; i < sizeof(name_mapping) / sizeof(name_mapping[0]); i++) { if (1==1 @@ -419,6 +423,27 @@ int BuiltinFunction_Minus(CallFrame* top_frame) return CallFrame_StackPush(top_frame, &result); } +int Interpreter_GetParenthesizedRange(Interpreter* self, CallFrame* top_frame, size_t* paren_start, size_t* paren_end, size_t stop_token) +{ + size_t open_paren_count = 0; + size_t start_paren_index = top_frame->instruction_pointer; + do { + Token* t = Interpreter_ExpectToken(self, top_frame, stop_token); + if (t == NULL) { + // TODO: Error message + return EXIT_FAILURE; + } + top_frame->instruction_pointer++; + open_paren_count += t->type == TOKENTYPE_LEFT_PAREN; + open_paren_count -= t->type == TOKENTYPE_RIGHT_PAREN; + } while (open_paren_count != 0); + size_t stop_paren_index = --top_frame->instruction_pointer; + + if (paren_start != NULL) *paren_start = start_paren_index; + if (paren_end != NULL) *paren_end = stop_paren_index; + return EXIT_SUCCESS; +} + int Interpreter_ExecuteNext(Interpreter* self, size_t stop_token) { size_t frame_count = DynamicArray_GetLength(&self->call_frames); @@ -485,6 +510,113 @@ int Interpreter_ExecuteNext(Interpreter* self, size_t stop_token) break; } + case TOKENTYPE_BIND: + { + top_frame->instruction_pointer++; + Token* identifier_token = Interpreter_ExpectToken(self, top_frame, stop_token); + if (identifier_token == NULL) { + // TODO: Error message + return EXIT_FAILURE; + } + + // char variable_name[identifier_token->get.identifier.length + 1]; + // StringView_Paste(variable_name, identifier_token->get.identifier); + // variable_name[identifier_token->get.identifier.length] = '\0'; + // printf("Binding variable with name %s\n", variable_name); + + top_frame->instruction_pointer++; + Token* as_token = Interpreter_ExpectToken(self, top_frame, stop_token); + if (as_token == NULL) { + // TODO: Error message + return EXIT_FAILURE; + } + + size_t as_token_index = top_frame->instruction_pointer; + top_frame->instruction_pointer++; + + size_t paren_start, paren_end; + if (Interpreter_GetParenthesizedRange(self, top_frame, &paren_start, &paren_end, stop_token)) { + // TODO: Error message + return EXIT_FAILURE; + } + + top_frame->instruction_pointer = as_token_index; + + FlupFunction* evaluation_function = CallFrame_Reserve(top_frame, sizeof(FlupFunction), alignof(FlupFunction)); + if (evaluation_function == NULL) { + return ENOMEM; + } + + StringView evaluation_name = identifier_token->get.identifier; + while (!StringView_StartsWith(evaluation_name, StringView_FromString("bind"))) { + evaluation_name = (StringView) { + .source = evaluation_name.source - 1, + .length = evaluation_name.length + 1, + }; + } + evaluation_function->name = evaluation_name; + evaluation_function->return_type = StringView_FromString("any"); + + FlupFunctionAlternative* evaluation_alternative = CallFrame_Reserve(top_frame, sizeof(FlupFunctionAlternative), alignof(FlupFunctionAlternative)); + if (evaluation_alternative == NULL) { + return ENOMEM; + } + evaluation_alternative->body_token_start = paren_start + 1; + evaluation_alternative->body_token_end = paren_end; + evaluation_alternative->next = NULL; + + evaluation_function->alternatives = evaluation_alternative; + + FlupVariable* parent_variables = top_frame->variables; + + CallFrame* evaluation_frame; + DynamicArray_AppendEmpty(&self->call_frames, (void**) &evaluation_frame); + if (evaluation_frame == NULL) { + return ENOMEM; + } + + if (CallFrame_Create(evaluation_frame, evaluation_function)) { + return ENOMEM; + } + evaluation_frame->instruction_pointer = evaluation_alternative->body_token_start; + evaluation_frame->variables = parent_variables; + + break; + } + + case TOKENTYPE_AS: + { + Value variable_value; + if (CallFrame_StackPop(top_frame, &variable_value)) { + // TODO: Error message + return EXIT_FAILURE; + } + + top_frame->instruction_pointer--; + Token* identifier_token = Interpreter_ExpectToken(self, top_frame, stop_token); + if (identifier_token == NULL) { + // TODO: Error message + return EXIT_FAILURE; + } + // TODO: Type-check the token + StringView variable_name = identifier_token->get.identifier; + + if (CallFrame_DefineVariable(top_frame, variable_name, variable_value)) { + // TODO: Error message + return EXIT_FAILURE; + } + + top_frame->instruction_pointer += 2; // points to opening paren + size_t paren_end_index; + if (Interpreter_GetParenthesizedRange(self, top_frame, NULL, &paren_end_index, stop_token)) { + // TODO: Error message + return EXIT_FAILURE; + } + + top_frame->instruction_pointer = paren_end_index + 1; + break; + } + case TOKENTYPE_PIPE: case TOKENTYPE_SEMICOLON: case TOKENTYPE_LEFT_BRACE: @@ -500,8 +632,6 @@ int Interpreter_ExecuteNext(Interpreter* self, size_t stop_token) case TOKENTYPE_GREATERTHAN: case TOKENTYPE_GREATEREQUAL: case TOKENTYPE_COMMA: - case TOKENTYPE_BIND: - case TOKENTYPE_AS: case TOKENTYPE_LEFT_PAREN: case TOKENTYPE_RIGHT_PAREN: fprintf(stderr, "Unexpected token with type: %s\n, continuing with next token...\n", TokenType_ToString(t->type));