add nilptrs, more conversion functions and change how ptrs work

Pointers now no longer point to the Value struct (the internal wrapper for
values) but to the value itself.
This commit is contained in:
r4 2021-12-28 17:53:27 +01:00
parent befce544e7
commit ba8d2f0702
5 changed files with 51 additions and 10 deletions

31
main.c
View File

@ -8,6 +8,7 @@
#include "ir.h" #include "ir.h"
#include "lex.h" #include "lex.h"
#include "parse.h" #include "parse.h"
#include "runtime.h"
#include "util.h" #include "util.h"
#include "vm.h" #include "vm.h"
@ -57,6 +58,7 @@ static Value fn_int(Value *args) {
case TypeFloat: ret.Int = (ssize_t)args[0].Float; break; case TypeFloat: ret.Int = (ssize_t)args[0].Float; break;
case TypeInt: ret.Int = args[0].Int; break; case TypeInt: ret.Int = args[0].Int; break;
case TypeBool: ret.Int = (ssize_t)args[0].Bool; break; case TypeBool: ret.Int = (ssize_t)args[0].Bool; break;
case TypeChar: ret.Int = (ssize_t)args[0].Char; break;
case TypeArr: case TypeArr:
if (args[0].Arr.is_string && args[0].Arr.type == TypeChar) { if (args[0].Arr.is_string && args[0].Arr.type == TypeChar) {
ssize_t endpos; ssize_t endpos;
@ -83,6 +85,7 @@ static Value fn_float(Value *args) {
case TypeFloat: ret.Float = args[0].Float; break; case TypeFloat: ret.Float = args[0].Float; break;
case TypeInt: ret.Float = (double)args[0].Int; break; case TypeInt: ret.Float = (double)args[0].Int; break;
case TypeBool: ret.Float = (double)args[0].Bool; break; case TypeBool: ret.Float = (double)args[0].Bool; break;
case TypeChar: ret.Float = (double)args[0].Char; break;
case TypeArr: case TypeArr:
if (args[0].Arr.is_string && args[0].Arr.type == TypeChar) { if (args[0].Arr.is_string && args[0].Arr.type == TypeChar) {
ssize_t endpos; ssize_t endpos;
@ -99,6 +102,31 @@ static Value fn_float(Value *args) {
return ret; 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) { static Value fn_pow(Value *args) {
if (!(args[0].type == TypeFloat && args[1].type == TypeFloat)) { if (!(args[0].type == TypeFloat && args[1].type == TypeFloat)) {
set_err("pow() requires arguments of type float"); 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 = "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 = "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 = "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 = "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 = "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, }}, { .name = "getln", .kind = FuncFixedArgs, .returns = true, .side_effects = true, .FixedArgs = { .n_args = 0, .WithRet.func = fn_getln, }},

View File

@ -133,6 +133,9 @@ bool is_nonzero(const Value *v) {
case TypeInt: return v->Int != 0; case TypeInt: return v->Int != 0;
case TypeFloat: return v->Float != 0.0; case TypeFloat: return v->Float != 0.0;
case TypeBool: return v->Bool; 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(); default: ASSERT_UNREACHED();
} }
} }

11
tok.c
View File

@ -11,6 +11,7 @@ size_t type_size[TypeEnumSize] = {
[TypeInt] = sizeof(((Value*)NULL)->Int), [TypeInt] = sizeof(((Value*)NULL)->Int),
[TypeBool] = sizeof(((Value*)NULL)->Bool), [TypeBool] = sizeof(((Value*)NULL)->Bool),
[TypeChar] = sizeof(((Value*)NULL)->Char), [TypeChar] = sizeof(((Value*)NULL)->Char),
[TypePtr] = sizeof(((Value*)NULL)->Ptr),
[TypeArr] = sizeof(((Value*)NULL)->Arr), [TypeArr] = sizeof(((Value*)NULL)->Arr),
}; };
@ -47,11 +48,17 @@ void print_value(const Value *v, bool raw) {
else printf("'%c'", v->Char); else printf("'%c'", v->Char);
} }
break; break;
case TypePtr: case TypePtr: {
if (v->Ptr.val) {
printf("ptr<%s>(", type_str[v->Ptr.type]); printf("ptr<%s>(", type_str[v->Ptr.type]);
print_value(v->Ptr.val, false); Value deref = { .type = v->Ptr.type };
memcpy(&deref.Void, v->Ptr.val, type_size[v->Ptr.type]);
print_value(&deref, false);
printf(")"); printf(")");
} else
printf("ptr<%s>(nil)", type_str[v->Ptr.type]);
break; break;
}
case TypeArr: case TypeArr:
if (v->Arr.is_string) { if (v->Arr.is_string) {
if (v->Arr.type != TypeChar) if (v->Arr.type != TypeChar)

2
tok.h
View File

@ -31,7 +31,7 @@ typedef struct Value {
char Char; char Char;
struct { struct {
Type type; Type type;
struct Value *val; void *val;
} Ptr; } Ptr;
struct { struct {
Type type; Type type;

2
vm.c
View File

@ -70,7 +70,7 @@ void run(const IRToks *ir, const BuiltinFunc *builtin_funcs) {
.type = TypePtr, .type = TypePtr,
.Ptr = { .Ptr = {
.type = v->type, .type = v->type,
.val = v, .val = &v->Void,
}, },
}; };
break; break;