2218 lines
74 KiB
C
2218 lines
74 KiB
C
// Kyler Olsen
|
|
// YREA SLS
|
|
// Builtin Functions
|
|
// November 2025
|
|
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
|
|
#include "sls/bool.h"
|
|
#include "sls/builtin.h"
|
|
#include "sls/hash_table.h"
|
|
#include "sls/interpreter.h"
|
|
#include "sls/lexer.h"
|
|
#include "sls/file.h"
|
|
|
|
Boolean builtin_addition(InterpreterState *interpreter_state);
|
|
Boolean builtin_subtraction(InterpreterState *interpreter_state);
|
|
Boolean builtin_multiplication(InterpreterState *interpreter_state);
|
|
Boolean builtin_division(InterpreterState *interpreter_state);
|
|
Boolean builtin_modulus(InterpreterState *interpreter_state);
|
|
Boolean builtin_exponential(InterpreterState *interpreter_state);
|
|
Boolean builtin_greater_than(InterpreterState *interpreter_state);
|
|
Boolean builtin_greater_than_or_equal_to(InterpreterState *interpreter_state);
|
|
Boolean builtin_less_than(InterpreterState *interpreter_state);
|
|
Boolean builtin_less_than_or_equal_to(InterpreterState *interpreter_state);
|
|
Boolean builtin_equal_to(InterpreterState *interpreter_state);
|
|
Boolean builtin_not_equal_to(InterpreterState *interpreter_state);
|
|
Boolean builtin_abs(InterpreterState *interpreter_state);
|
|
Boolean builtin_acos(InterpreterState *interpreter_state);
|
|
Boolean builtin_and(InterpreterState *interpreter_state);
|
|
Boolean builtin_asin(InterpreterState *interpreter_state);
|
|
// Boolean builtin_assert(InterpreterState *interpreter_state);
|
|
// Boolean builtin_at(InterpreterState *interpreter_state);
|
|
Boolean builtin_atan(InterpreterState *interpreter_state);
|
|
Boolean builtin_atan2(InterpreterState *interpreter_state);
|
|
Boolean builtin_bitand(InterpreterState *interpreter_state);
|
|
Boolean builtin_bitnot(InterpreterState *interpreter_state);
|
|
Boolean builtin_bitor(InterpreterState *interpreter_state);
|
|
Boolean builtin_bitxor(InterpreterState *interpreter_state);
|
|
Boolean builtin_ceil(InterpreterState *interpreter_state);
|
|
// Boolean builtin_concat(InterpreterState *interpreter_state);
|
|
Boolean builtin_const(InterpreterState *interpreter_state);
|
|
Boolean builtin_cos(InterpreterState *interpreter_state);
|
|
Boolean builtin_depth(InterpreterState *interpreter_state);
|
|
Boolean builtin_drop(InterpreterState *interpreter_state);
|
|
Boolean builtin_dup(InterpreterState *interpreter_state);
|
|
// Boolean builtin_each(InterpreterState *interpreter_state);
|
|
// Boolean builtin_ends_with(InterpreterState *interpreter_state);
|
|
// Boolean builtin_enum(InterpreterState *interpreter_state);
|
|
// Boolean builtin_enumerate(InterpreterState *interpreter_state);
|
|
Boolean builtin_eval(InterpreterState *interpreter_state);
|
|
// Boolean builtin_filter(InterpreterState *interpreter_state);
|
|
// Boolean builtin_find(InterpreterState *interpreter_state);
|
|
Boolean builtin_floor(InterpreterState *interpreter_state);
|
|
// Boolean builtin_fn(InterpreterState *interpreter_state);
|
|
// Boolean builtin_foldl(InterpreterState *interpreter_state);
|
|
// Boolean builtin_foldr(InterpreterState *interpreter_state);
|
|
Boolean builtin_for(InterpreterState *interpreter_state);
|
|
// Boolean builtin_format(InterpreterState *interpreter_state);
|
|
// Boolean builtin_get(InterpreterState *interpreter_state);
|
|
Boolean builtin_if(InterpreterState *interpreter_state);
|
|
// Boolean builtin_impl(InterpreterState *interpreter_state);
|
|
// Boolean builtin_implements(InterpreterState *interpreter_state);
|
|
// Boolean builtin_inher(InterpreterState *interpreter_state);
|
|
Boolean builtin_lambda(InterpreterState *interpreter_state);
|
|
// Boolean builtin_length(InterpreterState *interpreter_state);
|
|
Boolean builtin_ln(InterpreterState *interpreter_state);
|
|
Boolean builtin_log(InterpreterState *interpreter_state);
|
|
// Boolean builtin_map(InterpreterState *interpreter_state);
|
|
// Boolean builtin_match(InterpreterState *interpreter_state);
|
|
// Boolean builtin_mean(InterpreterState *interpreter_state);
|
|
Boolean builtin_not(InterpreterState *interpreter_state);
|
|
Boolean builtin_or(InterpreterState *interpreter_state);
|
|
// Boolean builtin_over(InterpreterState *interpreter_state);
|
|
Boolean builtin_pick(InterpreterState *interpreter_state);
|
|
Boolean builtin_rand(InterpreterState *interpreter_state);
|
|
// Boolean builtin_reduce(InterpreterState *interpreter_state);
|
|
// Boolean builtin_replace(InterpreterState *interpreter_state);
|
|
// Boolean builtin_reverse(InterpreterState *interpreter_state);
|
|
Boolean builtin_roll(InterpreterState *interpreter_state);
|
|
Boolean builtin_round(InterpreterState *interpreter_state);
|
|
Boolean builtin_seed(InterpreterState *interpreter_state);
|
|
// Boolean builtin_set(InterpreterState *interpreter_state);
|
|
Boolean builtin_shl(InterpreterState *interpreter_state);
|
|
Boolean builtin_shr(InterpreterState *interpreter_state);
|
|
Boolean builtin_sin(InterpreterState *interpreter_state);
|
|
// Boolean builtin_slice(InterpreterState *interpreter_state);
|
|
// Boolean builtin_split(InterpreterState *interpreter_state);
|
|
Boolean builtin_sqrt(InterpreterState *interpreter_state);
|
|
// Boolean builtin_starts_with(InterpreterState *interpreter_state);
|
|
// Boolean builtin_struct(InterpreterState *interpreter_state);
|
|
// Boolean builtin_substr(InterpreterState *interpreter_state);
|
|
// Boolean builtin_sum(InterpreterState *interpreter_state);
|
|
Boolean builtin_swap(InterpreterState *interpreter_state);
|
|
Boolean builtin_tan(InterpreterState *interpreter_state);
|
|
// Boolean builtin_trait(InterpreterState *interpreter_state);
|
|
// Boolean builtin_transpose(InterpreterState *interpreter_state);
|
|
// Boolean builtin_trim(InterpreterState *interpreter_state);
|
|
Boolean builtin_type_of(InterpreterState *interpreter_state);
|
|
// Boolean builtin_union(InterpreterState *interpreter_state);
|
|
Boolean builtin_while(InterpreterState *interpreter_state);
|
|
// Boolean builtin_window(InterpreterState *interpreter_state);
|
|
// Boolean builtin_zip(InterpreterState *interpreter_state);
|
|
|
|
static inline Boolean hash_table_put_funcs(HashTable *ht, SlsStr key, FunctionItem *item) {
|
|
return hash_table_put(ht, key, (void *)item);
|
|
}
|
|
|
|
typedef enum {
|
|
NUMERIC_FLOAT = 1 << 0,
|
|
NUMERIC_SIGNED = 1 << 1,
|
|
NUMERIC_64 = 1 << 2,
|
|
NUMERIC_32 = 1 << 3,
|
|
NUMERIC_16 = 1 << 4,
|
|
NUMERIC_8 = 1 << 5,
|
|
} NumericTypes;
|
|
|
|
|
|
Boolean load_builtins(InterpreterState *interpreter_state) {
|
|
FunctionItem *func;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_addition};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("+"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_subtraction};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("-"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_multiplication};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("*"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_division};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("/"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_modulus};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("%"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_exponential};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("^"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_greater_than};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR(">"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_greater_than_or_equal_to};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR(">="), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_less_than};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("<"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_less_than_or_equal_to};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("<="), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_equal_to};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("=="), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_not_equal_to};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("!="), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_abs};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("abs"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_acos};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("acos"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_and};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("acos"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_asin};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("asin"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_atan};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("atan"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_atan2};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("atan2"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_bitand};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("bitand"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_bitnot};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("bitnot"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_bitor};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("bitor"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_bitxor};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("bitxor"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_ceil};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("ceil"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_const};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("const"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_cos};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("cos"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_depth};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("depth"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_drop};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("drop"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_dup};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("dup"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_eval};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("eval"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_floor};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("floor"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_for};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("for"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_if};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("if"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_lambda};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("lambda"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_ln};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("ln"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_log};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("log"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_not};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("not"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_or};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("or"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_pick};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("pick"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_rand};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("rand"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_roll};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("roll"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_round};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("round"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_seed};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("seed"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_shl};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("shl"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_shr};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("shr"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_sin};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("sin"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_sqrt};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("sqrt"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_swap};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("swap"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_tan};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("tan"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_type_of};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("type_of"), func))
|
|
return FALSE;
|
|
|
|
func = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (func == NULL) return FALSE;
|
|
*func = (FunctionItem){ .type = FUNCTION_BUILTIN, .builtin = *builtin_while};
|
|
if (!hash_table_put_funcs(interpreter_state->functions, SLS_STR("while"), func))
|
|
return FALSE;
|
|
|
|
LexerInfo lexer_info;
|
|
init_lexer(&lexer_info, SLS_STR("__builtin.sls"), SLS_STR(
|
|
"// Kyler Olsen\n"
|
|
"// YREA SLS\n"
|
|
"// SLS Defined Builtin Operators\n"
|
|
"// November 2025\n"
|
|
"\n"
|
|
"{ ln swap ln swap / } lambda ::logb const\n"
|
|
"{ 1 pick 1 pick < { swap drop } { drop } if } lambda ::max const\n"
|
|
"{ 1 pick 1 pick < { drop } { swap drop } if } lambda ::min const\n"
|
|
"{ 3 1 roll } lambda ::rot const\n"
|
|
));
|
|
LexerResult result = lexical_analysis(&lexer_info);
|
|
if (result.type == SLS_ERROR) {
|
|
sls_str_free(&result.error.message);
|
|
return FALSE;
|
|
} else {
|
|
LexerTokenResult *head = result.result;
|
|
while (head) {
|
|
if (head->type == SLS_ERROR) {
|
|
sls_str_free(&result.error.message);
|
|
clean_token_result(result.result);
|
|
return FALSE;
|
|
} else if (!execute(interpreter_state, head)) {
|
|
clean_token_result(result.result);
|
|
return FALSE;
|
|
}
|
|
head = head->next;
|
|
}
|
|
clean_token_result(result.result);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#define NUMERIC_TYPE \
|
|
double af = 0; \
|
|
uint64_t ai = 0; \
|
|
uint64_t type = 0; \
|
|
if (interpreter_state->stack == NULL) return FALSE; \
|
|
\
|
|
switch (interpreter_state->stack->type) { \
|
|
case STACK_IDENTIFIER: \
|
|
return FALSE; \
|
|
case STACK_I64: \
|
|
ai = interpreter_state->stack->i64; \
|
|
af = interpreter_state->stack->i64; \
|
|
type |= NUMERIC_64; \
|
|
type |= NUMERIC_SIGNED; \
|
|
break; \
|
|
case STACK_I32: \
|
|
ai = interpreter_state->stack->i32; \
|
|
af = interpreter_state->stack->i32; \
|
|
type |= NUMERIC_32; \
|
|
type |= NUMERIC_SIGNED; \
|
|
break; \
|
|
case STACK_I16: \
|
|
ai = interpreter_state->stack->i16; \
|
|
af = interpreter_state->stack->i16; \
|
|
type |= NUMERIC_16; \
|
|
type |= NUMERIC_SIGNED; \
|
|
break; \
|
|
case STACK_I8: \
|
|
ai = interpreter_state->stack->i8; \
|
|
af = interpreter_state->stack->i8; \
|
|
type |= NUMERIC_8; \
|
|
type |= NUMERIC_SIGNED; \
|
|
break; \
|
|
case STACK_U64: \
|
|
ai = interpreter_state->stack->u64; \
|
|
af = interpreter_state->stack->u64; \
|
|
type |= NUMERIC_64; \
|
|
break; \
|
|
case STACK_U32: \
|
|
ai = interpreter_state->stack->u32; \
|
|
af = interpreter_state->stack->u32; \
|
|
type |= NUMERIC_32; \
|
|
break; \
|
|
case STACK_U16: \
|
|
ai = interpreter_state->stack->u16; \
|
|
af = interpreter_state->stack->u16; \
|
|
type |= NUMERIC_16; \
|
|
break; \
|
|
case STACK_U8: \
|
|
ai = interpreter_state->stack->u8; \
|
|
af = interpreter_state->stack->u8; \
|
|
type |= NUMERIC_8; \
|
|
break; \
|
|
case STACK_FLOAT: \
|
|
af = interpreter_state->stack->f32; \
|
|
type |= NUMERIC_32; \
|
|
type |= NUMERIC_FLOAT; \
|
|
break; \
|
|
case STACK_DOUBLE: \
|
|
af = interpreter_state->stack->f64; \
|
|
type |= NUMERIC_64; \
|
|
type |= NUMERIC_FLOAT; \
|
|
break; \
|
|
case STACK_CHARACTER: \
|
|
ai = interpreter_state->stack->character; \
|
|
af = interpreter_state->stack->character; \
|
|
break; \
|
|
case STACK_BOOLEAN: \
|
|
ai = interpreter_state->stack->boolean; \
|
|
af = interpreter_state->stack->boolean; \
|
|
break; \
|
|
case STACK_TOKEN_STRING: \
|
|
case STACK_CALLABLE: \
|
|
return FALSE; \
|
|
} \
|
|
|
|
#define NUMERIC_TYPES \
|
|
double af = 0, bf = 0; \
|
|
uint64_t ai = 0, bi = 0; \
|
|
uint64_t type = 0; \
|
|
if (interpreter_state->stack == NULL) return FALSE; \
|
|
if (interpreter_state->stack->next == NULL) return FALSE; \
|
|
\
|
|
switch (interpreter_state->stack->type) { \
|
|
case STACK_IDENTIFIER: \
|
|
return FALSE; \
|
|
case STACK_I64: \
|
|
ai = interpreter_state->stack->i64; \
|
|
af = interpreter_state->stack->i64; \
|
|
type |= NUMERIC_64; \
|
|
type |= NUMERIC_SIGNED; \
|
|
break; \
|
|
case STACK_I32: \
|
|
ai = interpreter_state->stack->i32; \
|
|
af = interpreter_state->stack->i32; \
|
|
type |= NUMERIC_32; \
|
|
type |= NUMERIC_SIGNED; \
|
|
break; \
|
|
case STACK_I16: \
|
|
ai = interpreter_state->stack->i16; \
|
|
af = interpreter_state->stack->i16; \
|
|
type |= NUMERIC_16; \
|
|
type |= NUMERIC_SIGNED; \
|
|
break; \
|
|
case STACK_I8: \
|
|
ai = interpreter_state->stack->i8; \
|
|
af = interpreter_state->stack->i8; \
|
|
type |= NUMERIC_8; \
|
|
type |= NUMERIC_SIGNED; \
|
|
break; \
|
|
case STACK_U64: \
|
|
ai = interpreter_state->stack->u64; \
|
|
af = interpreter_state->stack->u64; \
|
|
type |= NUMERIC_64; \
|
|
break; \
|
|
case STACK_U32: \
|
|
ai = interpreter_state->stack->u32; \
|
|
af = interpreter_state->stack->u32; \
|
|
type |= NUMERIC_32; \
|
|
break; \
|
|
case STACK_U16: \
|
|
ai = interpreter_state->stack->u16; \
|
|
af = interpreter_state->stack->u16; \
|
|
type |= NUMERIC_16; \
|
|
break; \
|
|
case STACK_U8: \
|
|
ai = interpreter_state->stack->u8; \
|
|
af = interpreter_state->stack->u8; \
|
|
type |= NUMERIC_8; \
|
|
break; \
|
|
case STACK_FLOAT: \
|
|
af = interpreter_state->stack->f32; \
|
|
type |= NUMERIC_32; \
|
|
type |= NUMERIC_FLOAT; \
|
|
break; \
|
|
case STACK_DOUBLE: \
|
|
af = interpreter_state->stack->f64; \
|
|
type |= NUMERIC_64; \
|
|
type |= NUMERIC_FLOAT; \
|
|
break; \
|
|
case STACK_CHARACTER: \
|
|
ai = interpreter_state->stack->character; \
|
|
af = interpreter_state->stack->character; \
|
|
break; \
|
|
case STACK_BOOLEAN: \
|
|
ai = interpreter_state->stack->boolean; \
|
|
af = interpreter_state->stack->boolean; \
|
|
break; \
|
|
case STACK_TOKEN_STRING: \
|
|
case STACK_CALLABLE: \
|
|
return FALSE; \
|
|
} \
|
|
\
|
|
switch (interpreter_state->stack->next->type) { \
|
|
case STACK_IDENTIFIER: \
|
|
return FALSE; \
|
|
case STACK_I64: \
|
|
bi = interpreter_state->stack->next->i64; \
|
|
bf = interpreter_state->stack->next->i64; \
|
|
type |= NUMERIC_64; \
|
|
type |= NUMERIC_SIGNED; \
|
|
break; \
|
|
case STACK_I32: \
|
|
bi = interpreter_state->stack->next->i32; \
|
|
bf = interpreter_state->stack->next->i32; \
|
|
type |= NUMERIC_32; \
|
|
type |= NUMERIC_SIGNED; \
|
|
break; \
|
|
case STACK_I16: \
|
|
bi = interpreter_state->stack->next->i16; \
|
|
bf = interpreter_state->stack->next->i16; \
|
|
type |= NUMERIC_16; \
|
|
type |= NUMERIC_SIGNED; \
|
|
break; \
|
|
case STACK_I8: \
|
|
bi = interpreter_state->stack->next->i8; \
|
|
bf = interpreter_state->stack->next->i8; \
|
|
type |= NUMERIC_8; \
|
|
type |= NUMERIC_SIGNED; \
|
|
break; \
|
|
case STACK_U64: \
|
|
bi = interpreter_state->stack->next->u64; \
|
|
bf = interpreter_state->stack->next->u64; \
|
|
type |= NUMERIC_64; \
|
|
break; \
|
|
case STACK_U32: \
|
|
bi = interpreter_state->stack->next->u32; \
|
|
bf = interpreter_state->stack->next->u32; \
|
|
type |= NUMERIC_32; \
|
|
break; \
|
|
case STACK_U16: \
|
|
bi = interpreter_state->stack->next->u16; \
|
|
bf = interpreter_state->stack->next->u16; \
|
|
type |= NUMERIC_16; \
|
|
break; \
|
|
case STACK_U8: \
|
|
bi = interpreter_state->stack->next->u8; \
|
|
bf = interpreter_state->stack->next->u8; \
|
|
type |= NUMERIC_8; \
|
|
break; \
|
|
case STACK_FLOAT: \
|
|
bf = interpreter_state->stack->next->f32; \
|
|
type |= NUMERIC_32; \
|
|
type |= NUMERIC_FLOAT; \
|
|
break; \
|
|
case STACK_DOUBLE: \
|
|
bf = interpreter_state->stack->next->f64; \
|
|
type |= NUMERIC_64; \
|
|
type |= NUMERIC_FLOAT; \
|
|
break; \
|
|
case STACK_CHARACTER: \
|
|
bi = interpreter_state->stack->next->character; \
|
|
bf = interpreter_state->stack->next->character; \
|
|
break; \
|
|
case STACK_BOOLEAN: \
|
|
bi = interpreter_state->stack->next->boolean; \
|
|
bf = interpreter_state->stack->next->boolean; \
|
|
break; \
|
|
case STACK_TOKEN_STRING: \
|
|
case STACK_CALLABLE: \
|
|
return FALSE; \
|
|
} \
|
|
|
|
#define FLOAT_FUNCTION(func) \
|
|
(void)ai; \
|
|
(void)type; \
|
|
\
|
|
StackItem *node = interpreter_state->stack; \
|
|
interpreter_state->stack = interpreter_state->stack->next; \
|
|
node->next = NULL; \
|
|
clean_stack(node); \
|
|
\
|
|
return push_token(interpreter_state, (Token){ \
|
|
.type = SLS_FLOAT_BUILTIN_DEFAULT, \
|
|
.double_literal = func(af), \
|
|
}); \
|
|
|
|
#define ARITHMETIC(op) \
|
|
StackItem *node = interpreter_state->stack; \
|
|
interpreter_state->stack = interpreter_state->stack->next->next; \
|
|
node->next->next = NULL; \
|
|
clean_stack(node); \
|
|
\
|
|
if (type & NUMERIC_FLOAT && type & NUMERIC_64) { \
|
|
return push_token(interpreter_state, (Token){ \
|
|
.type = TOKEN_DOUBLE, \
|
|
.double_literal = bf op af, \
|
|
}); \
|
|
} else if (type & NUMERIC_FLOAT) { \
|
|
return push_token(interpreter_state, (Token){ \
|
|
.type = TOKEN_FLOAT, \
|
|
.float_literal = (float)bf op (float)af, \
|
|
}); \
|
|
} else if (type & NUMERIC_SIGNED && type & NUMERIC_64) { \
|
|
return push_token(interpreter_state, (Token){ \
|
|
.type = TOKEN_INTEGER, \
|
|
.integer_literal = (IntegerLiteral){ \
|
|
.type = INTEGER_I64, \
|
|
.value = bi op ai, \
|
|
}, \
|
|
}); \
|
|
} else if (type & NUMERIC_SIGNED && type & NUMERIC_32) { \
|
|
return push_token(interpreter_state, (Token){ \
|
|
.type = TOKEN_INTEGER, \
|
|
.integer_literal = (IntegerLiteral){ \
|
|
.type = INTEGER_I32, \
|
|
.value = bi op ai, \
|
|
}, \
|
|
}); \
|
|
} else if (type & NUMERIC_SIGNED && type & NUMERIC_16) { \
|
|
return push_token(interpreter_state, (Token){ \
|
|
.type = TOKEN_INTEGER, \
|
|
.integer_literal = (IntegerLiteral){ \
|
|
.type = INTEGER_I16, \
|
|
.value = bi op ai, \
|
|
}, \
|
|
}); \
|
|
} else if (type & NUMERIC_SIGNED) { \
|
|
return push_token(interpreter_state, (Token){ \
|
|
.type = TOKEN_INTEGER, \
|
|
.integer_literal = (IntegerLiteral){ \
|
|
.type = INTEGER_I8, \
|
|
.value = bi op ai, \
|
|
}, \
|
|
}); \
|
|
} else if (type & NUMERIC_64) { \
|
|
return push_token(interpreter_state, (Token){ \
|
|
.type = TOKEN_INTEGER, \
|
|
.integer_literal = (IntegerLiteral){ \
|
|
.type = INTEGER_U64, \
|
|
.value = bi op ai, \
|
|
}, \
|
|
}); \
|
|
} else if (type & NUMERIC_32) { \
|
|
return push_token(interpreter_state, (Token){ \
|
|
.type = TOKEN_INTEGER, \
|
|
.integer_literal = (IntegerLiteral){ \
|
|
.type = INTEGER_U32, \
|
|
.value = bi op ai, \
|
|
}, \
|
|
}); \
|
|
} else if (type & NUMERIC_16) { \
|
|
return push_token(interpreter_state, (Token){ \
|
|
.type = TOKEN_INTEGER, \
|
|
.integer_literal = (IntegerLiteral){ \
|
|
.type = INTEGER_U16, \
|
|
.value = bi op ai, \
|
|
}, \
|
|
}); \
|
|
} else { \
|
|
return push_token(interpreter_state, (Token){ \
|
|
.type = TOKEN_INTEGER, \
|
|
.integer_literal = (IntegerLiteral){ \
|
|
.type = INTEGER_U8, \
|
|
.value = bi op ai, \
|
|
}, \
|
|
}); \
|
|
} \
|
|
|
|
#define TRUTHY \
|
|
Boolean value = FALSE; \
|
|
switch (conditional->type) { \
|
|
case STACK_IDENTIFIER: \
|
|
value = FALSE; \
|
|
break; \
|
|
case STACK_I64: \
|
|
value = (conditional->i64) ? TRUE : FALSE; \
|
|
break; \
|
|
case STACK_I32: \
|
|
value = (conditional->i32) ? TRUE : FALSE; \
|
|
break; \
|
|
case STACK_I16: \
|
|
value = (conditional->i16) ? TRUE : FALSE; \
|
|
break; \
|
|
case STACK_I8: \
|
|
value = (conditional->i8) ? TRUE : FALSE; \
|
|
break; \
|
|
case STACK_U64: \
|
|
value = (conditional->u64) ? TRUE : FALSE; \
|
|
break; \
|
|
case STACK_U32: \
|
|
value = (conditional->u32) ? TRUE : FALSE; \
|
|
break; \
|
|
case STACK_U16: \
|
|
value = (conditional->u16) ? TRUE : FALSE; \
|
|
break; \
|
|
case STACK_U8: \
|
|
value = (conditional->u8) ? TRUE : FALSE; \
|
|
break; \
|
|
case STACK_FLOAT: \
|
|
value = (conditional->f32) ? TRUE : FALSE; \
|
|
break; \
|
|
case STACK_DOUBLE: \
|
|
value = (conditional->f64) ? TRUE : FALSE; \
|
|
break; \
|
|
case STACK_CHARACTER: \
|
|
value = (conditional->character) ? TRUE : FALSE; \
|
|
break; \
|
|
case STACK_BOOLEAN: \
|
|
value = conditional->boolean; \
|
|
break; \
|
|
case STACK_TOKEN_STRING: \
|
|
case STACK_CALLABLE: \
|
|
value = (conditional->token_string.length && conditional->token_string.tokens[0].type != TOKEN_EOF) ? TRUE : FALSE; \
|
|
break; \
|
|
} \
|
|
|
|
#define SCALAR(item, value) \
|
|
switch (item->type) { \
|
|
case STACK_IDENTIFIER: \
|
|
return FALSE; \
|
|
case STACK_I64: \
|
|
if (item->i64 < 0) return FALSE; \
|
|
value = item->i64; \
|
|
break; \
|
|
case STACK_I32: \
|
|
if (item->i32 < 0) return FALSE; \
|
|
value = item->i32; \
|
|
break; \
|
|
case STACK_I16: \
|
|
if (item->i16 < 0) return FALSE; \
|
|
value = item->i16; \
|
|
break; \
|
|
case STACK_I8: \
|
|
if (item->i8 < 0) return FALSE; \
|
|
value = item->i8; \
|
|
break; \
|
|
case STACK_U64: \
|
|
value = item->u64; \
|
|
break; \
|
|
case STACK_U32: \
|
|
value = item->u32; \
|
|
break; \
|
|
case STACK_U16: \
|
|
value = item->u16; \
|
|
break; \
|
|
case STACK_U8: \
|
|
value = item->u8; \
|
|
break; \
|
|
case STACK_FLOAT: \
|
|
return FALSE; \
|
|
case STACK_DOUBLE: \
|
|
return FALSE; \
|
|
case STACK_CHARACTER: \
|
|
value = item->character; \
|
|
break; \
|
|
case STACK_BOOLEAN: \
|
|
value = item->boolean; \
|
|
break; \
|
|
case STACK_TOKEN_STRING: \
|
|
case STACK_CALLABLE: \
|
|
return FALSE; \
|
|
} \
|
|
|
|
Boolean builtin_addition(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPES;
|
|
ARITHMETIC(+);
|
|
}
|
|
|
|
Boolean builtin_subtraction(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPES;
|
|
ARITHMETIC(-);
|
|
}
|
|
|
|
Boolean builtin_multiplication(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPES;
|
|
ARITHMETIC(*);
|
|
}
|
|
|
|
Boolean builtin_division(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPES;
|
|
(void)ai;
|
|
(void)bi;
|
|
(void)type;
|
|
|
|
if (af == 0) return FALSE;
|
|
|
|
StackItem *node = interpreter_state->stack;
|
|
interpreter_state->stack = interpreter_state->stack->next->next;
|
|
node->next->next = NULL;
|
|
clean_stack(node);
|
|
|
|
return push_token(interpreter_state, (Token){
|
|
.type = SLS_FLOAT_BUILTIN_DEFAULT,
|
|
.double_literal = bf / af,
|
|
});
|
|
}
|
|
|
|
Boolean builtin_modulus(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPES;
|
|
(void)af;
|
|
(void)bf;
|
|
|
|
if (type & NUMERIC_FLOAT) {
|
|
return FALSE;
|
|
} else if (ai == 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
StackItem *node = interpreter_state->stack;
|
|
interpreter_state->stack = interpreter_state->stack->next->next;
|
|
node->next->next = NULL;
|
|
clean_stack(node);
|
|
|
|
if (type & NUMERIC_SIGNED && type & NUMERIC_64) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I64,
|
|
.value = bi % ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_SIGNED && type & NUMERIC_32) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I32,
|
|
.value = bi % ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_SIGNED && type & NUMERIC_16) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I16,
|
|
.value = bi % ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_SIGNED) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I8,
|
|
.value = bi % ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_64) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U64,
|
|
.value = bi % ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_32) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U32,
|
|
.value = bi % ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_16) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U16,
|
|
.value = bi % ai,
|
|
},
|
|
});
|
|
} else {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U8,
|
|
.value = bi % ai,
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
Boolean builtin_exponential(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPES;
|
|
(void)ai;
|
|
(void)bi;
|
|
(void)type;
|
|
|
|
StackItem *node = interpreter_state->stack;
|
|
interpreter_state->stack = interpreter_state->stack->next->next;
|
|
node->next->next = NULL;
|
|
clean_stack(node);
|
|
|
|
return push_token(interpreter_state, (Token){
|
|
.type = SLS_FLOAT_BUILTIN_DEFAULT,
|
|
.double_literal = pow(bf, af),
|
|
});
|
|
}
|
|
|
|
Boolean builtin_greater_than(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPES;
|
|
(void)ai;
|
|
(void)bi;
|
|
(void)type;
|
|
|
|
StackItem *node = interpreter_state->stack;
|
|
interpreter_state->stack = interpreter_state->stack->next->next;
|
|
node->next->next = NULL;
|
|
clean_stack(node);
|
|
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_BOOLEAN,
|
|
.boolean_literal = bf > af,
|
|
});
|
|
}
|
|
|
|
Boolean builtin_greater_than_or_equal_to(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPES;
|
|
(void)ai;
|
|
(void)bi;
|
|
(void)type;
|
|
|
|
StackItem *node = interpreter_state->stack;
|
|
interpreter_state->stack = interpreter_state->stack->next->next;
|
|
node->next->next = NULL;
|
|
clean_stack(node);
|
|
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_BOOLEAN,
|
|
.boolean_literal = bf >= af,
|
|
});
|
|
}
|
|
|
|
Boolean builtin_less_than(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPES;
|
|
(void)ai;
|
|
(void)bi;
|
|
(void)type;
|
|
|
|
StackItem *node = interpreter_state->stack;
|
|
interpreter_state->stack = interpreter_state->stack->next->next;
|
|
node->next->next = NULL;
|
|
clean_stack(node);
|
|
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_BOOLEAN,
|
|
.boolean_literal = bf < af,
|
|
});
|
|
}
|
|
|
|
Boolean builtin_less_than_or_equal_to(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPES;
|
|
(void)ai;
|
|
(void)bi;
|
|
(void)type;
|
|
|
|
StackItem *node = interpreter_state->stack;
|
|
interpreter_state->stack = interpreter_state->stack->next->next;
|
|
node->next->next = NULL;
|
|
clean_stack(node);
|
|
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_BOOLEAN,
|
|
.boolean_literal = bf <= af,
|
|
});
|
|
}
|
|
|
|
Boolean builtin_equal_to(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPES;
|
|
(void)ai;
|
|
(void)bi;
|
|
(void)type;
|
|
|
|
StackItem *node = interpreter_state->stack;
|
|
interpreter_state->stack = interpreter_state->stack->next->next;
|
|
node->next->next = NULL;
|
|
clean_stack(node);
|
|
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_BOOLEAN,
|
|
.boolean_literal = bf == af,
|
|
});
|
|
}
|
|
|
|
Boolean builtin_not_equal_to(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPES;
|
|
(void)ai;
|
|
(void)bi;
|
|
(void)type;
|
|
|
|
StackItem *node = interpreter_state->stack;
|
|
interpreter_state->stack = interpreter_state->stack->next->next;
|
|
node->next->next = NULL;
|
|
clean_stack(node);
|
|
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_BOOLEAN,
|
|
.boolean_literal = bf != af,
|
|
});
|
|
}
|
|
|
|
Boolean builtin_abs(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPE;
|
|
|
|
if (!((type & NUMERIC_SIGNED) | (type & NUMERIC_FLOAT)))
|
|
return FALSE;
|
|
|
|
StackItem *node = interpreter_state->stack;
|
|
interpreter_state->stack = interpreter_state->stack->next;
|
|
node->next = NULL;
|
|
clean_stack(node);
|
|
|
|
if (type & NUMERIC_FLOAT && type & NUMERIC_64) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_DOUBLE,
|
|
.double_literal = fabs(af),
|
|
});
|
|
} else if (type & NUMERIC_FLOAT) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_FLOAT,
|
|
.float_literal = fabs(af),
|
|
});
|
|
} else if (type & NUMERIC_SIGNED && type & NUMERIC_64) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I64,
|
|
.value = llabs((int64_t)ai),
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_SIGNED && type & NUMERIC_32) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I32,
|
|
.value = llabs((int64_t)ai),
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_SIGNED && type & NUMERIC_16) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I16,
|
|
.value = llabs((int64_t)ai),
|
|
},
|
|
});
|
|
} else {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I8,
|
|
.value = llabs((int64_t)ai),
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
Boolean builtin_acos(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPE;
|
|
if (af < -1 || af > 1) return FALSE;
|
|
FLOAT_FUNCTION(acos);
|
|
}
|
|
|
|
Boolean builtin_and(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPES;
|
|
|
|
StackItem *node = interpreter_state->stack;
|
|
interpreter_state->stack = interpreter_state->stack->next->next;
|
|
node->next->next = NULL;
|
|
clean_stack(node);
|
|
|
|
if (type & NUMERIC_FLOAT) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_BOOLEAN,
|
|
.boolean_literal = (Boolean){ bf && af },
|
|
});
|
|
} else {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_BOOLEAN,
|
|
.boolean_literal = (Boolean){ bi && ai },
|
|
});
|
|
}
|
|
}
|
|
|
|
Boolean builtin_asin(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPE;
|
|
if (af < -1 || af > 1) return FALSE;
|
|
FLOAT_FUNCTION(asin);
|
|
}
|
|
|
|
Boolean builtin_atan(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPE;
|
|
FLOAT_FUNCTION(atan);
|
|
}
|
|
|
|
Boolean builtin_atan2(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPES;
|
|
(void)ai;
|
|
(void)bi;
|
|
(void)type;
|
|
|
|
StackItem *node = interpreter_state->stack;
|
|
interpreter_state->stack = interpreter_state->stack->next->next;
|
|
node->next->next = NULL;
|
|
clean_stack(node);
|
|
|
|
return push_token(interpreter_state, (Token){
|
|
.type = SLS_FLOAT_BUILTIN_DEFAULT,
|
|
.double_literal = atan2(bf, af),
|
|
});
|
|
}
|
|
|
|
Boolean builtin_bitand(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPES;
|
|
(void)af;
|
|
(void)bf;
|
|
|
|
if (type & NUMERIC_FLOAT)
|
|
return FALSE;
|
|
|
|
StackItem *node = interpreter_state->stack;
|
|
interpreter_state->stack = interpreter_state->stack->next->next;
|
|
node->next->next = NULL;
|
|
clean_stack(node);
|
|
|
|
if (type & NUMERIC_SIGNED && type & NUMERIC_64) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I64,
|
|
.value = bi & ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_SIGNED && type & NUMERIC_32) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I32,
|
|
.value = bi & ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_SIGNED && type & NUMERIC_16) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I16,
|
|
.value = bi & ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_SIGNED) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I8,
|
|
.value = bi & ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_64) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U64,
|
|
.value = bi & ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_32) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U32,
|
|
.value = bi & ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_16) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U16,
|
|
.value = bi & ai,
|
|
},
|
|
});
|
|
} else {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U8,
|
|
.value = bi & ai,
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
Boolean builtin_bitnot(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPE;
|
|
(void)af;
|
|
|
|
if (type & NUMERIC_FLOAT)
|
|
return FALSE;
|
|
|
|
StackItem *node = interpreter_state->stack;
|
|
interpreter_state->stack = interpreter_state->stack->next;
|
|
node->next = NULL;
|
|
clean_stack(node);
|
|
|
|
if (type & NUMERIC_SIGNED && type & NUMERIC_64) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I64,
|
|
.value = ~ ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_SIGNED && type & NUMERIC_32) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I32,
|
|
.value = ~ ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_SIGNED && type & NUMERIC_16) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I16,
|
|
.value = ~ ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_SIGNED) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I8,
|
|
.value = ~ ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_64) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U64,
|
|
.value = ~ ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_32) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U32,
|
|
.value = ~ ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_16) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U16,
|
|
.value = ~ ai,
|
|
},
|
|
});
|
|
} else {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U8,
|
|
.value = ~ ai,
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
Boolean builtin_bitor(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPES;
|
|
(void)af;
|
|
(void)bf;
|
|
|
|
if (type & NUMERIC_FLOAT)
|
|
return FALSE;
|
|
|
|
StackItem *node = interpreter_state->stack;
|
|
interpreter_state->stack = interpreter_state->stack->next->next;
|
|
node->next->next = NULL;
|
|
clean_stack(node);
|
|
|
|
if (type & NUMERIC_SIGNED && type & NUMERIC_64) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I64,
|
|
.value = bi | ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_SIGNED && type & NUMERIC_32) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I32,
|
|
.value = bi | ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_SIGNED && type & NUMERIC_16) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I16,
|
|
.value = bi | ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_SIGNED) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I8,
|
|
.value = bi | ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_64) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U64,
|
|
.value = bi | ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_32) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U32,
|
|
.value = bi | ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_16) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U16,
|
|
.value = bi | ai,
|
|
},
|
|
});
|
|
} else {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U8,
|
|
.value = bi | ai,
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
Boolean builtin_bitxor(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPES;
|
|
(void)af;
|
|
(void)bf;
|
|
|
|
if (type & NUMERIC_FLOAT)
|
|
return FALSE;
|
|
|
|
StackItem *node = interpreter_state->stack;
|
|
interpreter_state->stack = interpreter_state->stack->next->next;
|
|
node->next->next = NULL;
|
|
clean_stack(node);
|
|
|
|
if (type & NUMERIC_SIGNED && type & NUMERIC_64) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I64,
|
|
.value = bi ^ ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_SIGNED && type & NUMERIC_32) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I32,
|
|
.value = bi ^ ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_SIGNED && type & NUMERIC_16) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I16,
|
|
.value = bi ^ ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_SIGNED) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I8,
|
|
.value = bi ^ ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_64) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U64,
|
|
.value = bi ^ ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_32) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U32,
|
|
.value = bi ^ ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_16) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U16,
|
|
.value = bi ^ ai,
|
|
},
|
|
});
|
|
} else {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U8,
|
|
.value = bi ^ ai,
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
Boolean builtin_ceil(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPE;
|
|
FLOAT_FUNCTION(ceil);
|
|
}
|
|
|
|
Boolean builtin_const(InterpreterState *interpreter_state) {
|
|
if (interpreter_state->stack == NULL) return FALSE;
|
|
StackItem *name = interpreter_state->stack;
|
|
if (name->type != STACK_IDENTIFIER) return FALSE;
|
|
if (name->next == NULL) return FALSE;
|
|
StackItem *item = name->next;
|
|
if (item->type != STACK_CALLABLE) return FALSE;
|
|
if (hash_table_get(interpreter_state->functions, name->identifier.name, NULL) != NULL) return FALSE;
|
|
|
|
FunctionItem *function_item = (FunctionItem *)malloc(sizeof(FunctionItem));
|
|
if (function_item == NULL) return FALSE;
|
|
function_item->type = FUNCTION_TOKEN_STRING;
|
|
function_item->token_string = item->token_string;
|
|
|
|
interpreter_state->stack = item->next;
|
|
name->next = NULL;
|
|
|
|
Boolean return_value = hash_table_put_funcs(interpreter_state->functions, name->identifier.name, function_item);
|
|
clean_stack(name);
|
|
return return_value;
|
|
}
|
|
|
|
Boolean builtin_cos(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPE;
|
|
FLOAT_FUNCTION(cos);
|
|
}
|
|
|
|
Boolean builtin_depth(InterpreterState *interpreter_state) {
|
|
size_t depth = 0;
|
|
for (StackItem *node = interpreter_state->stack; node; node = node->next)
|
|
depth++;
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = SLS_UNSIGNED_INTEGER_BUILTIN_DEFAULT,
|
|
.value = (uint64_t)depth,
|
|
},
|
|
});
|
|
}
|
|
|
|
Boolean builtin_drop(InterpreterState *interpreter_state) {
|
|
StackItem *node = interpreter_state->stack;
|
|
if (node == NULL) return FALSE;
|
|
interpreter_state->stack = node->next;
|
|
node->next = NULL;
|
|
clean_stack(node);
|
|
return TRUE;
|
|
}
|
|
|
|
Boolean builtin_dup(InterpreterState *interpreter_state) {
|
|
if (interpreter_state->stack == NULL) return FALSE;
|
|
|
|
StackItem *item = (StackItem *)malloc(sizeof(StackItem));
|
|
if (item == NULL) return FALSE;
|
|
item->type = interpreter_state->stack->type;
|
|
item->next = interpreter_state->stack;
|
|
|
|
switch (interpreter_state->stack->type) {
|
|
case STACK_IDENTIFIER:
|
|
item->identifier = interpreter_state->stack->identifier;
|
|
break;
|
|
case STACK_I64:
|
|
item->i64 = interpreter_state->stack->i64;
|
|
break;
|
|
case STACK_I32:
|
|
item->i32 = interpreter_state->stack->i32;
|
|
break;
|
|
case STACK_I16:
|
|
item->i16 = interpreter_state->stack->i16;
|
|
break;
|
|
case STACK_I8:
|
|
item->i8 = interpreter_state->stack->i8;
|
|
break;
|
|
case STACK_U64:
|
|
item->u64 = interpreter_state->stack->u64;
|
|
break;
|
|
case STACK_U32:
|
|
item->u32 = interpreter_state->stack->u32;
|
|
break;
|
|
case STACK_U16:
|
|
item->u16 = interpreter_state->stack->u16;
|
|
break;
|
|
case STACK_U8:
|
|
item->u8 = interpreter_state->stack->u8;
|
|
break;
|
|
case STACK_FLOAT:
|
|
item->f32 = interpreter_state->stack->f32;
|
|
break;
|
|
case STACK_DOUBLE:
|
|
item->f64 = interpreter_state->stack->f64;
|
|
break;
|
|
case STACK_CHARACTER:
|
|
item->character = interpreter_state->stack->character;
|
|
break;
|
|
case STACK_BOOLEAN:
|
|
item->boolean = interpreter_state->stack->boolean;
|
|
break;
|
|
case STACK_TOKEN_STRING:
|
|
case STACK_CALLABLE:
|
|
item->token_string = copy_token_string(interpreter_state->stack->token_string);
|
|
break;
|
|
}
|
|
|
|
interpreter_state->stack = item;
|
|
return TRUE;
|
|
}
|
|
|
|
Boolean builtin_eval(InterpreterState *interpreter_state) {
|
|
if (interpreter_state->stack == NULL) return FALSE;
|
|
StackItem *code_target = interpreter_state->stack;
|
|
|
|
interpreter_state->stack = code_target->next;
|
|
code_target->next = NULL;
|
|
|
|
Boolean return_value = FALSE;
|
|
if (code_target->type == STACK_TOKEN_STRING || code_target->type == STACK_CALLABLE)
|
|
return_value = execute_token_string(interpreter_state, code_target->token_string);
|
|
else if (code_target->type == STACK_IDENTIFIER)
|
|
return_value = execute_func(interpreter_state, code_target->identifier.name);
|
|
|
|
clean_stack(code_target);
|
|
return return_value;
|
|
}
|
|
|
|
Boolean builtin_floor(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPE;
|
|
FLOAT_FUNCTION(floor);
|
|
}
|
|
|
|
Boolean builtin_for(InterpreterState *interpreter_state) {
|
|
if (interpreter_state->stack == NULL) return FALSE;
|
|
StackItem *for_block = interpreter_state->stack;
|
|
if (for_block->next == NULL) return FALSE;
|
|
StackItem *end_item = for_block->next;
|
|
if (end_item->next == NULL) return FALSE;
|
|
StackItem *start_item = end_item->next;
|
|
|
|
if (!(
|
|
for_block->type == STACK_TOKEN_STRING ||
|
|
for_block->type == STACK_CALLABLE ||
|
|
for_block->type == STACK_IDENTIFIER
|
|
)) return FALSE;
|
|
|
|
interpreter_state->stack = start_item->next;
|
|
start_item->next = NULL;
|
|
|
|
size_t start_value = 0;
|
|
SCALAR(start_item, start_value);
|
|
size_t end_value = 0;
|
|
SCALAR(end_item, end_value);
|
|
|
|
Boolean return_value = FALSE;
|
|
for (size_t i = start_value; i < end_value; i++) {
|
|
return_value = push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = SLS_INTEGER_BUILTIN_DEFAULT,
|
|
.value = (uint64_t)i,
|
|
},
|
|
});
|
|
if (!return_value) break;
|
|
|
|
if (for_block->type == STACK_TOKEN_STRING || for_block->type == STACK_CALLABLE)
|
|
return_value = execute_token_string(interpreter_state, for_block->token_string);
|
|
else if (for_block->type == STACK_IDENTIFIER)
|
|
return_value = execute_func(interpreter_state, for_block->identifier.name);
|
|
if (!return_value) break;
|
|
}
|
|
|
|
clean_stack(for_block);
|
|
return return_value;
|
|
}
|
|
|
|
Boolean builtin_if(InterpreterState *interpreter_state) {
|
|
if (interpreter_state->stack == NULL) return FALSE;
|
|
StackItem *else_block = interpreter_state->stack;
|
|
if (else_block->next == NULL) return FALSE;
|
|
StackItem *then_block = else_block->next;
|
|
if (then_block->next == NULL) return FALSE;
|
|
StackItem *conditional = then_block->next;
|
|
|
|
if (!(
|
|
else_block->type == STACK_TOKEN_STRING ||
|
|
else_block->type == STACK_CALLABLE ||
|
|
else_block->type == STACK_IDENTIFIER
|
|
)) return FALSE;
|
|
|
|
if (!(
|
|
then_block->type == STACK_TOKEN_STRING ||
|
|
then_block->type == STACK_CALLABLE ||
|
|
then_block->type == STACK_IDENTIFIER
|
|
)) return FALSE;
|
|
|
|
interpreter_state->stack = conditional->next;
|
|
conditional->next = NULL;
|
|
|
|
TRUTHY;
|
|
|
|
Boolean return_value = FALSE;
|
|
if (value) {
|
|
if (then_block->type == STACK_TOKEN_STRING || then_block->type == STACK_CALLABLE)
|
|
return_value = execute_token_string(interpreter_state, then_block->token_string);
|
|
else if (then_block->type == STACK_IDENTIFIER)
|
|
return_value = execute_func(interpreter_state, then_block->identifier.name);
|
|
} else {
|
|
if (else_block->type == STACK_TOKEN_STRING || else_block->type == STACK_CALLABLE)
|
|
return_value = execute_token_string(interpreter_state, else_block->token_string);
|
|
else if (else_block->type == STACK_IDENTIFIER)
|
|
return_value = execute_func(interpreter_state, else_block->identifier.name);
|
|
}
|
|
|
|
clean_stack(else_block);
|
|
return return_value;
|
|
}
|
|
|
|
Boolean builtin_lambda(InterpreterState *interpreter_state) {
|
|
if (interpreter_state->stack == NULL) return FALSE;
|
|
if (interpreter_state->stack->type != STACK_TOKEN_STRING) return FALSE;
|
|
interpreter_state->stack->type = STACK_CALLABLE;
|
|
return TRUE;
|
|
}
|
|
|
|
Boolean builtin_ln(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPE;
|
|
if (af <= 0) return FALSE;
|
|
FLOAT_FUNCTION(log);
|
|
}
|
|
|
|
Boolean builtin_log(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPE;
|
|
if (af <= 0) return FALSE;
|
|
FLOAT_FUNCTION(log10);
|
|
}
|
|
|
|
Boolean builtin_not(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPE;
|
|
|
|
StackItem *node = interpreter_state->stack;
|
|
interpreter_state->stack = interpreter_state->stack->next->next;
|
|
node->next->next = NULL;
|
|
clean_stack(node);
|
|
|
|
if (type & NUMERIC_FLOAT) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_BOOLEAN,
|
|
.boolean_literal = (Boolean){ !af },
|
|
});
|
|
} else {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_BOOLEAN,
|
|
.boolean_literal = (Boolean){ !ai },
|
|
});
|
|
}
|
|
}
|
|
|
|
Boolean builtin_or(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPES;
|
|
|
|
StackItem *node = interpreter_state->stack;
|
|
interpreter_state->stack = interpreter_state->stack->next->next;
|
|
node->next->next = NULL;
|
|
clean_stack(node);
|
|
|
|
if (type & NUMERIC_FLOAT) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_BOOLEAN,
|
|
.boolean_literal = (Boolean){ bf || af },
|
|
});
|
|
} else {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_BOOLEAN,
|
|
.boolean_literal = (Boolean){ bi || ai },
|
|
});
|
|
}
|
|
}
|
|
|
|
Boolean builtin_pick(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPE;
|
|
(void)af;
|
|
|
|
if (type & NUMERIC_FLOAT)
|
|
return FALSE;
|
|
|
|
StackItem *picked = interpreter_state->stack->next;
|
|
for (size_t i = 0; i < ai; i++) {
|
|
picked = picked->next;
|
|
if (picked == NULL) return FALSE;
|
|
}
|
|
|
|
if (picked == NULL) return FALSE;
|
|
|
|
StackItem *node = interpreter_state->stack;
|
|
if (node == NULL) return FALSE;
|
|
interpreter_state->stack = node->next;
|
|
node->next = NULL;
|
|
clean_stack(node);
|
|
|
|
StackItem *item = (StackItem *)malloc(sizeof(StackItem));
|
|
if (item == NULL) return FALSE;
|
|
item->type = picked->type;
|
|
item->next = interpreter_state->stack;
|
|
|
|
switch (interpreter_state->stack->type) {
|
|
case STACK_IDENTIFIER:
|
|
item->identifier = picked->identifier;
|
|
break;
|
|
case STACK_I64:
|
|
item->i64 = picked->i64;
|
|
break;
|
|
case STACK_I32:
|
|
item->i32 = picked->i32;
|
|
break;
|
|
case STACK_I16:
|
|
item->i16 = picked->i16;
|
|
break;
|
|
case STACK_I8:
|
|
item->i8 = picked->i8;
|
|
break;
|
|
case STACK_U64:
|
|
item->u64 = picked->u64;
|
|
break;
|
|
case STACK_U32:
|
|
item->u32 = picked->u32;
|
|
break;
|
|
case STACK_U16:
|
|
item->u16 = picked->u16;
|
|
break;
|
|
case STACK_U8:
|
|
item->u8 = picked->u8;
|
|
break;
|
|
case STACK_FLOAT:
|
|
item->f32 = picked->f32;
|
|
break;
|
|
case STACK_DOUBLE:
|
|
item->f64 = picked->f64;
|
|
break;
|
|
case STACK_CHARACTER:
|
|
item->character = picked->character;
|
|
break;
|
|
case STACK_BOOLEAN:
|
|
item->boolean = picked->boolean;
|
|
break;
|
|
case STACK_TOKEN_STRING:
|
|
case STACK_CALLABLE:
|
|
item->token_string = copy_token_string(picked->token_string);
|
|
break;
|
|
}
|
|
|
|
interpreter_state->stack = item;
|
|
return TRUE;
|
|
}
|
|
|
|
Boolean builtin_rand(InterpreterState *interpreter_state) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = SLS_FLOAT_BUILTIN_DEFAULT,
|
|
.double_literal = rand() / RAND_MAX,
|
|
});
|
|
}
|
|
|
|
Boolean builtin_roll(InterpreterState *interpreter_state) {
|
|
if (interpreter_state->stack == NULL) return FALSE;
|
|
if (interpreter_state->stack->next == NULL) return FALSE;
|
|
|
|
StackItem *times_item = interpreter_state->stack;
|
|
StackItem *count_item = times_item->next;
|
|
|
|
size_t times = 0;
|
|
SCALAR(times_item, times);
|
|
|
|
size_t count = 0;
|
|
SCALAR(count_item, count);
|
|
|
|
StackItem *head = NULL, *tail = NULL, *prev = NULL;
|
|
if (count > 0) {
|
|
StackItem *node = count_item->next;
|
|
for (size_t i = 0; i < count; i++) {
|
|
if (node == NULL) return FALSE;
|
|
if (i == (count - times) - 1) {
|
|
tail = node;
|
|
head = node->next;
|
|
}
|
|
prev = node;
|
|
node = node->next;
|
|
}
|
|
}
|
|
|
|
if (head == NULL || tail == NULL) return FALSE;
|
|
|
|
interpreter_state->stack = head;
|
|
tail->next = prev->next;
|
|
prev->next = count_item->next;
|
|
count_item->next = NULL;
|
|
clean_stack(times_item);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
Boolean builtin_round(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPE;
|
|
FLOAT_FUNCTION(round);
|
|
}
|
|
|
|
Boolean builtin_seed(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPE;
|
|
(void)af;
|
|
|
|
if (type & NUMERIC_FLOAT) {
|
|
return FALSE;
|
|
}
|
|
|
|
StackItem *node = interpreter_state->stack;
|
|
interpreter_state->stack = interpreter_state->stack->next;
|
|
node->next = NULL;
|
|
clean_stack(node);
|
|
|
|
srand(ai);
|
|
return TRUE;
|
|
}
|
|
|
|
Boolean builtin_shl(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPES;
|
|
(void)af;
|
|
(void)bf;
|
|
|
|
if (type & NUMERIC_FLOAT)
|
|
return FALSE;
|
|
|
|
StackItem *node = interpreter_state->stack;
|
|
interpreter_state->stack = interpreter_state->stack->next->next;
|
|
node->next->next = NULL;
|
|
clean_stack(node);
|
|
|
|
if (type & NUMERIC_SIGNED && type & NUMERIC_64) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I64,
|
|
.value = bi << ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_SIGNED && type & NUMERIC_32) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I32,
|
|
.value = bi << ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_SIGNED && type & NUMERIC_16) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I16,
|
|
.value = bi << ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_SIGNED) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I8,
|
|
.value = bi << ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_64) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U64,
|
|
.value = bi << ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_32) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U32,
|
|
.value = bi << ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_16) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U16,
|
|
.value = bi << ai,
|
|
},
|
|
});
|
|
} else {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U8,
|
|
.value = bi << ai,
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
Boolean builtin_shr(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPES;
|
|
(void)af;
|
|
(void)bf;
|
|
|
|
if (type & NUMERIC_FLOAT)
|
|
return FALSE;
|
|
|
|
StackItem *node = interpreter_state->stack;
|
|
interpreter_state->stack = interpreter_state->stack->next->next;
|
|
node->next->next = NULL;
|
|
clean_stack(node);
|
|
|
|
if (type & NUMERIC_SIGNED && type & NUMERIC_64) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I64,
|
|
.value = bi >> ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_SIGNED && type & NUMERIC_32) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I32,
|
|
.value = bi >> ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_SIGNED && type & NUMERIC_16) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I16,
|
|
.value = bi >> ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_SIGNED) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_I8,
|
|
.value = bi >> ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_64) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U64,
|
|
.value = bi >> ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_32) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U32,
|
|
.value = bi >> ai,
|
|
},
|
|
});
|
|
} else if (type & NUMERIC_16) {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U16,
|
|
.value = bi >> ai,
|
|
},
|
|
});
|
|
} else {
|
|
return push_token(interpreter_state, (Token){
|
|
.type = TOKEN_INTEGER,
|
|
.integer_literal = (IntegerLiteral){
|
|
.type = INTEGER_U8,
|
|
.value = bi >> ai,
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
Boolean builtin_sin(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPE;
|
|
FLOAT_FUNCTION(sin);
|
|
}
|
|
|
|
Boolean builtin_sqrt(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPE;
|
|
if (af < 0) return FALSE;
|
|
FLOAT_FUNCTION(sqrt);
|
|
}
|
|
|
|
Boolean builtin_swap(InterpreterState *interpreter_state) {
|
|
if (interpreter_state->stack == NULL) return FALSE;
|
|
if (interpreter_state->stack->next == NULL) return FALSE;
|
|
|
|
StackItem *a = interpreter_state->stack;
|
|
StackItem *b = a->next;
|
|
|
|
a->next = b->next;
|
|
b->next = a;
|
|
interpreter_state->stack = b;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
Boolean builtin_tan(InterpreterState *interpreter_state) {
|
|
NUMERIC_TYPE;
|
|
FLOAT_FUNCTION(tan);
|
|
}
|
|
|
|
Boolean builtin_type_of(InterpreterState *interpreter_state) {
|
|
if (interpreter_state->stack == NULL)
|
|
return FALSE;
|
|
|
|
StackItem *node = interpreter_state->stack;
|
|
interpreter_state->stack = interpreter_state->stack->next;
|
|
node->next = NULL;
|
|
|
|
Boolean return_value = push_token(interpreter_state, (Token){
|
|
.type = TOKEN_IDENTIFIER,
|
|
.identifier = (Identifier){
|
|
.is_literal = TRUE,
|
|
.name = sls_str_malloc(STACK_TYPES_TYPES[node->type], TYPE_NAMES_SAFE_LENGTH),
|
|
},
|
|
});
|
|
|
|
clean_stack(node);
|
|
return return_value;
|
|
}
|
|
|
|
Boolean builtin_while(InterpreterState *interpreter_state) {
|
|
if (interpreter_state->stack == NULL) return FALSE;
|
|
StackItem *while_block = interpreter_state->stack;
|
|
if (while_block->next == NULL) return FALSE;
|
|
StackItem *conditional_block = while_block->next;
|
|
|
|
if (!(
|
|
while_block->type == STACK_TOKEN_STRING ||
|
|
while_block->type == STACK_CALLABLE ||
|
|
while_block->type == STACK_IDENTIFIER
|
|
)) return FALSE;
|
|
|
|
if (!(
|
|
conditional_block->type == STACK_TOKEN_STRING ||
|
|
conditional_block->type == STACK_CALLABLE ||
|
|
conditional_block->type == STACK_IDENTIFIER
|
|
)) return FALSE;
|
|
|
|
interpreter_state->stack = conditional_block->next;
|
|
conditional_block->next = NULL;
|
|
|
|
Boolean return_value = FALSE;
|
|
while (TRUE) {
|
|
if (conditional_block->type == STACK_TOKEN_STRING || conditional_block->type == STACK_CALLABLE)
|
|
return_value = execute_token_string(interpreter_state, conditional_block->token_string);
|
|
else if (conditional_block->type == STACK_IDENTIFIER)
|
|
return_value = execute_func(interpreter_state, conditional_block->identifier.name);
|
|
if (!return_value) break;
|
|
if (interpreter_state->stack == NULL) return FALSE;
|
|
|
|
StackItem *conditional = interpreter_state->stack;
|
|
interpreter_state->stack = conditional->next;
|
|
conditional->next = NULL;
|
|
TRUTHY;
|
|
clean_stack(conditional);
|
|
if (!value) break;
|
|
|
|
if (while_block->type == STACK_TOKEN_STRING || while_block->type == STACK_CALLABLE)
|
|
return_value = execute_token_string(interpreter_state, while_block->token_string);
|
|
else if (while_block->type == STACK_IDENTIFIER)
|
|
return_value = execute_func(interpreter_state, while_block->identifier.name);
|
|
if (!return_value) break;
|
|
}
|
|
|
|
clean_stack(while_block);
|
|
return return_value;
|
|
}
|