YREA-SLS/SLS_C/src/interpreter.c

201 lines
5.4 KiB
C

// Kyler Olsen
// YREA SLS
// Interpreter
// November 2025
#include <stdlib.h>
#include "sls/string.h"
#include "sls/interpreter.h"
#include "sls/lexer.h"
#include "sls/hash_table.h"
#include "sls/builtin.h"
static const size_t HASH_TABLE_BUCKET_COUNT = 256;
const char *STACK_TYPES_NAMES[] = {
"Identifier",
"64-bit Integer",
"32-bit Integer",
"16-bit Integer",
"8-bit Integer",
"64-bit U Integer",
"32-bit U Integer",
"16-bit U Integer",
"8-bit U Integer",
"Float",
"Double",
"Character",
"Boolean",
"Token String",
};
const size_t STACK_TYPE_COUNT = sizeof(STACK_TYPES_NAMES) / sizeof(*STACK_TYPES_NAMES);
static inline Boolean hash_table_put_funcs(HashTable *ht, SlsStr key, FunctionItem *item) {
return hash_table_put(ht, key, (void *)item);
}
static inline FunctionItem *hash_table_get_funcs(const HashTable *ht, SlsStr key, FunctionItem *default_item) {
return (FunctionItem*)hash_table_get(ht, key, (void *)default_item);
}
Boolean push_token(InterpreterState *interpreter_state, Token token) {
StackType type;
switch (token.type) {
case TOKEN_EOF:
return TRUE;
case TOKEN_IDENTIFIER:
type = STACK_IDENTIFIER;
break;
case TOKEN_INTEGER:
switch (token.integer_literal.type) {
case INTEGER_I64:
type = STACK_I64;
break;
case INTEGER_I32:
type = STACK_I32;
break;
case INTEGER_I16:
type = STACK_I16;
break;
case INTEGER_I8:
type = STACK_I8;
break;
case INTEGER_U64:
type = STACK_U64;
break;
case INTEGER_U32:
type = STACK_U32;
break;
case INTEGER_U16:
type = STACK_U16;
break;
case INTEGER_U8:
type = STACK_U8;
break;
}
break;
case TOKEN_FLOAT:
type = STACK_FLOAT;
break;
case TOKEN_DOUBLE:
type = STACK_DOUBLE;
break;
case TOKEN_CHARACTER:
type = STACK_CHARACTER;
break;
case TOKEN_STRING:
return FALSE;
case TOKEN_BOOLEAN:
type = STACK_BOOLEAN;
break;
case TOKEN_ARRAY:
return FALSE;
case TOKEN_TOKEN_STRING:
type = STACK_TOKEN_STRING;
break;
case TOKEN_TYPE_TUPLE:
return FALSE;
}
StackItem *item = (StackItem *)malloc(sizeof(StackItem));
if (item == NULL) return FALSE;
item->type = type;
item->next = interpreter_state->stack;
interpreter_state->stack = item;
switch (type) {
case STACK_IDENTIFIER:
item->identifier = token.identifier;
break;
case STACK_I64:
item->i64 = (int64_t)token.integer_literal.value;
break;
case STACK_I32:
item->i32 = (int32_t)token.integer_literal.value;
break;
case STACK_I16:
item->i16 = (int16_t)token.integer_literal.value;
break;
case STACK_I8:
item->i8 = (int8_t)token.integer_literal.value;
break;
case STACK_U64:
item->u64 = (uint64_t)token.integer_literal.value;
break;
case STACK_U32:
item->u32 = (uint32_t)token.integer_literal.value;
break;
case STACK_U16:
item->u16 = (uint16_t)token.integer_literal.value;
break;
case STACK_U8:
item->u8 = (uint8_t)token.integer_literal.value;
break;
case STACK_FLOAT:
item->f32 = token.float_literal;
break;
case STACK_DOUBLE:
item->f64 = token.double_literal;
break;
case STACK_CHARACTER:
item->character = token.character_literal;
break;
case STACK_BOOLEAN:
item->boolean = token.boolean_literal;
break;
case STACK_TOKEN_STRING:
item->token_string = copy_token_string(token.token_string);
break;
}
return TRUE;
}
static Boolean execute_func(InterpreterState *interpreter_state, SlsStr key) {
FunctionItem *func = hash_table_get_funcs(interpreter_state->functions, key, NULL);
if (func == NULL) return FALSE;
switch (func->type) {
case FUNCTION_BUILTIN:
return func->builtin(interpreter_state);
case FUNCTION_TOKEN_STRING:
return FALSE;
}
return FALSE;
}
Boolean execute(InterpreterState *interpreter_state, LexerTokenResult *token) {
if (token->result.type == TOKEN_IDENTIFIER && !token->result.identifier.is_literal)
return execute_func(interpreter_state, token->result.identifier.name);
else
return push_token(interpreter_state, token->result);
}
InterpreterState *interpreter_create() {
InterpreterState *interpreter_state = (InterpreterState *)malloc(sizeof(InterpreterState));
if (interpreter_state == NULL)
return NULL;
interpreter_state->stack = NULL;
interpreter_state->functions = init_hash_table(HASH_TABLE_BUCKET_COUNT);
if (!load_builtins(interpreter_state)) {
interpreter_delete(interpreter_state);
return NULL;
}
return interpreter_state;
}
void clean_stack(StackItem *item) {
if (item == NULL) return;
if (item->type == STACK_TOKEN_STRING)
clean_token_string(item->token_string);
clean_stack(item->next);
free(item);
}
void interpreter_delete(InterpreterState *interpreter_state) {
clean_stack(interpreter_state->stack);
del_hash_table(interpreter_state->functions);
free(interpreter_state);
}