WIP function calls

This commit is contained in:
zongor 2025-07-05 12:40:33 -04:00
parent aab4c887ca
commit 0263d1511d
10 changed files with 188 additions and 241 deletions

View File

@ -33,141 +33,39 @@ void demo_add_compile(Value *memory) {
memory[i++].u = OP(OP_HALT, 0, 0, 0); memory[i++].u = OP(OP_HALT, 0, 0, 0);
} }
static void letDeclaration() {
/* uint8_t global = parseVariable("Expect variable name."); */
/* if (match(TOKEN_EQUAL)) { */
/* expression(); */
/* } else { */
/* emitByte(OP_NIL); */
/* } */
/* consume(TOKEN_SEMICOLON, */
/* "Expect ';' after variable declaration."); */
/* defineVariable(global); */
}
static void declaration(Token t) {
if (t.type == TOKEN_LET) {
letDeclaration();
} else {
/* statement(); */
}
}
/**
* Compile.
*/
void compile(Value *memory, char *buffer) { void compile(Value *memory, char *buffer) {
initTokenizer(buffer); initTokenizer(buffer);
Token t = nextToken(); Token t = nextToken();
do { while (t.type != TOKEN_EOF) {
printToken(t); printToken(t);
switch (t.type) { declaration(t);
case TOKEN_LEFT_PAREN:
break;
case TOKEN_RIGHT_PAREN:
break;
case TOKEN_LEFT_BRACE:
break;
case TOKEN_RIGHT_BRACE:
break;
case TOKEN_SEMICOLON:
break;
case TOKEN_IDENTIFIER:
break;
case TOKEN_STRING:
break;
case TOKEN_FLOAT:
break;
case TOKEN_U8:
break;
case TOKEN_I8:
break;
case TOKEN_U16:
break;
case TOKEN_I16:
break;
case TOKEN_U64:
break;
case TOKEN_I64:
break;
case TOKEN_INT:
break;
case TOKEN_UINT:
break;
case TOKEN_FALSE:
break;
case TOKEN_TRUE:
break;
case TOKEN_NULL:
break;
case TOKEN_EOF:
break;
case TOKEN_ERROR:
break;
case TOKEN_ADD:
break;
case TOKEN_SUB:
break;
case TOKEN_MUL:
break;
case TOKEN_DIV:
break;
case TOKEN_MOD:
break;
case TOKEN_GT:
break;
case TOKEN_LT:
break;
case TOKEN_EQ:
break;
case TOKEN_GE:
break;
case TOKEN_LE:
break;
case TOKEN_NE:
break;
case TOKEN_AND:
break;
case TOKEN_OR:
break;
case TOKEN_XOR:
break;
case TOKEN_SHIFTRIGHT:
break;
case TOKEN_SHIFTLEFT:
break;
case TOKEN_FN:
break;
case TOKEN_TO:
break;
case TOKEN_IN:
break;
case TOKEN_IS:
break;
case TOKEN_AS:
break;
case TOKEN_USE:
break;
case TOKEN_IF:
break;
case TOKEN_ELSE:
break;
case TOKEN_DEFAULT:
break;
case TOKEN_FOR:
break;
case TOKEN_TRY:
break;
case TOKEN_CATCH:
break;
case TOKEN_WHILE:
break;
case TOKEN_DO:
break;
case TOKEN_EXIT:
break;
case TOKEN_SWITCH:
break;
case TOKEN_RETURN:
break;
case TOKEN_CONST:
break;
case TOKEN_TYPE:
break;
case TOKEN_THIS:
break;
case TOKEN_YIELD:
break;
case TOKEN_CASE:
break;
case TOKEN_ASSERT:
break;
case TOKEN_BREAK:
break;
case TOKEN_LET:
break;
case TOKEN_PRINT:
break;
default:
break;
}
t = nextToken(); t = nextToken();
} while (t.type != TOKEN_EOF); }
} }

View File

@ -1,6 +1,6 @@
#include "parser.h"
#include "compiler.h" #include "compiler.h"
#include "debug.h" #include "debug.h"
#include "parser.h"
#include "vm.h" #include "vm.h"
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
@ -16,14 +16,14 @@
#include <emscripten.h> #include <emscripten.h>
#endif #endif
VM *vm; VM vm = {0};
void mainloop() { void mainloop() {
if (!step_vm(vm)) { if (!step_vm(&vm)) {
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
emscripten_cancel_main_loop(); /* this should "kill" the app. */ emscripten_cancel_main_loop(); /* this should "kill" the app. */
#else #else
core_dump(vm); core_dump(&vm);
exit(0); exit(0);
#endif #endif
} }
@ -50,10 +50,8 @@ int main(int argc, char **argv) {
} }
initTokenMap(); initTokenMap();
vm = init_vm(); compile(vm.memory, buffer);
vm->frame = (Frame*)malloc(sizeof(Frame)); /* demo_add_compile(vm.memory); */
compile(vm->memory, buffer);
demo_add_compile(vm->memory);
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
emscripten_set_main_loop(mainloop, 0, 1); emscripten_set_main_loop(mainloop, 0, 1);

View File

@ -10,76 +10,81 @@ typedef union {
char c[4]; /* 4 Byte char array for string packing */ char c[4]; /* 4 Byte char array for string packing */
} Value; } Value;
typedef union { typedef struct {
uint32_t length; uint32_t start;
char *string; uint32_t end;
Value *array; } Slice;
Value *code;
} Object;
#define MAX_REGS 256 #define MAX_REGS 256
typedef struct { typedef struct {
Value registers[MAX_REGS]; /* R0-R255 */ Value registers[MAX_REGS]; /* R0-R255 */
Object *locals; /* Short lived object */ Slice allocated;
} Frame; } Frame;
#define MEMORY_SIZE 1024
#define STACK_SIZE 128 #define STACK_SIZE 128
#define RETURN_STACK_SIZE 256
typedef struct { typedef struct {
Value stack[STACK_SIZE]; Value memory[MEMORY_SIZE]; /* Memory array */
uint32_t stack_size;
uint32_t pc; /* Program counter */
Value *memory;
uint32_t memory_size; uint32_t memory_size;
Frame *frame; Value return_stack[RETURN_STACK_SIZE];
uint32_t return_stack_size;
Frame stack[STACK_SIZE];
uint32_t stack_size;
uint32_t rp; /* Return stack pointer (top of stack) */
uint32_t sp; /* Stack pointer (top of stack) */
uint32_t pc; /* Program counter */
} VM; } VM;
typedef enum { typedef enum {
OP_HALT, /* terminate execution */ OP_HALT, /* halt : terminate execution */
OP_LOADI, /* dest = next memory location as int */ OP_LOADI, /* lodi : dest = next memory location as int */
OP_LOADU, /* dest = next memory location as uint */ OP_LOADU, /* lodu : dest = next memory location as uint */
OP_LOADF, /* dest = next memory location as float */ OP_LOADF, /* lodf : dest = next memory location as float */
OP_STOREI, /* next memory location = src1 as int */ OP_STOREI, /* stri : next memory location = src1 as int */
OP_STOREU, /* next memory location = src1 as uint */ OP_STOREU, /* stru : next memory location = src1 as uint */
OP_STOREF, /* next memory location = src1 as float */ OP_STOREF, /* strf : next memory location = src1 as float */
OP_ADD_INT, /* dest = src1 + src2 */ OP_ADD_INT, /* addi : dest = src1 + src2 */
OP_SUB_INT, /* dest = src1 - src2 */ OP_SUB_INT, /* subs : dest = src1 - src2 */
OP_MUL_INT, /* dest = src1 * src2 */ OP_MUL_INT, /* mulm : dest = src1 * src2 */
OP_DIV_INT, /* dest = src1 / src2 */ OP_DIV_INT, /* divd : dest = src1 / src2 */
OP_JEQ_INT, /* jump to address dest if src1 as int == src2 as int */ OP_JEQ_INT, /* jeqi : jump to address dest if src1 as int == src2 as int */
OP_JGT_INT, /* jump to address dest if src1 as int > src2 as int*/ OP_JGT_INT, /* jgti : jump to address dest if src1 as int > src2 as int*/
OP_JLT_INT, /* jump to address dest if src1 as int < src2 as int */ OP_JLT_INT, /* jlti : jump to address dest if src1 as int < src2 as int */
OP_JLE_INT, /* jump to address dest if src1 as int <= src2 as int */ OP_JLE_INT, /* jlei : jump to address dest if src1 as int <= src2 as int */
OP_JGE_INT, /* jump to address dest if src1 as int >= src2 as int*/ OP_JGE_INT, /* jgei : jump to address dest if src1 as int >= src2 as int*/
OP_INT_TO_REAL, /* dest = src1 as f32 */ OP_INT_TO_REAL, /* itor : dest = src1 as f32 */
OP_ADD_UINT, /* dest = src1 + src2 */ OP_ADD_UINT, /* addu : dest = src1 + src2 */
OP_SUB_UINT, /* dest = src1 - src2 */ OP_SUB_UINT, /* subu : dest = src1 - src2 */
OP_MUL_UINT, /* dest = src1 * src2 */ OP_MUL_UINT, /* mulu : dest = src1 * src2 */
OP_DIV_UINT, /* dest = src1 / src2 */ OP_DIV_UINT, /* divu : dest = src1 / src2 */
OP_JEQ_UINT, /* jump to address dest if src1 as int == src2 as uint */ OP_JEQ_UINT, /* jequ : jump to address dest if src1 as int == src2 as uint */
OP_JGT_UINT, /* jump to address dest if src1 as int > src2 as uint*/ OP_JGT_UINT, /* jgtu : jump to address dest if src1 as int > src2 as uint*/
OP_JLT_UINT, /* jump to address dest if src1 as int < src2 as uint */ OP_JLT_UINT, /* jltu : jump to address dest if src1 as int < src2 as uint */
OP_JLE_UINT, /* jump to address dest if src1 as int <= src2 as uint */ OP_JLE_UINT, /* jleu : jump to address dest if src1 as int <= src2 as uint */
OP_JGE_UINT, /* jump to address dest if src1 as int >= src2 as uint*/ OP_JGE_UINT, /* jgeu : jump to address dest if src1 as int >= src2 as uint*/
OP_UINT_TO_REAL, /* dest = src1 as f32 */ OP_UINT_TO_REAL, /* utor : dest = src1 as f32 */
OP_ADD_REAL, /* dest = src1 + src2 */ OP_ADD_REAL, /* addr : dest = src1 + src2 */
OP_SUB_REAL, /* dest = src1 - src2 */ OP_SUB_REAL, /* subr : dest = src1 - src2 */
OP_MUL_REAL, /* dest = src1 * src2 */ OP_MUL_REAL, /* mulr : dest = src1 * src2 */
OP_DIV_REAL, /* dest = src1 / src2 */ OP_DIV_REAL, /* divr : dest = src1 / src2 */
OP_JEQ_REAL, /* jump to address dest if src1 as real == src2 as real */ OP_JEQ_REAL, /* jeqr : jump to address dest if src1 as real == src2 as real */
OP_JGE_REAL, /* jump to address dest if src1 as real >= src2 as real */ OP_JGE_REAL, /* jgtr : jump to address dest if src1 as real >= src2 as real */
OP_JGT_REAL, /* jump to address dest if src1 as real > src2 as real */ OP_JGT_REAL, /* jltr : jump to address dest if src1 as real > src2 as real */
OP_JLT_REAL, /* jump to address dest if src1 as real < src2 as real */ OP_JLT_REAL, /* jler : jump to address dest if src1 as real < src2 as real */
OP_JLE_REAL, /* jump to address dest if src1 as real <= src2 as real */ OP_JLE_REAL, /* jger : jump to address dest if src1 as real <= src2 as real */
OP_REAL_TO_INT, /* dest = src1 as int */ OP_REAL_TO_INT, /* rtoi : dest = src1 as int */
OP_REAL_TO_UINT, /* dest = src1 as uint */ OP_REAL_TO_UINT, /* rtou : dest = src1 as uint */
OP_MOV, /* dest = src1 */ OP_MOV, /* move : dest = src1 */
OP_JMP, /* jump to address src1 unconditionally */ OP_JMP, /* jump : jump to address src1 unconditionally */
OP_INT_TO_STRING, /* dest = src1 as str */ OP_CALL, /* creates a new frame */
OP_UINT_TO_STRING, /* dest = src1 as str */ OP_RETURN, /* returns from a frame to the parent frame */
OP_REAL_TO_STRING, /* dest = src1 as str */ OP_INT_TO_STRING, /* itos : dest = src1 as str */
OP_READ_STRING, /* dest = read as str */ OP_UINT_TO_STRING, /* utos : dest = src1 as str */
OP_PRINT_STRING, /* write src1 to stdout */ OP_REAL_TO_STRING, /* rtos : dest = src1 as str */
OP_CMP_STRING, /* dest = (str == src2) as bool */ OP_READ_STRING, /* read : dest = read as str */
OP_PRINT_STRING, /* wrte : write src1 to stdout */
OP_CMP_STRING, /* cmps : dest = (str == src2) as bool */
} Opcode; } Opcode;
/* defines a uint32 opcode */ /* defines a uint32 opcode */

View File

@ -48,6 +48,7 @@ void initTokenMap() {
put_TokenMap(tokenMap, "ge", TOKEN_GE); put_TokenMap(tokenMap, "ge", TOKEN_GE);
put_TokenMap(tokenMap, "srl", TOKEN_SHIFTRIGHT); put_TokenMap(tokenMap, "srl", TOKEN_SHIFTRIGHT);
put_TokenMap(tokenMap, "sll", TOKEN_SHIFTLEFT); put_TokenMap(tokenMap, "sll", TOKEN_SHIFTLEFT);
put_TokenMap(tokenMap, "toS", TOKEN_TO_S);
} }
typedef struct Tokenizer Tokenizer; typedef struct Tokenizer Tokenizer;
@ -222,6 +223,10 @@ Token nextToken() {
return makeToken(TOKEN_MUL); return makeToken(TOKEN_MUL);
case ';': case ';':
return makeToken(TOKEN_SEMICOLON); return makeToken(TOKEN_SEMICOLON);
case '=':
return makeToken(TOKEN_EQUALS);
case '.':
return makeToken(TOKEN_DOT);
case '"': case '"':
return string(); return string();
} }
@ -234,6 +239,8 @@ void printToken(Token t) {
char *str = currentTokenToS(); char *str = currentTokenToS();
switch (t.type) { switch (t.type) {
PRINT_TOKEN_CASE(TOKEN_EQUALS)
PRINT_TOKEN_CASE(TOKEN_DOT)
PRINT_TOKEN_CASE(TOKEN_LEFT_PAREN) PRINT_TOKEN_CASE(TOKEN_LEFT_PAREN)
PRINT_TOKEN_CASE(TOKEN_RIGHT_PAREN) PRINT_TOKEN_CASE(TOKEN_RIGHT_PAREN)
PRINT_TOKEN_CASE(TOKEN_LEFT_BRACE) PRINT_TOKEN_CASE(TOKEN_LEFT_BRACE)
@ -299,6 +306,7 @@ void printToken(Token t) {
PRINT_TOKEN_CASE(TOKEN_BREAK) PRINT_TOKEN_CASE(TOKEN_BREAK)
PRINT_TOKEN_CASE(TOKEN_LET) PRINT_TOKEN_CASE(TOKEN_LET)
PRINT_TOKEN_CASE(TOKEN_PRINT) PRINT_TOKEN_CASE(TOKEN_PRINT)
PRINT_TOKEN_CASE(TOKEN_TO_S)
} }
free(str); free(str);
} }

View File

@ -12,6 +12,8 @@ typedef enum TokenType
TOKEN_LEFT_BRACE, TOKEN_LEFT_BRACE,
TOKEN_RIGHT_BRACE, TOKEN_RIGHT_BRACE,
TOKEN_SEMICOLON, TOKEN_SEMICOLON,
TOKEN_EQUALS,
TOKEN_DOT,
/* Literals */ /* Literals */
TOKEN_IDENTIFIER, TOKEN_IDENTIFIER,
TOKEN_STRING, TOKEN_STRING,
@ -75,6 +77,7 @@ typedef enum TokenType
TOKEN_BREAK, TOKEN_BREAK,
TOKEN_LET, TOKEN_LET,
TOKEN_PRINT, TOKEN_PRINT,
TOKEN_TO_S,
} TokenType; } TokenType;
#define PRINT_TOKEN_CASE(token_suffix) \ #define PRINT_TOKEN_CASE(token_suffix) \

View File

@ -3,17 +3,19 @@
#define COMPARE_AND_JUMP(type, accessor, op) \ #define COMPARE_AND_JUMP(type, accessor, op) \
do { \ do { \
type value = vm->frame->registers[src1].accessor; \ type value = vm->stack[vm->sp].registers[src1].accessor; \
type value2 = vm->frame->registers[src2].accessor; \ type value2 = vm->stack[vm->sp].registers[src2].accessor; \
vm->pc = (value op value2) ? dest : vm->pc; \ vm->pc = (value op value2) ? dest : vm->pc; \
return true; \ return true; \
} while (0) } while (0)
#define MATH_OP(accessor, op) \ #define MATH_OP(accessor, op) \
do { \ do { \
vm->frame->registers[dest].accessor = \ vm->stack[vm->sp].registers[dest].accessor = \
vm->frame->registers[src1] \ vm->stack[vm->sp] \
.accessor op vm->frame->registers[src2] \ .registers[src1] \
.accessor op vm->stack[vm->sp] \
.registers[src2] \
.accessor; \ .accessor; \
return true; \ return true; \
} while (0) } while (0)
@ -31,18 +33,6 @@ void mem_strcpy(Value *memory, const char *str, uint32_t length,
} }
} }
#define MEMORY_SIZE 1024
VM *init_vm() {
Value memory[MEMORY_SIZE] = {0}; /* Memory array */
VM *vm = (VM *)malloc(sizeof(VM));
vm->memory = memory;
vm->memory_size = MEMORY_SIZE;
vm->stack_size = 0;
return vm;
}
/** /**
* Step to the next opcode in the vm. * Step to the next opcode in the vm.
*/ */
@ -62,23 +52,37 @@ bool step_vm(VM *vm) {
switch (opcode) { switch (opcode) {
case OP_HALT: case OP_HALT:
return false; return false;
case OP_CALL:
vm->return_stack[vm->rp++].u = vm->pc; /* push the return address */
vm->sp++; /* increment to the next free frame */
return true;
case OP_RETURN:
vm->pc = vm->return_stack[vm->rp].u; /* set pc to return address */
Slice s = vm->stack[vm->rp].allocated;
memset(&vm->memory[s.start], 0, s.end - s.start); /* deallocate memory from slice */
vm->return_stack[vm->rp--].u = 0; /* deallocate the stack */
vm->return_stack[vm->rp] = vm->stack[vm->sp].registers[0]; /* push the return value onto the return stack (always register 0) */
return true;
case OP_LOADI: case OP_LOADI:
vm->frame->registers[dest].i = vm->memory[vm->pc++].i; vm->stack[vm->sp].registers[dest].i = vm->memory[vm->pc++].i;
return true; return true;
case OP_LOADU: case OP_LOADU:
vm->frame->registers[dest].u = vm->memory[vm->pc++].u; vm->stack[vm->sp].registers[dest].u = vm->memory[vm->pc++].u;
return true; return true;
case OP_LOADF: case OP_LOADF:
vm->frame->registers[dest].f = vm->memory[vm->pc++].f; vm->stack[vm->sp].registers[dest].f = vm->memory[vm->pc++].f;
return true; return true;
case OP_STOREI: case OP_STOREI:
vm->memory[vm->pc++].i = vm->frame->registers[src1].i; vm->memory[vm->pc++].i = vm->stack[vm->sp].registers[src1].i;
return true; return true;
case OP_STOREU: case OP_STOREU:
vm->memory[vm->pc++].u = vm->frame->registers[src1].u; vm->memory[vm->pc++].u = vm->stack[vm->sp].registers[src1].u;
return true; return true;
case OP_STOREF: case OP_STOREF:
vm->memory[vm->pc++].f = vm->frame->registers[src1].f; vm->memory[vm->pc++].f = vm->stack[vm->sp].registers[src1].f;
return true; return true;
case OP_ADD_INT: case OP_ADD_INT:
MATH_OP(i, +); MATH_OP(i, +);
@ -105,22 +109,26 @@ bool step_vm(VM *vm) {
case OP_DIV_REAL: case OP_DIV_REAL:
MATH_OP(f, /); MATH_OP(f, /);
case OP_REAL_TO_INT: case OP_REAL_TO_INT:
vm->frame->registers[dest].i = (int32_t)(vm->frame->registers[src1].f); vm->stack[vm->sp].registers[dest].i =
(int32_t)(vm->stack[vm->sp].registers[src1].f);
return true; return true;
case OP_INT_TO_REAL: case OP_INT_TO_REAL:
vm->frame->registers[dest].f = (float)(vm->frame->registers[src1].i); vm->stack[vm->sp].registers[dest].f =
(float)(vm->stack[vm->sp].registers[src1].i);
return true; return true;
case OP_REAL_TO_UINT: case OP_REAL_TO_UINT:
vm->frame->registers[dest].u = (uint32_t)(vm->frame->registers[src1].f); vm->stack[vm->sp].registers[dest].u =
(uint32_t)(vm->stack[vm->sp].registers[src1].f);
return true; return true;
case OP_UINT_TO_REAL: case OP_UINT_TO_REAL:
vm->frame->registers[dest].f = (float)(vm->frame->registers[src1].u); vm->stack[vm->sp].registers[dest].f =
(float)(vm->stack[vm->sp].registers[src1].u);
return true; return true;
case OP_MOV: case OP_MOV:
vm->frame->registers[dest] = vm->frame->registers[src1]; vm->stack[vm->sp].registers[dest] = vm->stack[vm->sp].registers[src1];
return true; return true;
case OP_JMP: case OP_JMP:
vm->pc = vm->frame->registers[src1].u; /* Jump to address */ vm->pc = vm->stack[vm->sp].registers[src1].u; /* Jump to address */
return true; return true;
case OP_JEQ_UINT: { case OP_JEQ_UINT: {
COMPARE_AND_JUMP(uint32_t, u, ==); COMPARE_AND_JUMP(uint32_t, u, ==);
@ -168,31 +176,31 @@ bool step_vm(VM *vm) {
COMPARE_AND_JUMP(float, u, <=); COMPARE_AND_JUMP(float, u, <=);
} }
case OP_INT_TO_STRING: { case OP_INT_TO_STRING: {
int32_t a = (int32_t)vm->frame->registers[src1].i; int32_t a = (int32_t)vm->stack[vm->sp].registers[src1].i;
uint32_t str_dest = (uint32_t)vm->frame->registers[dest].u; uint32_t str_dest = (uint32_t)vm->stack[vm->sp].registers[dest].u;
char buffer[32]; char buffer[32];
int len = sprintf(buffer, "%d", a); int len = sprintf(buffer, "%d", a);
mem_strcpy(vm->memory, buffer, len, str_dest); mem_strcpy(vm->memory, buffer, len, str_dest);
return true; return true;
} }
case OP_UINT_TO_STRING: { case OP_UINT_TO_STRING: {
uint32_t a = (uint32_t)vm->frame->registers[src1].u; uint32_t a = (uint32_t)vm->stack[vm->sp].registers[src1].u;
uint32_t str_dest = (uint32_t)vm->frame->registers[dest].u; uint32_t str_dest = (uint32_t)vm->stack[vm->sp].registers[dest].u;
char buffer[32]; char buffer[32];
int len = sprintf(buffer, "%d", a); int len = sprintf(buffer, "%d", a);
mem_strcpy(vm->memory, buffer, len, str_dest); mem_strcpy(vm->memory, buffer, len, str_dest);
return true; return true;
} }
case OP_REAL_TO_STRING: { case OP_REAL_TO_STRING: {
float a = (float)vm->frame->registers[src1].f; float a = (float)vm->stack[vm->sp].registers[src1].f;
uint32_t str_dest = (uint32_t)vm->frame->registers[dest].u; uint32_t str_dest = (uint32_t)vm->stack[vm->sp].registers[dest].u;
char buffer[32]; char buffer[32];
int len = sprintf(buffer, "%f", a); int len = sprintf(buffer, "%f", a);
mem_strcpy(vm->memory, buffer, len, str_dest); mem_strcpy(vm->memory, buffer, len, str_dest);
return true; return true;
} }
case OP_READ_STRING: { case OP_READ_STRING: {
uint32_t str_dest = (uint32_t)vm->frame->registers[dest].u; uint32_t str_dest = (uint32_t)vm->stack[vm->sp].registers[dest].u;
uint32_t buffer = str_dest + 1; uint32_t buffer = str_dest + 1;
uint32_t length = 0; uint32_t length = 0;
while (1) { while (1) {
@ -208,7 +216,7 @@ bool step_vm(VM *vm) {
return true; return true;
} }
case OP_PRINT_STRING: { case OP_PRINT_STRING: {
uint32_t ptr = (uint32_t)vm->frame->registers[src1].u; uint32_t ptr = (uint32_t)vm->stack[vm->sp].registers[src1].u;
uint32_t length = vm->memory[ptr].u; uint32_t length = vm->memory[ptr].u;
uint32_t str_src = ptr + 1; uint32_t str_src = ptr + 1;
uint32_t i; uint32_t i;
@ -222,8 +230,8 @@ bool step_vm(VM *vm) {
return true; return true;
} }
case OP_CMP_STRING: { case OP_CMP_STRING: {
uint32_t addr1 = (uint32_t)vm->frame->registers[src1].u; uint32_t addr1 = (uint32_t)vm->stack[vm->sp].registers[src1].u;
uint32_t addr2 = (uint32_t)vm->frame->registers[src2].u; uint32_t addr2 = (uint32_t)vm->stack[vm->sp].registers[src2].u;
uint32_t length1 = vm->memory[addr1 - 1].u; uint32_t length1 = vm->memory[addr1 - 1].u;
uint32_t length2 = vm->memory[addr2 - 1].u; uint32_t length2 = vm->memory[addr2 - 1].u;
uint32_t equal = 1; uint32_t equal = 1;

View File

@ -1 +1,2 @@
print(1 + 2); let sum = 1 + 2;
print(sum.toS());

6
test/fib.zre Normal file
View File

@ -0,0 +1,6 @@
fn fib(int n) {
if (n < 2) return n;
return fib(n - 2) + fib(n - 1);
}
print fib(35);

6
test/func-simple.zre Normal file
View File

@ -0,0 +1,6 @@
fn add(a int, b int) int {
return a + b;
}
let sum = add(1, 1);
print(sum.toS());

14
test/funcs.zre Normal file
View File

@ -0,0 +1,14 @@
fn first() {
int a = 1;
second(a, -1);
int b = 2;
second(a, b);
}
fn second(int c, int d) {
str numbers = c.toS() + " " + d.toS();
print(numbers);
! implied return because return type is null
}
first();