// Kyler Olsen
// YREA SLS
// Interpreter Header
// November 2025

#ifndef SLS_INTERPRETER_H
#define SLS_INTERPRETER_H

#include <stddef.h>

#include "sls/bool.h"
#include "sls/lexer.h"
#include "sls/hash_table.h"

typedef enum {
    STACK_IDENTIFIER,
    STACK_I64,
    STACK_I32,
    STACK_I16,
    STACK_I8,
    STACK_U64,
    STACK_U32,
    STACK_U16,
    STACK_U8,
    STACK_FLOAT,
    STACK_DOUBLE,
    STACK_CHARACTER,
    STACK_BOOLEAN,
    STACK_TOKEN_STRING,
    STACK_CALLABLE,
} StackType;

extern const char *STACK_TYPES_NAMES[];
extern const char *STACK_TYPES_TYPES[];
extern const size_t STACK_TYPE_COUNT;

typedef struct StackItem {
    StackType type;
    union {
        Identifier identifier; // type == STACK_IDENTIFIER
        int64_t i64; // type == STACK_I64
        int32_t i32; // type == STACK_I32
        int16_t i16; // type == STACK_I16
        int8_t i8; // type == STACK_I8
        uint64_t u64; // type == STACK_U64
        uint32_t u32; // type == STACK_U32
        uint16_t u16; // type == STACK_U16
        uint8_t u8; // type == STACK_U8
        float f32; // type == STACK_FLOAT
        double f64; // type == STACK_DOUBLE
        uint8_t character; // type == STACK_CHARACTER
        Boolean boolean; // type == STACK_BOOLEAN
        TokenString token_string; // type == STACK_TOKEN_STRING
    };
    struct StackItem *next;
} StackItem;

typedef struct {
    StackItem *stack;
    HashTable *functions;
} InterpreterState;

typedef enum {
    FUNCTION_TOKEN_STRING,
    FUNCTION_BUILTIN,
} FunctionType;

typedef struct {
    FunctionType type;
    union {
        TokenString token_string; // type == FUNCTION_TOKEN_STRING
        Boolean (*builtin)(InterpreterState *); // type == FUNCTION_BUILTIN
    };
} FunctionItem;

Boolean push_token(InterpreterState *interpreter_state, Token token);
void clean_stack(StackItem *item);

Boolean execute_func(InterpreterState *interpreter_state, SlsStr key);
Boolean execute_token_string(InterpreterState *interpreter_state, TokenString token_string);
Boolean execute(InterpreterState *interpreter_state, LexerTokenResult *token);
InterpreterState *interpreter_create();
void interpreter_delete(InterpreterState *interpreter_state);

#endif // SLS_INTERPRETER_H
