feat+ref: refactor + new types
This commit is contained in:
+172
-145
@@ -1,3 +1,5 @@
|
||||
#include "common/fzl_types.h"
|
||||
#include "common/fzl_value.h"
|
||||
#include <common/fzl_builtins.h>
|
||||
#include <common/fzl_opcodes.h>
|
||||
#include <compiler/utils/fzl_const_pool.h>
|
||||
@@ -20,13 +22,13 @@ fzl_vm_t *fzl_mkvm(const char *filepath)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vm->consts = NULL;
|
||||
vm->consts = NULL;
|
||||
vm->consts_count = 0;
|
||||
vm->ops = NULL;
|
||||
vm->ops_count = 0;
|
||||
vm->ip = 0;
|
||||
memset(vm->stack, 0, sizeof(vm->stack));
|
||||
vm->stack_top = 0;
|
||||
vm->ops = NULL;
|
||||
vm->ops_count = 0;
|
||||
vm->ip = 0;
|
||||
memset(vm->dstack, 0, sizeof(vm->dstack));
|
||||
vm->dtop = 0;
|
||||
|
||||
FILE *fd = fopen(filepath, "rb");
|
||||
if (!fd)
|
||||
@@ -56,7 +58,7 @@ fzl_vm_t *fzl_mkvm(const char *filepath)
|
||||
if (consts_count > 0)
|
||||
{
|
||||
vm->consts_count = consts_count;
|
||||
vm->consts = malloc(consts_count * sizeof(fzl_const_t));
|
||||
vm->consts = malloc(consts_count * sizeof(fzl_value_t));
|
||||
|
||||
for (size_t i = 0; i < consts_count; i++)
|
||||
{
|
||||
@@ -87,7 +89,7 @@ fzl_vm_t *fzl_mkvm(const char *filepath)
|
||||
}
|
||||
|
||||
vm->ops_count = ops_count;
|
||||
vm->ops = malloc(ops_count * sizeof(uint64_t));
|
||||
vm->ops = malloc(ops_count * sizeof(uint64_t));
|
||||
for (size_t i = 0; i < ops_count; i++)
|
||||
{
|
||||
uint64_t op;
|
||||
@@ -113,148 +115,173 @@ int fzl_vm_run(fzl_vm_t *vm)
|
||||
|
||||
switch (opcode)
|
||||
{
|
||||
case FZL_OPCODE_CALL_BUILTIN:
|
||||
uint64_t fn_id = vm->ops[++vm->ip];
|
||||
if (fn_id == FZL_BUILTIN_PRINTLINE)
|
||||
case FZL_OPCODE_CALL_BUILTIN:
|
||||
{
|
||||
fzl_const_t arg = vm->stack[--vm->stack_top];
|
||||
if (arg.type == FZL_CONSTTYPE_STRING)
|
||||
printf("%s\n", arg.as.string.chars);
|
||||
else if (arg.type == FZL_CONSTTYPE_NUMBER)
|
||||
printf("%lu\n", arg.as.num.value);
|
||||
uint64_t fn_id = vm->ops[++vm->ip];
|
||||
if (fn_id == FZL_BUILTIN_PRINTLINE)
|
||||
{
|
||||
fzl_value_t arg = vm->dstack[--vm->dtop];
|
||||
if (arg.type == FZL_TYPE_STRING)
|
||||
printf("%s\n", arg.as.s.value);
|
||||
else if (arg.type == FZL_TYPE_CHAR)
|
||||
printf("%c\n", arg.as.c);
|
||||
else if (arg.type == FZL_TYPE_INT8)
|
||||
printf("%d\n", arg.as.i8);
|
||||
else if (arg.type == FZL_TYPE_INT16)
|
||||
printf("%d\n", arg.as.i16);
|
||||
else if (arg.type == FZL_TYPE_INT32)
|
||||
printf("%d\n", arg.as.i32);
|
||||
else if (arg.type == FZL_TYPE_INT64)
|
||||
printf("%ld\n", arg.as.i64);
|
||||
else if (arg.type == FZL_TYPE_INT)
|
||||
printf("%ld\n", arg.as.i);
|
||||
else if (arg.type == FZL_TYPE_UINT8)
|
||||
printf("%u\n", arg.as.u8);
|
||||
else if (arg.type == FZL_TYPE_UINT16)
|
||||
printf("%u\n", arg.as.u16);
|
||||
else if (arg.type == FZL_TYPE_UINT32)
|
||||
printf("%u\n", arg.as.u32);
|
||||
else if (arg.type == FZL_TYPE_UINT64)
|
||||
printf("%lu\n", arg.as.u64);
|
||||
else if (arg.type == FZL_TYPE_UINT)
|
||||
printf("%lu\n", arg.as.u);
|
||||
else if (arg.type == FZL_TYPE_BOOL)
|
||||
printf("%b\n", arg.as.b);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(last_err, sizeof(last_err),
|
||||
"runtime error - undefined builtin %lu", fn_id);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
||||
case FZL_OPCODE_LOADCONST:
|
||||
{
|
||||
uint64_t cn = vm->ops[++vm->ip];
|
||||
if (vm->consts_count <= cn)
|
||||
{
|
||||
snprintf(last_err, sizeof(last_err), "runtime error - unknown const");
|
||||
return -1;
|
||||
}
|
||||
fzl_const_t c = vm->consts[cn];
|
||||
vm->dstack[vm->dtop++] =
|
||||
(fzl_value_t){.type = FZL_TYPE_STRING,
|
||||
.as.s.length = c.as.string.length,
|
||||
.as.s.value = c.as.string.chars};
|
||||
}
|
||||
break;
|
||||
|
||||
case FZL_OPCODE_ADD:
|
||||
if (vm->dtop < 2)
|
||||
{
|
||||
snprintf(last_err, sizeof(last_err),
|
||||
"runtime error - expected 2 values in stack");
|
||||
return -1;
|
||||
}
|
||||
fzl_value_t add1 = vm->dstack[--vm->dtop];
|
||||
fzl_value_t add2 = vm->dstack[--vm->dtop];
|
||||
vm->dstack[vm->dtop++] =
|
||||
(fzl_value_t){.type = add1.type, .as.u = add1.as.u + add2.as.u};
|
||||
break;
|
||||
|
||||
case FZL_OPCODE_SUB:
|
||||
if (vm->dtop < 2)
|
||||
{
|
||||
snprintf(last_err, sizeof(last_err),
|
||||
"runtime error - expected 2 values in stack");
|
||||
return -1;
|
||||
}
|
||||
fzl_value_t sub1 = vm->dstack[--vm->dtop];
|
||||
fzl_value_t sub2 = vm->dstack[--vm->dtop];
|
||||
vm->dstack[vm->dtop++] =
|
||||
(fzl_value_t){.type = add1.type, .as.u = sub1.as.u - sub2.as.u};
|
||||
break;
|
||||
|
||||
case FZL_OPCODE_MUL:
|
||||
if (vm->dtop < 2)
|
||||
{
|
||||
snprintf(last_err, sizeof(last_err),
|
||||
"runtime error - expected 2 values in stack");
|
||||
return -1;
|
||||
}
|
||||
fzl_value_t mul1 = vm->dstack[--vm->dtop];
|
||||
fzl_value_t mul2 = vm->dstack[--vm->dtop];
|
||||
vm->dstack[vm->dtop++] =
|
||||
(fzl_value_t){.type = mul1.type, .as.u = mul1.as.u * mul2.as.u};
|
||||
break;
|
||||
|
||||
case FZL_OPCODE_DIV:
|
||||
if (vm->dtop < 2)
|
||||
{
|
||||
snprintf(last_err, sizeof(last_err),
|
||||
"runtime error - expected 2 values in stack");
|
||||
return -1;
|
||||
}
|
||||
fzl_value_t div1 = vm->dstack[--vm->dtop];
|
||||
fzl_value_t div2 = vm->dstack[--vm->dtop];
|
||||
vm->dstack[vm->dtop++] =
|
||||
(fzl_value_t){.type = div1.type, .as.u = div2.as.u / div1.as.u};
|
||||
break;
|
||||
|
||||
case FZL_OPCODE_POW:
|
||||
if (vm->dtop < 2)
|
||||
{
|
||||
snprintf(last_err, sizeof(last_err),
|
||||
"runtime error - expected 2 values in stack");
|
||||
return -1;
|
||||
}
|
||||
fzl_value_t pow1 = vm->dstack[--vm->dtop];
|
||||
fzl_value_t pow2 = vm->dstack[--vm->dtop];
|
||||
|
||||
uint64_t pow_n = pow1.as.u;
|
||||
uint64_t pow_res = pow_n;
|
||||
uint64_t pow_times = pow2.as.u;
|
||||
for (size_t i = 1; i < pow_times; i++)
|
||||
pow_res *= pow_n;
|
||||
|
||||
vm->dstack[vm->dtop++] =
|
||||
(fzl_value_t){.type = pow1.type, .as.u = pow_res};
|
||||
break;
|
||||
|
||||
case FZL_OPCODE_MOD:
|
||||
if (vm->dtop < 2)
|
||||
{
|
||||
snprintf(last_err, sizeof(last_err),
|
||||
"runtime error - expected 2 values in stack");
|
||||
return -1;
|
||||
}
|
||||
fzl_value_t mod1 = vm->dstack[--vm->dtop];
|
||||
fzl_value_t mod2 = vm->dstack[--vm->dtop];
|
||||
vm->dstack[vm->dtop++] =
|
||||
(fzl_value_t){.type = mod1.type, .as.u = mod2.as.u % mod1.as.u};
|
||||
break;
|
||||
|
||||
case FZL_OPCODE_NEG:
|
||||
if (vm->dtop < 1)
|
||||
{
|
||||
snprintf(last_err, sizeof(last_err),
|
||||
"runtime error - expected value in stack");
|
||||
return -1;
|
||||
}
|
||||
fzl_value_t neg_n = vm->dstack[--vm->dtop];
|
||||
vm->dstack[vm->dtop++] =
|
||||
(fzl_value_t){.type = neg_n.type, .as.u = -neg_n.as.u};
|
||||
break;
|
||||
|
||||
case FZL_OPCODE_PUSHNUM:
|
||||
{
|
||||
uint64_t push_n = vm->ops[++vm->ip];
|
||||
vm->dstack[vm->dtop++] =
|
||||
(fzl_value_t){.type = FZL_TYPE_UINT, .as.u = push_n};
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
snprintf(last_err, sizeof(last_err),
|
||||
"runtime error - undefined builtin %lu", fn_id);
|
||||
"runtime error - unknown opcode %u", opcode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case FZL_OPCODE_LOADCONST:
|
||||
uint64_t cn = vm->ops[++vm->ip];
|
||||
if (vm->consts_count <= cn)
|
||||
{
|
||||
snprintf(last_err, sizeof(last_err), "runtime error - unknown const");
|
||||
return -1;
|
||||
}
|
||||
fzl_const_t c = vm->consts[cn];
|
||||
vm->stack[vm->stack_top++] = c;
|
||||
break;
|
||||
|
||||
case FZL_OPCODE_ADD:
|
||||
if (vm->stack_top < 2)
|
||||
{
|
||||
snprintf(last_err, sizeof(last_err),
|
||||
"runtime error - expected 2 values in stack");
|
||||
return -1;
|
||||
}
|
||||
fzl_const_t add1 = vm->stack[--vm->stack_top];
|
||||
fzl_const_t add2 = vm->stack[--vm->stack_top];
|
||||
vm->stack[vm->stack_top++] =
|
||||
(fzl_const_t){.type = FZL_CONSTTYPE_NUMBER,
|
||||
.as.num.value = add1.as.num.value + add2.as.num.value};
|
||||
break;
|
||||
|
||||
case FZL_OPCODE_SUB:
|
||||
if (vm->stack_top < 2)
|
||||
{
|
||||
snprintf(last_err, sizeof(last_err),
|
||||
"runtime error - expected 2 values in stack");
|
||||
return -1;
|
||||
}
|
||||
fzl_const_t sub1 = vm->stack[--vm->stack_top];
|
||||
fzl_const_t sub2 = vm->stack[--vm->stack_top];
|
||||
vm->stack[vm->stack_top++] =
|
||||
(fzl_const_t){.type = FZL_CONSTTYPE_NUMBER,
|
||||
.as.num.value = sub1.as.num.value - sub2.as.num.value};
|
||||
break;
|
||||
|
||||
case FZL_OPCODE_MUL:
|
||||
if (vm->stack_top < 2)
|
||||
{
|
||||
snprintf(last_err, sizeof(last_err),
|
||||
"runtime error - expected 2 values in stack");
|
||||
return -1;
|
||||
}
|
||||
fzl_const_t mul1 = vm->stack[--vm->stack_top];
|
||||
fzl_const_t mul2 = vm->stack[--vm->stack_top];
|
||||
vm->stack[vm->stack_top++] =
|
||||
(fzl_const_t){.type = FZL_CONSTTYPE_NUMBER,
|
||||
.as.num.value = mul1.as.num.value * mul2.as.num.value};
|
||||
break;
|
||||
|
||||
case FZL_OPCODE_DIV:
|
||||
if (vm->stack_top < 2)
|
||||
{
|
||||
snprintf(last_err, sizeof(last_err),
|
||||
"runtime error - expected 2 values in stack");
|
||||
return -1;
|
||||
}
|
||||
fzl_const_t div1 = vm->stack[--vm->stack_top];
|
||||
fzl_const_t div2 = vm->stack[--vm->stack_top];
|
||||
vm->stack[vm->stack_top++] =
|
||||
(fzl_const_t){.type = FZL_CONSTTYPE_NUMBER,
|
||||
.as.num.value = div2.as.num.value / div1.as.num.value};
|
||||
break;
|
||||
|
||||
case FZL_OPCODE_POW:
|
||||
if (vm->stack_top < 2)
|
||||
{
|
||||
snprintf(last_err, sizeof(last_err),
|
||||
"runtime error - expected 2 values in stack");
|
||||
return -1;
|
||||
}
|
||||
fzl_const_t pow1 = vm->stack[--vm->stack_top];
|
||||
fzl_const_t pow2 = vm->stack[--vm->stack_top];
|
||||
|
||||
uint64_t pow_n = pow1.as.num.value;
|
||||
uint64_t pow_res = pow_n;
|
||||
uint64_t pow_times = pow2.as.num.value;
|
||||
for (size_t i = 1; i < pow_times; i++)
|
||||
pow_res *= pow_n;
|
||||
|
||||
vm->stack[vm->stack_top++] =
|
||||
(fzl_const_t){.type = FZL_CONSTTYPE_NUMBER, .as.num.value = pow_res};
|
||||
break;
|
||||
|
||||
case FZL_OPCODE_MOD:
|
||||
if (vm->stack_top < 2)
|
||||
{
|
||||
snprintf(last_err, sizeof(last_err),
|
||||
"runtime error - expected 2 values in stack");
|
||||
return -1;
|
||||
}
|
||||
fzl_const_t mod1 = vm->stack[--vm->stack_top];
|
||||
fzl_const_t mod2 = vm->stack[--vm->stack_top];
|
||||
vm->stack[vm->stack_top++] =
|
||||
(fzl_const_t){.type = FZL_CONSTTYPE_NUMBER,
|
||||
.as.num.value = mod2.as.num.value % mod1.as.num.value};
|
||||
break;
|
||||
|
||||
case FZL_OPCODE_NEG:
|
||||
if (vm->stack_top < 1)
|
||||
{
|
||||
snprintf(last_err, sizeof(last_err),
|
||||
"runtime error - expected value in stack");
|
||||
return -1;
|
||||
}
|
||||
fzl_const_t neg_n = vm->stack[--vm->stack_top];
|
||||
vm->stack[vm->stack_top++] = (fzl_const_t){
|
||||
.type = FZL_CONSTTYPE_NUMBER, .as.num.value = -neg_n.as.num.value};
|
||||
break;
|
||||
|
||||
case FZL_OPCODE_PUSHNUM:
|
||||
uint64_t push_n = vm->ops[++vm->ip];
|
||||
vm->stack[vm->stack_top++] =
|
||||
(fzl_const_t){.type = FZL_CONSTTYPE_NUMBER, .as.num.value = push_n};
|
||||
break;
|
||||
|
||||
default:
|
||||
snprintf(last_err, sizeof(last_err), "runtime error - unknown opcode %u",
|
||||
opcode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
vm->ip++;
|
||||
|
||||
Reference in New Issue
Block a user