diff --git a/src/builtin-functions.c b/src/builtin-functions.c new file mode 100644 index 0000000..119e75b --- /dev/null +++ b/src/builtin-functions.c @@ -0,0 +1,154 @@ +/* + * This code is part of the programming language flup + * flup comes with ABSOLUTELY NO WARRANTY and is licensed under AGPL-3.0 or later. + * Copyright (C) 2024 VegOwOtenks + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "builtin-functions.h" + +#include "value.h" + +#include +#include + +int BuiltinFunction_Equality(CallFrame* top_frame) +{ + Value v1; + Value v2; + + CallFrame_StackPop(top_frame, &v1); + if (CallFrame_StackPop(top_frame, &v2) != EXIT_SUCCESS) { + // TODO: Error message + return EXIT_FAILURE; + } + + Value result; + result.type = VALUETYPE_BOOLEAN; + result.get.boolean = Value_Equal(&v1, &v2); + + top_frame->instruction_pointer++; + return CallFrame_StackPush(top_frame, &result); + +} + +int BuiltinFunction_Plus(CallFrame* top_frame) +{ + Value v1; + Value v2; + + CallFrame_StackPop(top_frame, &v1); + if (CallFrame_StackPop(top_frame, &v2) != EXIT_SUCCESS) { + // TODO: Error message + return EXIT_FAILURE; + } + if (v1.type != v2.type) { + // TODO: Error message + return EXIT_FAILURE; + } + + Value result; + result.type = v1.type; + switch (v1.type) { + case VALUETYPE_INT64: + result.get.i64 = v2.get.i64 + v1.get.i64; + break; + case VALUETYPE_DOUBLE: + result.get.f64 = v2.get.f64 + v1.get.f64; + break; + case VALUETYPE_BOOLEAN: + result.get.boolean = v2.get.boolean + v1.get.boolean; + break; + } + + top_frame->instruction_pointer++; + return CallFrame_StackPush(top_frame, &result); +} + +int BuiltinFunction_Minus(CallFrame* top_frame) +{ + Value v1; + Value v2; + + CallFrame_StackPop(top_frame, &v1); + if (CallFrame_StackPop(top_frame, &v2) != EXIT_SUCCESS) { + // TODO: Error message + return EXIT_FAILURE; + } + if (v1.type != v2.type) { + // TODO: Error message + return EXIT_FAILURE; + } + + Value result; + result.type = v1.type; + switch (v1.type) { + case VALUETYPE_INT64: + result.get.i64 = v2.get.i64 - v1.get.i64; + break; + case VALUETYPE_DOUBLE: + result.get.f64 = v2.get.f64 - v1.get.f64; + break; + case VALUETYPE_BOOLEAN: + result.get.boolean = v2.get.boolean - v1.get.boolean; + break; + } + + top_frame->instruction_pointer++; + return CallFrame_StackPush(top_frame, &result); +} + + +int BuiltinFunction_PrintLine(CallFrame* top_frame) +{ + Value v1; + + if (CallFrame_StackPop(top_frame, &v1) != EXIT_SUCCESS) { + return EXIT_FAILURE; + } + + switch (v1.type) { + case VALUETYPE_INT64: + printf("%i\n", v1.get.i64); + break; + case VALUETYPE_DOUBLE: + printf("%f\n", v1.get.f64); + break; + case VALUETYPE_BOOLEAN: + if (v1.get.boolean) { + printf("true\n"); + } else { + printf("false\n"); + } + break; + } + + return EXIT_SUCCESS; +} + +int BuiltinFunction_Duplicate(CallFrame* top_frame) +{ + Value v1; + + if (CallFrame_StackPop(top_frame, &v1) != EXIT_SUCCESS) { + return EXIT_FAILURE; + } + + if (CallFrame_StackPush(top_frame, &v1) || CallFrame_StackPush(top_frame, &v1)) { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/src/builtin-functions.h b/src/builtin-functions.h new file mode 100644 index 0000000..cd690a3 --- /dev/null +++ b/src/builtin-functions.h @@ -0,0 +1,34 @@ +/* + * This code is part of the programming language flup + * flup comes with ABSOLUTELY NO WARRANTY and is licensed under AGPL-3.0 or later. + * Copyright (C) 2024 VegOwOtenks + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef FLUP_BUILTINFUNCTION_H +#define FLUP_BUILTINFUNCTION_H + +#include "callframe.h" +#include "tokenizer.h" + + +int BuiltinFunction_Minus(CallFrame* top_frame); +int BuiltinFunction_Plus(CallFrame* top_frame); +int BuiltinFunction_Equality(CallFrame* top_frame); +int BuiltinFunction_PrintLine(CallFrame* top_frame); +int BuiltinFunction_Duplicate(CallFrame* top_frame); + + +#endif \ No newline at end of file diff --git a/src/callframe.c b/src/callframe.c new file mode 100644 index 0000000..608e2be --- /dev/null +++ b/src/callframe.c @@ -0,0 +1,125 @@ +/* + * This code is part of the programming language flup + * flup comes with ABSOLUTELY NO WARRANTY and is licensed under AGPL-3.0 or later. + * Copyright (C) 2024 VegOwOtenks + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "callframe.h" + +#include + +int CallFrame_Create(CallFrame* self, FlupFunction* self_function) +{ + if (DynamicArray_Create(&self->stack, sizeof(Value), 8, NULL)) { + return ENOMEM; + } + self->memory_pad.memory = NULL; + self->self_function = self_function; + self->alternative = self->self_function->alternatives; + self->instruction_pointer = self->alternative->condition_token_start; + + self->variables = NULL; + self->functions = NULL; + + return EXIT_SUCCESS; +} + +int CallFrame_DefineVariable(CallFrame* self, StringView name, Value value) +{ + FlupVariable* v = CallFrame_Reserve(self, sizeof(FlupVariable), alignof(FlupVariable)); + if (v == NULL) { + return ENOMEM; + } + + v->name = name; + v->value = value; + + v->next = self->variables; + self->variables = v; + + return EXIT_SUCCESS; +} + + +int CallFrame_StackPop(CallFrame* self, Value* dest) +{ + size_t stack_size = DynamicArray_GetLength(&self->stack); + Value* popped = DynamicArray_GetPointer(&self->stack, stack_size - 1); + if (popped == NULL) { + return ENOTFOUND; + } + + *dest = *popped; + DynamicArray_Remove(&self->stack, stack_size - 1); + + return EXIT_SUCCESS; +} + +int CallFrame_StackPush(CallFrame* self, Value* value) +{ + return DynamicArray_Append(&self->stack, value); +} + +FlupVariable* CallFrame_FindVariable(CallFrame* self, StringView name) +{ + for (FlupVariable* variable = self->variables; variable != NULL; variable = variable->next) { + if (StringView_Equal(variable->name, name)) { + return variable; + } + } + + return NULL; +} + +void CallFrame_Destroy(CallFrame* self) +{ + if (self->memory_pad.memory != NULL) { + Scratchpad_Destroy(&self->memory_pad); + } + + DynamicArray_Destroy(&self->stack); +} + +void* CallFrame_Reserve(CallFrame* self, size_t amount, size_t alignment) +{ + if (self->memory_pad.memory == NULL) { + if (Scratchpad_Create(&self->memory_pad, 1024, NULL)) return NULL; + } + + return Scratchpad_ReserveAligned(&self->memory_pad, amount, alignment); +} + +bool CallFrame_IsExecutingCondition(CallFrame* frame) +{ + return frame->instruction_pointer >= frame->alternative->condition_token_start + && frame->instruction_pointer <= frame->alternative->condition_token_end; +} + +bool CallFrame_IsSelectingCondition(CallFrame* frame) +{ + return frame->instruction_pointer == frame->alternative->condition_token_end + 1; +} + +bool CallFrame_IsExecutingBody(CallFrame* frame) +{ + return frame->instruction_pointer < frame->alternative->body_token_end; +} + +bool CallFrame_IsReturningBody(CallFrame* frame) +{ + return frame->instruction_pointer == frame->alternative->body_token_end; +} + diff --git a/src/callframe.h b/src/callframe.h new file mode 100644 index 0000000..9f18051 --- /dev/null +++ b/src/callframe.h @@ -0,0 +1,59 @@ +/* + * This code is part of the programming language flup + * flup comes with ABSOLUTELY NO WARRANTY and is licensed under AGPL-3.0 or later. + * Copyright (C) 2024 VegOwOtenks + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef FLUP_CALLFRAME_H +#define FLUP_CALLFRAME_H + +#include "function.h" +#include "variable.h" +#include "value.h" +#include "dynamicarray/dynamicarray.h" +#include "StringView/StringView.h" +#include "Scratchpad/Scratchpad.h" + +typedef struct CallFrame_s { + size_t instruction_pointer; + /* ip = condition start : start + * ip = condition_end + 1 : done + * + */ + FlupFunction* self_function; + FlupFunctionAlternative* alternative; + FlupFunction* functions; // functions defined in this callframe + FlupVariable* variables; // variables defined in this callframe + DynamicArray stack; // Value + Scratchpad memory_pad; +} CallFrame; + +int CallFrame_Create(CallFrame* self, FlupFunction* self_function); +void CallFrame_Destroy(CallFrame* self); + +int CallFrame_DefineVariable(CallFrame* self, StringView name, Value value); +int CallFrame_StackPop(CallFrame* self, Value* dest); +int CallFrame_StackPush(CallFrame* self, Value* value); +FlupVariable* CallFrame_FindVariable(CallFrame* self, StringView name); +void* CallFrame_Reserve(CallFrame* self, size_t amount, size_t alignment); +bool CallFrame_IsExecutingCondition(CallFrame* frame); +bool CallFrame_IsSelectingCondition(CallFrame* frame); +bool CallFrame_IsExecutingBody(CallFrame* frame); +bool CallFrame_IsReturningBody(CallFrame* frame); + + + +#endif \ No newline at end of file diff --git a/src/function.h b/src/function.h new file mode 100644 index 0000000..1022709 --- /dev/null +++ b/src/function.h @@ -0,0 +1,48 @@ +/* + * This code is part of the programming language flup + * flup comes with ABSOLUTELY NO WARRANTY and is licensed under AGPL-3.0 or later. + * Copyright (C) 2024 VegOwOtenks + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef FLUP_FUNCTION_H +#define FLUP_FUNCTION_H + +#include +#include "StringView/StringView.h" + +typedef struct FlupFunctionAlternative_s { + size_t condition_token_start; + size_t condition_token_end; + size_t body_token_start; + size_t body_token_end; + struct FlupFunctionAlternative_s* next; +} FlupFunctionAlternative; + +typedef struct ParameterDefinition_s { + StringView type; + StringView name; + struct ParameterDefinition_s* next; +} ParameterDefinition; + +typedef struct FlupFunction_s { + StringView name; + ParameterDefinition* parameters; + StringView return_type; + FlupFunctionAlternative* alternatives; + struct FlupFunction_s* next; +} FlupFunction; + +#endif \ No newline at end of file diff --git a/src/interpreter.c b/src/interpreter.c index b677eb8..1630364 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -1,41 +1,9 @@ #include "interpreter.h" +#include "builtin-functions.h" #include #include -static int CallFrame_Create(CallFrame* self, FlupFunction* self_function) -{ - if (DynamicArray_Create(&self->stack, sizeof(Value), 8, NULL)) { - return ENOMEM; - } - self->memory_pad.memory = NULL; - self->self_function = self_function; - self->alternative = self->self_function->alternatives; - self->instruction_pointer = self->alternative->condition_token_start; - - self->variables = NULL; - self->functions = NULL; - - return EXIT_SUCCESS; -} - -static void CallFrame_Destroy(CallFrame* self) -{ - if (self->memory_pad.memory != NULL) { - Scratchpad_Destroy(&self->memory_pad); - } - - DynamicArray_Destroy(&self->stack); -} - -static void* CallFrame_Reserve(CallFrame* self, size_t amount, size_t alignment) -{ - if (self->memory_pad.memory == NULL) { - if (Scratchpad_Create(&self->memory_pad, 1024, NULL)) return NULL; - } - - return Scratchpad_ReserveAligned(&self->memory_pad, amount, alignment); -} static FlupFunctionAlternative* FlupFunctionAlternative_Malloc(size_t condition_token_start, size_t condition_token_end, size_t body_token_start, size_t body_token_end) { @@ -49,6 +17,17 @@ static FlupFunctionAlternative* FlupFunctionAlternative_Malloc(size_t condition_ return a; } +const char* standard_builtin_names[] = { + "println", + "duplicate", + NULL +}; + +const BuiltinFunction standard_builtin_functions[] = { + BuiltinFunction_PrintLine, + BuiltinFunction_Duplicate, +}; + int Interpreter_Create(Interpreter* self, DynamicArray* tokens) { if (DynamicArray_Create(&self->call_frames, sizeof(CallFrame), 16, NULL)) { @@ -56,6 +35,9 @@ int Interpreter_Create(Interpreter* self, DynamicArray* tokens) } self->tokens = tokens; + self->builtin_names = standard_builtin_names; + self->builtin_functions = standard_builtin_functions; + return EXIT_SUCCESS; } @@ -113,7 +95,7 @@ int Interpreter_ParseFunction(Interpreter* self, CallFrame* top_frame, size_t st return EXIT_FAILURE; } - *pdef = CallFrame_Reserve(top_frame, sizeof(**pdef), alignof(**pdef)); + *pdef = CallFrame_Reserve(top_frame, sizeof(ParameterDefinition), alignof(ParameterDefinition)); if (*pdef == NULL) { return ENOMEM; } @@ -192,7 +174,7 @@ int Interpreter_ParseFunction(Interpreter* self, CallFrame* top_frame, size_t st nested_functions_count > 0); size_t body_end = top_frame->instruction_pointer; - *fdef = CallFrame_Reserve(top_frame, sizeof(**pdef), alignof(**pdef)); + *fdef = CallFrame_Reserve(top_frame, sizeof(ParameterDefinition), alignof(ParameterDefinition)); if (*fdef == NULL) { return ENOMEM; } @@ -208,7 +190,7 @@ int Interpreter_ParseFunction(Interpreter* self, CallFrame* top_frame, size_t st return EXIT_FAILURE; } } - + // one token colon top_frame->instruction_pointer++; @@ -231,49 +213,23 @@ FlupFunction* Interpreter_FindFunction(Interpreter* self, StringView name) return NULL; } -bool _are_types_compatible(enum ValueType type, StringView type_name) +int Interpreter_CallBuiltinFunction(Interpreter* self, CallFrame* parent_frame, Token* name) { - 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 - && type == type_mapping[i] - && StringView_Equal(type_name, StringView_FromString(name_mapping[i])) - ) { - return true; + StringView function_name = name->get.identifier; + for (size_t i = 0; self->builtin_names[i] != NULL; i++) { + if (StringView_Equal(function_name, StringView_FromString(self->builtin_names[i]))) { + return self->builtin_functions[i](parent_frame); } } - return false; -} - -int CallFrame_DefineVariable(CallFrame* self, StringView name, Value value) -{ - FlupVariable* v = CallFrame_Reserve(self, sizeof(FlupVariable), alignof(FlupVariable)); - if (v == NULL) { - return ENOMEM; - } - - v->name = name; - v->value = value; - - v->next = self->variables; - self->variables = v; - - return EXIT_SUCCESS; + return EXIT_FAILURE; } int Interpreter_CallFunction(Interpreter* self, CallFrame* parent_frame, Token* name) { FlupFunction* function = Interpreter_FindFunction(self, name->get.identifier); if (function == NULL) { - // TODO: Error message - return EXIT_FAILURE; + return Interpreter_CallBuiltinFunction(self, parent_frame, name); } CallFrame* new_frame; @@ -300,7 +256,7 @@ int Interpreter_CallFunction(Interpreter* self, CallFrame* parent_frame, Token* ParameterDefinition* parameter_def = function->parameters; for (size_t stack_index = stack_size - argument_count; stack_index != stack_size; stack_index++, parameter_def = parameter_def->next) { Value* parameter_value = DynamicArray_GetPointer(&parent_frame->stack, stack_index); - if (! _are_types_compatible(parameter_value->type, parameter_def->type)) { + if (!Value_TypeMatchesStringName(parameter_value->type, parameter_def->type)) { // TODO: Error message return EXIT_FAILURE; } @@ -318,137 +274,6 @@ int Interpreter_CallFunction(Interpreter* self, CallFrame* parent_frame, Token* return EXIT_SUCCESS; } -FlupVariable* CallFrame_FindVariable(CallFrame* self, StringView name) -{ - for (FlupVariable* variable = self->variables; variable != NULL; variable = variable->next) { - if (StringView_Equal(variable->name, name)) { - return variable; - } - } - - return NULL; -} - -int CallFrame_StackPop(CallFrame* self, Value* dest) -{ - size_t stack_size = DynamicArray_GetLength(&self->stack); - Value* popped = DynamicArray_GetPointer(&self->stack, stack_size - 1); - if (popped == NULL) { - return ENOTFOUND; - } - - *dest = *popped; - DynamicArray_Remove(&self->stack, stack_size - 1); - - return EXIT_SUCCESS; -} - -int CallFrame_StackPush(CallFrame* self, Value* value) -{ - return DynamicArray_Append(&self->stack, value); -} - -bool Value_Equal(Value* v1, Value* v2) -{ - if (v1->type != v2->type) return false; - switch (v1->type) { - case VALUETYPE_INT64: - return v1->get.i64 == v2->get.i64; - case VALUETYPE_DOUBLE: - return v1->get.f64 == v2->get.f64; - case VALUETYPE_BOOLEAN: - return v1->get.boolean = v2->get.boolean; - } - - return false; -} - -int BuiltinFunction_Equality(CallFrame* top_frame) -{ - Value v1; - Value v2; - - CallFrame_StackPop(top_frame, &v1); - if (CallFrame_StackPop(top_frame, &v2) != EXIT_SUCCESS) { - // TODO: Error message - return EXIT_FAILURE; - } - - Value result; - result.type = VALUETYPE_BOOLEAN; - result.get.boolean = Value_Equal(&v1, &v2); - - top_frame->instruction_pointer++; - return CallFrame_StackPush(top_frame, &result); - -} - -int BuiltinFunction_Plus(CallFrame* top_frame) -{ - Value v1; - Value v2; - - CallFrame_StackPop(top_frame, &v1); - if (CallFrame_StackPop(top_frame, &v2) != EXIT_SUCCESS) { - // TODO: Error message - return EXIT_FAILURE; - } - if (v1.type != v2.type) { - // TODO: Error message - return EXIT_FAILURE; - } - - Value result; - result.type = v1.type; - switch (v1.type) { - case VALUETYPE_INT64: - result.get.i64 = v2.get.i64 + v1.get.i64; - break; - case VALUETYPE_DOUBLE: - result.get.f64 = v2.get.f64 + v1.get.f64; - break; - case VALUETYPE_BOOLEAN: - result.get.boolean = v2.get.boolean + v1.get.boolean; - break; - } - - top_frame->instruction_pointer++; - return CallFrame_StackPush(top_frame, &result); -} - -int BuiltinFunction_Minus(CallFrame* top_frame) -{ - Value v1; - Value v2; - - CallFrame_StackPop(top_frame, &v1); - if (CallFrame_StackPop(top_frame, &v2) != EXIT_SUCCESS) { - // TODO: Error message - return EXIT_FAILURE; - } - if (v1.type != v2.type) { - // TODO: Error message - return EXIT_FAILURE; - } - - Value result; - result.type = v1.type; - switch (v1.type) { - case VALUETYPE_INT64: - result.get.i64 = v2.get.i64 - v1.get.i64; - break; - case VALUETYPE_DOUBLE: - result.get.f64 = v2.get.f64 - v1.get.f64; - break; - case VALUETYPE_BOOLEAN: - result.get.boolean = v2.get.boolean - v1.get.boolean; - break; - } - - top_frame->instruction_pointer++; - 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; @@ -627,9 +452,14 @@ int Interpreter_ExecuteNext(Interpreter* self, size_t stop_token) // 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; + FlupVariable* var = CallFrame_FindVariable(top_frame, variable_name); + if (var != NULL) { + var->value = variable_value; + } else { + if (CallFrame_DefineVariable(top_frame, variable_name, variable_value)) { + // TODO: Error message + return EXIT_FAILURE; + } } top_frame->instruction_pointer += 2; // points to opening paren @@ -672,40 +502,6 @@ int Interpreter_ExecuteNext(Interpreter* self, size_t stop_token) return EXIT_SUCCESS; } -bool Value_IsTruthy(Value* v) -{ - switch (v->type) { - case VALUETYPE_INT64: - return v->get.i64 != 0; - case VALUETYPE_DOUBLE: - return v->get.f64 != 0.0; - case VALUETYPE_BOOLEAN: - return v->get.boolean; - } - - return false; -} - -static bool CallFrame_IsExecutingCondition(CallFrame* frame) -{ - return frame->instruction_pointer >= frame->alternative->condition_token_start - && frame->instruction_pointer <= frame->alternative->condition_token_end; -} - -static bool CallFrame_IsSelectingCondition(CallFrame* frame) -{ - return frame->instruction_pointer == frame->alternative->condition_token_end + 1; -} - -static bool CallFrame_IsExecutingBody(CallFrame* frame) -{ - return frame->instruction_pointer < frame->alternative->body_token_end; -} - -static bool CallFrame_IsReturningBody(CallFrame* frame) -{ - return frame->instruction_pointer == frame->alternative->body_token_end; -} #define RPN(a,b,c) a c b int Interpreter_RunFrame(Interpreter* self) @@ -779,7 +575,7 @@ int Interpreter_RunFrame(Interpreter* self) // StringView_Paste(function_name, top_frame->self_function->name); // printf("%s\n", function_name); - if (! _are_types_compatible(return_value.type, top_frame->self_function->return_type)) { + if (!Value_TypeMatchesStringName(return_value.type, top_frame->self_function->return_type)) { // TODO: Error message return EXIT_FAILURE; } @@ -834,11 +630,11 @@ int Interpreter_Interpret(Interpreter* self) } first_frame->instruction_pointer = 0; - Interpreter_Run(self); + int run_code = Interpreter_Run(self); free(main_alternative); - return EXIT_SUCCESS; + return run_code; } void Interpreter_Destroy(Interpreter* self) diff --git a/src/interpreter.h b/src/interpreter.h index 0ec4454..49f1b6a 100644 --- a/src/interpreter.h +++ b/src/interpreter.h @@ -5,74 +5,24 @@ #include "../submodules/utilitiec/src/Scratchpad/Scratchpad.h" #include "tokenizer.h" +#include "callframe.h" +#include "value.h" #include -typedef struct FlupFunctionAlternative_s { - size_t condition_token_start; - size_t condition_token_end; - size_t body_token_start; - size_t body_token_end; - struct FlupFunctionAlternative_s* next; -} FlupFunctionAlternative; +typedef struct Interpreter_s Interpreter; -typedef struct ParameterDefinition_s { - StringView type; - StringView name; - struct ParameterDefinition_s* next; -} ParameterDefinition; +typedef int (*BuiltinFunction)(CallFrame *); -typedef struct FlupFunction_s { - StringView name; - ParameterDefinition* parameters; - StringView return_type; - FlupFunctionAlternative* alternatives; - struct FlupFunction_s* next; -} FlupFunction; +struct Interpreter_s { + const char** builtin_names; + const BuiltinFunction* builtin_functions; -enum ValueType { - VALUETYPE_INT64, - VALUETYPE_DOUBLE, - VALUETYPE_BOOLEAN, -}; - -union ValueContent { - int64_t i64; - double f64; - bool boolean; -}; - -typedef struct Value_s { - enum ValueType type; - union ValueContent get; -} Value; - -typedef struct FlupVariable_s { - StringView name; - Value value; - struct FlupVariable_s* next; -} FlupVariable; - -typedef struct CallFrame_s { - size_t instruction_pointer; - /* ip = condition start : start - * ip = condition_end + 1 : done - * - */ - FlupFunction* self_function; - FlupFunctionAlternative* alternative; - FlupFunction* functions; // functions defined in this callframe - FlupVariable* variables; // variables defined in this callframe - DynamicArray stack; // Value - Scratchpad memory_pad; -} CallFrame; - -typedef struct Interpreter_s { DynamicArray* tokens; DynamicArray call_frames; // stores CallFrame -} Interpreter; +}; int Interpreter_Create(Interpreter* self, DynamicArray* tokens); int Interpreter_Interpret(Interpreter* self); void Interpreter_Destroy(Interpreter* self); -#endif //header guard +#endif //FLUP_INTERPRETER_H diff --git a/src/main.c b/src/main.c index ab9e660..4e9bba1 100644 --- a/src/main.c +++ b/src/main.c @@ -113,12 +113,12 @@ int main(int argc, const char* argv []) Interpreter_Create(&interpreter, &tokens); - Interpreter_Interpret(&interpreter); + int interpret_code = Interpreter_Interpret(&interpreter); Interpreter_Destroy(&interpreter); DynamicArray_Destroy(&tokens); free(script_string); - return EXIT_SUCCESS; + return interpret_code; } diff --git a/src/value.c b/src/value.c new file mode 100644 index 0000000..61e7835 --- /dev/null +++ b/src/value.c @@ -0,0 +1,72 @@ +/* + * This code is part of the programming language flup + * flup comes with ABSOLUTELY NO WARRANTY and is licensed under AGPL-3.0 or later. + * Copyright (C) 2024 VegOwOtenks + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "value.h" + + +bool Value_IsTruthy(Value* v) +{ + switch (v->type) { + case VALUETYPE_INT64: + return v->get.i64 != 0; + case VALUETYPE_DOUBLE: + return v->get.f64 != 0.0; + case VALUETYPE_BOOLEAN: + return v->get.boolean; + } + + return false; +} + +bool Value_Equal(Value* v1, Value* v2) +{ + if (v1->type != v2->type) return false; + switch (v1->type) { + case VALUETYPE_INT64: + return v1->get.i64 == v2->get.i64; + case VALUETYPE_DOUBLE: + return v1->get.f64 == v2->get.f64; + case VALUETYPE_BOOLEAN: + return v1->get.boolean = v2->get.boolean; + } + + return false; +} + +bool Value_TypeMatchesStringName(enum ValueType type, StringView type_name) +{ + 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 + && type == type_mapping[i] + && StringView_Equal(type_name, StringView_FromString(name_mapping[i])) + ) { + return true; + } + } + + return false; +} + diff --git a/src/value.h b/src/value.h new file mode 100644 index 0000000..1ac4f26 --- /dev/null +++ b/src/value.h @@ -0,0 +1,49 @@ +/* + * This code is part of the programming language flup + * flup comes with ABSOLUTELY NO WARRANTY and is licensed under AGPL-3.0 or later. + * Copyright (C) 2024 VegOwOtenks + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef FLUP_VALUE_H +#define FLUP_VALUE_H + +#include +#include +#include "StringView/StringView.h" + +enum ValueType { + VALUETYPE_INT64, + VALUETYPE_DOUBLE, + VALUETYPE_BOOLEAN, +}; + +union ValueContent { + int64_t i64; + double f64; + bool boolean; +}; + +typedef struct Value_s { + enum ValueType type; + union ValueContent get; +} Value; + +bool Value_IsTruthy(Value* v); +bool Value_Equal(Value* v1, Value* v2); +bool Value_TypeMatchesStringName(enum ValueType type, StringView type_name); + + +#endif diff --git a/src/variable.h b/src/variable.h new file mode 100644 index 0000000..149e171 --- /dev/null +++ b/src/variable.h @@ -0,0 +1,32 @@ +/* + * This code is part of the programming language flup + * flup comes with ABSOLUTELY NO WARRANTY and is licensed under AGPL-3.0 or later. + * Copyright (C) 2024 VegOwOtenks + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef FLUP_VARIABLE_H +#define FLUP_VARIABLE_H + +#include "value.h" +#include "StringView/StringView.h" + +typedef struct FlupVariable_s { + StringView name; + Value value; + struct FlupVariable_s* next; +} FlupVariable; + +#endif \ No newline at end of file