Implements binding variables (including name shadowing)

This commit is contained in:
VegOwOtenks 2024-10-08 13:57:46 +02:00
parent 8ab0282199
commit b7f11d1fc2

View file

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