Compare commits

...

2 Commits

1 changed files with 344 additions and 101 deletions

View File

@ -4,6 +4,7 @@
// November 2025 // November 2025
#include <stdlib.h> #include <stdlib.h>
#include <math.h>
#include "sls/bool.h" #include "sls/bool.h"
#include "sls/builtin.h" #include "sls/builtin.h"
@ -105,6 +106,16 @@ static inline Boolean hash_table_put_funcs(HashTable *ht, SlsStr key, FunctionIt
return hash_table_put(ht, key, (void *)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) { Boolean load_builtins(InterpreterState *interpreter_state) {
FunctionItem *func; FunctionItem *func;
@ -645,113 +656,255 @@ Boolean load_builtins(InterpreterState *interpreter_state) {
return TRUE; return TRUE;
} }
#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: \
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: \
return FALSE; \
} \
#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, \
}, \
}); \
}
Boolean builtin_addition(InterpreterState *interpreter_state) { Boolean builtin_addition(InterpreterState *interpreter_state) {
(void)interpreter_state; NUMERIC_TYPES;
return FALSE; ARITHMETIC(+);
} }
Boolean builtin_subtraction(InterpreterState *interpreter_state) { Boolean builtin_subtraction(InterpreterState *interpreter_state) {
(void)interpreter_state; NUMERIC_TYPES;
return FALSE; ARITHMETIC(-);
} }
Boolean builtin_multiplication(InterpreterState *interpreter_state) { Boolean builtin_multiplication(InterpreterState *interpreter_state) {
(void)interpreter_state; NUMERIC_TYPES;
return FALSE; ARITHMETIC(*);
} }
Boolean builtin_division(InterpreterState *interpreter_state) { Boolean builtin_division(InterpreterState *interpreter_state) {
double a, b; NUMERIC_TYPES;
if (interpreter_state->stack == NULL) return FALSE; (void)ai;
if (interpreter_state->stack->next == NULL) return FALSE; (void)bi;
(void)type;
switch (interpreter_state->stack->type) { if (af == 0) return FALSE;
case STACK_IDENTIFIER:
return FALSE;
case STACK_I64:
a = interpreter_state->stack->i64;
break;
case STACK_I32:
a = interpreter_state->stack->i32;
break;
case STACK_I16:
a = interpreter_state->stack->i16;
break;
case STACK_I8:
a = interpreter_state->stack->i8;
break;
case STACK_U64:
a = interpreter_state->stack->u64;
break;
case STACK_U32:
a = interpreter_state->stack->u32;
break;
case STACK_U16:
a = interpreter_state->stack->u16;
break;
case STACK_U8:
a = interpreter_state->stack->u8;
break;
case STACK_FLOAT:
a = interpreter_state->stack->f32;
break;
case STACK_DOUBLE:
a = interpreter_state->stack->f64;
break;
case STACK_CHARACTER:
a = interpreter_state->stack->character;
break;
case STACK_BOOLEAN:
a = interpreter_state->stack->boolean;
break;
case STACK_TOKEN_STRING:
return FALSE;
}
switch (interpreter_state->stack->next->type) {
case STACK_IDENTIFIER:
return FALSE;
case STACK_I64:
b = interpreter_state->stack->next->i64;
break;
case STACK_I32:
b = interpreter_state->stack->next->i32;
break;
case STACK_I16:
b = interpreter_state->stack->next->i16;
break;
case STACK_I8:
b = interpreter_state->stack->next->i8;
break;
case STACK_U64:
b = interpreter_state->stack->next->u64;
break;
case STACK_U32:
b = interpreter_state->stack->next->u32;
break;
case STACK_U16:
b = interpreter_state->stack->next->u16;
break;
case STACK_U8:
b = interpreter_state->stack->next->u8;
break;
case STACK_FLOAT:
b = interpreter_state->stack->next->f32;
break;
case STACK_DOUBLE:
b = interpreter_state->stack->next->f64;
break;
case STACK_CHARACTER:
b = interpreter_state->stack->next->character;
break;
case STACK_BOOLEAN:
b = interpreter_state->stack->next->boolean;
break;
case STACK_TOKEN_STRING:
return FALSE;
}
if (a == 0) return FALSE;
StackItem *node = interpreter_state->stack; StackItem *node = interpreter_state->stack;
interpreter_state->stack = interpreter_state->stack->next->next; interpreter_state->stack = interpreter_state->stack->next->next;
@ -760,18 +913,108 @@ Boolean builtin_division(InterpreterState *interpreter_state) {
return push_token(interpreter_state, (Token){ return push_token(interpreter_state, (Token){
.type = TOKEN_DOUBLE, .type = TOKEN_DOUBLE,
.double_literal = (b/a), .double_literal = bf / af,
}); });
} }
Boolean builtin_modulus(InterpreterState *interpreter_state) { Boolean builtin_modulus(InterpreterState *interpreter_state) {
(void)interpreter_state; NUMERIC_TYPES;
(void)af;
(void)bf;
if (type & NUMERIC_FLOAT) {
return FALSE;
} else if (ai == 0) {
return FALSE; 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) { Boolean builtin_exponential(InterpreterState *interpreter_state) {
(void)interpreter_state; NUMERIC_TYPES;
return FALSE; (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_DOUBLE,
.double_literal = pow(bf, af),
});
} }
Boolean builtin_greater_than(InterpreterState *interpreter_state) { Boolean builtin_greater_than(InterpreterState *interpreter_state) {