diff --git a/main.c b/main.c index d033320..2e8b0af 100644 --- a/main.c +++ b/main.c @@ -8,6 +8,7 @@ #include "ir.h" #include "lex.h" #include "parse.h" +#include "runtime.h" #include "util.h" #include "vm.h" @@ -53,10 +54,11 @@ static Value fn_int(Value *args) { .Int = 0, }; switch (args[0].type) { - case TypeVoid: break; + case TypeVoid: break; case TypeFloat: ret.Int = (ssize_t)args[0].Float; break; case TypeInt: ret.Int = args[0].Int; break; case TypeBool: ret.Int = (ssize_t)args[0].Bool; break; + case TypeChar: ret.Int = (ssize_t)args[0].Char; break; case TypeArr: if (args[0].Arr.is_string && args[0].Arr.type == TypeChar) { ssize_t endpos; @@ -79,10 +81,11 @@ static Value fn_float(Value *args) { .Float = 0.0, }; switch (args[0].type) { - case TypeVoid: break; + case TypeVoid: break; case TypeFloat: ret.Float = args[0].Float; break; case TypeInt: ret.Float = (double)args[0].Int; break; case TypeBool: ret.Float = (double)args[0].Bool; break; + case TypeChar: ret.Float = (double)args[0].Char; break; case TypeArr: if (args[0].Arr.is_string && args[0].Arr.type == TypeChar) { ssize_t endpos; @@ -99,6 +102,31 @@ static Value fn_float(Value *args) { return ret; } +static Value fn_bool(Value *args) { + return (Value){ .type = TypeBool, .Bool = is_nonzero(&args[0]) }; +} + +static Value fn_char(Value *args) { + Value ret = { + .type = TypeChar, + .Float = 0.0, + }; + switch (args[0].type) { + case TypeVoid: break; + case TypeFloat: ret.Char = (char)args[0].Float; break; + case TypeInt: ret.Char = (char)args[0].Int; break; + case TypeBool: ret.Char = (char)args[0].Bool; break; + case TypeChar: ret.Char = args[0].Char; break; + default: ASSERT_UNREACHED(); + } + return ret; +} + +static Value fn_ptr(Value *args) { + (void)args; + return (Value){ .type = TypePtr, .Ptr = { .type = TypeVoid, .val = NULL }}; +} + static Value fn_pow(Value *args) { if (!(args[0].type == TypeFloat && args[1].type == TypeFloat)) { set_err("pow() requires arguments of type float"); @@ -209,6 +237,9 @@ int main(int argc, const char **argv) { { .name = "putln", .kind = FuncVarArgs, .returns = false, .side_effects = true, .VarArgs = { .min_args = 0, .NoRet.func = fn_putln, }}, { .name = "int", .kind = FuncFixedArgs, .returns = true, .side_effects = false, .FixedArgs = { .n_args = 1, .WithRet.func = fn_int, }}, { .name = "float", .kind = FuncFixedArgs, .returns = true, .side_effects = false, .FixedArgs = { .n_args = 1, .WithRet.func = fn_float, }}, + { .name = "bool", .kind = FuncFixedArgs, .returns = true, .side_effects = false, .FixedArgs = { .n_args = 1, .WithRet.func = fn_bool, }}, + { .name = "char", .kind = FuncFixedArgs, .returns = true, .side_effects = false, .FixedArgs = { .n_args = 1, .WithRet.func = fn_char, }}, + { .name = "ptr", .kind = FuncFixedArgs, .returns = true, .side_effects = false, .FixedArgs = { .n_args = 0, .WithRet.func = fn_ptr, }}, { .name = "pow", .kind = FuncFixedArgs, .returns = true, .side_effects = false, .FixedArgs = { .n_args = 2, .WithRet.func = fn_pow, }}, { .name = "sleep", .kind = FuncFixedArgs, .returns = false, .side_effects = true, .FixedArgs = { .n_args = 1, .NoRet.func = fn_sleep, }}, { .name = "getln", .kind = FuncFixedArgs, .returns = true, .side_effects = true, .FixedArgs = { .n_args = 0, .WithRet.func = fn_getln, }}, diff --git a/runtime.c b/runtime.c index 357c3e1..8eeb3dc 100644 --- a/runtime.c +++ b/runtime.c @@ -130,9 +130,12 @@ Value eval_unary(IRInstr instr, const Value *v) { bool is_nonzero(const Value *v) { switch (v->type) { - case TypeInt: return v->Int != 0; - case TypeFloat: return v->Float != 0.0; + case TypeInt: return v->Int != 0; + case TypeFloat: return v->Float != 0.0; case TypeBool: return v->Bool; + case TypeChar: return v->Char != 0; + case TypePtr: return v->Ptr.val != NULL; + case TypeArr: return v->Arr.len != 0; default: ASSERT_UNREACHED(); } } diff --git a/tok.c b/tok.c index d05a27b..e62be06 100644 --- a/tok.c +++ b/tok.c @@ -11,6 +11,7 @@ size_t type_size[TypeEnumSize] = { [TypeInt] = sizeof(((Value*)NULL)->Int), [TypeBool] = sizeof(((Value*)NULL)->Bool), [TypeChar] = sizeof(((Value*)NULL)->Char), + [TypePtr] = sizeof(((Value*)NULL)->Ptr), [TypeArr] = sizeof(((Value*)NULL)->Arr), }; @@ -47,11 +48,17 @@ void print_value(const Value *v, bool raw) { else printf("'%c'", v->Char); } break; - case TypePtr: - printf("ptr<%s>(", type_str[v->Ptr.type]); - print_value(v->Ptr.val, false); - printf(")"); + case TypePtr: { + if (v->Ptr.val) { + printf("ptr<%s>(", type_str[v->Ptr.type]); + Value deref = { .type = v->Ptr.type }; + memcpy(&deref.Void, v->Ptr.val, type_size[v->Ptr.type]); + print_value(&deref, false); + printf(")"); + } else + printf("ptr<%s>(nil)", type_str[v->Ptr.type]); break; + } case TypeArr: if (v->Arr.is_string) { if (v->Arr.type != TypeChar) diff --git a/tok.h b/tok.h index e4a6c51..b782d29 100644 --- a/tok.h +++ b/tok.h @@ -31,7 +31,7 @@ typedef struct Value { char Char; struct { Type type; - struct Value *val; + void *val; } Ptr; struct { Type type; diff --git a/vm.c b/vm.c index 53a2bc2..fc728d5 100644 --- a/vm.c +++ b/vm.c @@ -70,7 +70,7 @@ void run(const IRToks *ir, const BuiltinFunc *builtin_funcs) { .type = TypePtr, .Ptr = { .type = v->type, - .val = v, + .val = &v->Void, }, }; break;