feat: implement vm #1
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
printline(2 + 2)
|
|
||||||
printline(2 + 2 * 2)
|
printline(2 + 2 * 2)
|
||||||
printline(-1 + 1)
|
printline(-1 + 1)
|
||||||
printline(2 ^ 2)
|
printline(2 ^ 2)
|
||||||
printline(1 + 1 * 1 / 1)
|
printline(1 + 1 * 1 / 1)
|
||||||
printline(4 % 2)
|
printline(4 % 2)
|
||||||
|
printline(10 / 2)
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,8 @@
|
|||||||
// Constant types
|
// Constant types
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
FZL_CONSTTYPE_STRING
|
FZL_CONSTTYPE_STRING,
|
||||||
|
FZL_CONSTTYPE_NUMBER
|
||||||
} fzl_consttype_t;
|
} fzl_consttype_t;
|
||||||
|
|
||||||
// Constant descriptor
|
// Constant descriptor
|
||||||
@@ -23,6 +24,11 @@ typedef struct
|
|||||||
const char *chars;
|
const char *chars;
|
||||||
size_t length;
|
size_t length;
|
||||||
} string;
|
} string;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint64_t value;
|
||||||
|
} num;
|
||||||
} as;
|
} as;
|
||||||
} fzl_const_t;
|
} fzl_const_t;
|
||||||
|
|
||||||
|
|||||||
@@ -193,6 +193,7 @@ bool walk(fzl_walker_t *walker, fzl_node_t *node)
|
|||||||
if (!walk(walker, node->unary_op.operand))
|
if (!walk(walker, node->unary_op.operand))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
push_op(walker, FZL_OPCODE_PUSHARG);
|
||||||
push_op(walker, FZL_OPCODE_NEG);
|
push_op(walker, FZL_OPCODE_NEG);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
+116
-5
@@ -1,6 +1,6 @@
|
|||||||
#include "common/fzl_builtins.h"
|
#include <common/fzl_builtins.h>
|
||||||
#include "common/fzl_opcodes.h"
|
#include <common/fzl_opcodes.h>
|
||||||
#include "compiler/utils/fzl_const_pool.h"
|
#include <compiler/utils/fzl_const_pool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -111,7 +111,7 @@ int fzl_vm_run(fzl_vm_t *vm)
|
|||||||
vm->ip = 0;
|
vm->ip = 0;
|
||||||
while (vm->ip < vm->ops_count)
|
while (vm->ip < vm->ops_count)
|
||||||
{
|
{
|
||||||
uint64_t opcode = vm->ops[vm->ip];
|
fzl_opcode_t opcode = vm->ops[vm->ip];
|
||||||
|
|
||||||
switch (opcode)
|
switch (opcode)
|
||||||
{
|
{
|
||||||
@@ -120,7 +120,10 @@ int fzl_vm_run(fzl_vm_t *vm)
|
|||||||
if (fn_id == FZL_BUILTIN_PRINTLINE)
|
if (fn_id == FZL_BUILTIN_PRINTLINE)
|
||||||
{
|
{
|
||||||
fzl_const_t arg = vm->arg_stack[--vm->arg_top];
|
fzl_const_t arg = vm->arg_stack[--vm->arg_top];
|
||||||
|
if (arg.type == FZL_CONSTTYPE_STRING)
|
||||||
printf("%s\n", arg.as.string.chars);
|
printf("%s\n", arg.as.string.chars);
|
||||||
|
else if (arg.type == FZL_CONSTTYPE_NUMBER)
|
||||||
|
printf("%lu\n", arg.as.num.value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -152,8 +155,116 @@ int fzl_vm_run(fzl_vm_t *vm)
|
|||||||
vm->arg_stack[vm->arg_top++] = vm->stack[--vm->stack_top];
|
vm->arg_stack[vm->arg_top++] = vm->stack[--vm->stack_top];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case FZL_OPCODE_ADD:
|
||||||
|
if (vm->arg_top < 2)
|
||||||
|
{
|
||||||
|
snprintf(last_err, sizeof(last_err),
|
||||||
|
"runtime error - expected 2 values in argstack");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fzl_const_t add1 = vm->arg_stack[--vm->arg_top];
|
||||||
|
fzl_const_t add2 = vm->arg_stack[--vm->arg_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->arg_top < 2)
|
||||||
|
{
|
||||||
|
snprintf(last_err, sizeof(last_err),
|
||||||
|
"runtime error - expected 2 values in argstack");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fzl_const_t sub1 = vm->arg_stack[--vm->arg_top];
|
||||||
|
fzl_const_t sub2 = vm->arg_stack[--vm->arg_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->arg_top < 2)
|
||||||
|
{
|
||||||
|
snprintf(last_err, sizeof(last_err),
|
||||||
|
"runtime error - expected 2 values in argstack");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fzl_const_t mul1 = vm->arg_stack[--vm->arg_top];
|
||||||
|
fzl_const_t mul2 = vm->arg_stack[--vm->arg_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->arg_top < 2)
|
||||||
|
{
|
||||||
|
snprintf(last_err, sizeof(last_err),
|
||||||
|
"runtime error - expected 2 values in argstack");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fzl_const_t div1 = vm->arg_stack[--vm->arg_top];
|
||||||
|
fzl_const_t div2 = vm->arg_stack[--vm->arg_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->arg_top < 2)
|
||||||
|
{
|
||||||
|
snprintf(last_err, sizeof(last_err),
|
||||||
|
"runtime error - expected 2 values in argstack");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fzl_const_t pow1 = vm->arg_stack[--vm->arg_top];
|
||||||
|
fzl_const_t pow2 = vm->arg_stack[--vm->arg_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->arg_top < 2)
|
||||||
|
{
|
||||||
|
snprintf(last_err, sizeof(last_err),
|
||||||
|
"runtime error - expected 2 values in argstack");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fzl_const_t mod1 = vm->arg_stack[--vm->arg_top];
|
||||||
|
fzl_const_t mod2 = vm->arg_stack[--vm->arg_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->arg_top < 1)
|
||||||
|
{
|
||||||
|
snprintf(last_err, sizeof(last_err),
|
||||||
|
"runtime error - expected value in argstack");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fzl_const_t neg_n = vm->arg_stack[--vm->arg_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:
|
default:
|
||||||
snprintf(last_err, sizeof(last_err), "runtime error - unknown opcode %lu",
|
snprintf(last_err, sizeof(last_err), "runtime error - unknown opcode %u",
|
||||||
opcode);
|
opcode);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user