cleanup and implementation of builtin functions

This commit is contained in:
Alexander Acker 2024-10-08 17:17:10 +02:00
parent 78bb3321d8
commit 06f385d6b0
11 changed files with 621 additions and 302 deletions

154
src/builtin-functions.c Normal file
View file

@ -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 <stdlib.h>
#include <stdio.h>
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;
}

34
src/builtin-functions.h Normal file
View file

@ -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

125
src/callframe.c Normal file
View file

@ -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 <stdalign.h>
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;
}

59
src/callframe.h Normal file
View file

@ -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

48
src/function.h Normal file
View file

@ -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 <stdlib.h>
#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

View file

@ -1,41 +1,9 @@
#include "interpreter.h"
#include "builtin-functions.h"
#include <stdio.h>
#include <stdalign.h>
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)

View file

@ -5,74 +5,24 @@
#include "../submodules/utilitiec/src/Scratchpad/Scratchpad.h"
#include "tokenizer.h"
#include "callframe.h"
#include "value.h"
#include <stdint.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 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

View file

@ -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;
}

72
src/value.c Normal file
View file

@ -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;
}

49
src/value.h Normal file
View file

@ -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 <stdint.h>
#include <stdbool.h>
#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

32
src/variable.h Normal file
View file

@ -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