// Kyler Olsen // YREA SLS // Interpreter // November 2025 #include #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); }