WIP function calls
This commit is contained in:
		
							parent
							
								
									aab4c887ca
								
							
						
					
					
						commit
						0263d1511d
					
				
							
								
								
									
										162
									
								
								src/compiler.c
								
								
								
								
							
							
						
						
									
										162
									
								
								src/compiler.c
								
								
								
								
							| 
						 | 
				
			
			@ -33,141 +33,39 @@ void demo_add_compile(Value *memory) {
 | 
			
		|||
  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) {
 | 
			
		||||
  initTokenizer(buffer);
 | 
			
		||||
  Token t = nextToken();
 | 
			
		||||
  do {
 | 
			
		||||
   while (t.type != TOKEN_EOF) {
 | 
			
		||||
    printToken(t);
 | 
			
		||||
    switch (t.type) {
 | 
			
		||||
    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;
 | 
			
		||||
    }
 | 
			
		||||
    declaration(t);
 | 
			
		||||
    t = nextToken();
 | 
			
		||||
  } while (t.type != TOKEN_EOF);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										14
									
								
								src/main.c
								
								
								
								
							
							
						
						
									
										14
									
								
								src/main.c
								
								
								
								
							| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
#include "parser.h"
 | 
			
		||||
#include "compiler.h"
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
#include "parser.h"
 | 
			
		||||
#include "vm.h"
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -16,14 +16,14 @@
 | 
			
		|||
#include <emscripten.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
VM *vm;
 | 
			
		||||
VM vm = {0};
 | 
			
		||||
 | 
			
		||||
void mainloop() {
 | 
			
		||||
  if (!step_vm(vm)) {
 | 
			
		||||
  if (!step_vm(&vm)) {
 | 
			
		||||
#ifdef __EMSCRIPTEN__
 | 
			
		||||
    emscripten_cancel_main_loop(); /* this should "kill" the app. */
 | 
			
		||||
#else
 | 
			
		||||
    core_dump(vm);
 | 
			
		||||
    core_dump(&vm);
 | 
			
		||||
    exit(0);
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -50,10 +50,8 @@ int main(int argc, char **argv) {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  initTokenMap();
 | 
			
		||||
  vm = init_vm();
 | 
			
		||||
  vm->frame = (Frame*)malloc(sizeof(Frame));
 | 
			
		||||
  compile(vm->memory, buffer);
 | 
			
		||||
  demo_add_compile(vm->memory);
 | 
			
		||||
  compile(vm.memory, buffer);
 | 
			
		||||
  /* demo_add_compile(vm.memory); */
 | 
			
		||||
 | 
			
		||||
#ifdef __EMSCRIPTEN__
 | 
			
		||||
  emscripten_set_main_loop(mainloop, 0, 1);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										123
									
								
								src/opcodes.h
								
								
								
								
							
							
						
						
									
										123
									
								
								src/opcodes.h
								
								
								
								
							| 
						 | 
				
			
			@ -10,76 +10,81 @@ typedef union {
 | 
			
		|||
  char c[4];  /* 4 Byte char array for string packing */
 | 
			
		||||
} Value;
 | 
			
		||||
 | 
			
		||||
typedef union {
 | 
			
		||||
  uint32_t length;
 | 
			
		||||
  char *string;
 | 
			
		||||
  Value *array;
 | 
			
		||||
  Value *code;
 | 
			
		||||
} Object;
 | 
			
		||||
typedef struct {
 | 
			
		||||
  uint32_t start;
 | 
			
		||||
  uint32_t end;
 | 
			
		||||
} Slice;
 | 
			
		||||
 | 
			
		||||
#define MAX_REGS 256
 | 
			
		||||
typedef struct {
 | 
			
		||||
  Value registers[MAX_REGS]; /* R0-R255 */
 | 
			
		||||
  Object *locals;            /* Short lived object */
 | 
			
		||||
  Slice allocated;
 | 
			
		||||
} Frame;
 | 
			
		||||
 | 
			
		||||
#define STACK_SIZE 128
 | 
			
		||||
#define MEMORY_SIZE 1024
 | 
			
		||||
#define STACK_SIZE 128 
 | 
			
		||||
#define RETURN_STACK_SIZE 256
 | 
			
		||||
typedef struct {
 | 
			
		||||
  Value stack[STACK_SIZE]; 
 | 
			
		||||
  uint32_t stack_size;
 | 
			
		||||
  uint32_t pc;               /* Program counter */
 | 
			
		||||
  Value *memory; 
 | 
			
		||||
  Value memory[MEMORY_SIZE]; /* Memory array */
 | 
			
		||||
  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;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  OP_HALT,           /* terminate execution */
 | 
			
		||||
  OP_LOADI,          /* dest = next memory location as int */
 | 
			
		||||
  OP_LOADU,          /* dest = next memory location as uint */
 | 
			
		||||
  OP_LOADF,          /* dest = next memory location as float */
 | 
			
		||||
  OP_STOREI,         /* next memory location = src1 as int */
 | 
			
		||||
  OP_STOREU,         /* next memory location = src1 as uint */
 | 
			
		||||
  OP_STOREF,         /* next memory location = src1 as float */
 | 
			
		||||
  OP_ADD_INT,        /* dest = src1 + src2  */
 | 
			
		||||
  OP_SUB_INT,        /* dest = src1 - src2  */
 | 
			
		||||
  OP_MUL_INT,        /* dest = src1 * src2  */
 | 
			
		||||
  OP_DIV_INT,        /* dest = src1 / src2  */
 | 
			
		||||
  OP_JEQ_INT,        /* 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_JLT_INT,        /* 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_JGE_INT,        /* jump to address dest if src1 as int >= src2 as int*/
 | 
			
		||||
  OP_INT_TO_REAL,    /* dest = src1 as f32  */
 | 
			
		||||
  OP_ADD_UINT,       /* dest = src1 + src2  */
 | 
			
		||||
  OP_SUB_UINT,       /* dest = src1 - src2  */
 | 
			
		||||
  OP_MUL_UINT,       /* dest = src1 * src2  */
 | 
			
		||||
  OP_DIV_UINT,       /* dest = src1 / src2  */
 | 
			
		||||
  OP_JEQ_UINT,       /* 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_JLT_UINT,       /* 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_JGE_UINT,       /* jump to address dest if src1 as int >= src2 as uint*/
 | 
			
		||||
  OP_UINT_TO_REAL,   /* dest = src1 as f32  */
 | 
			
		||||
  OP_ADD_REAL,       /* dest = src1 + src2  */
 | 
			
		||||
  OP_SUB_REAL,       /* dest = src1 - src2  */
 | 
			
		||||
  OP_MUL_REAL,       /* dest = src1 * src2  */
 | 
			
		||||
  OP_DIV_REAL,       /* dest = src1 / src2  */
 | 
			
		||||
  OP_JEQ_REAL,       /* 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_JGT_REAL,       /* 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_JLE_REAL,       /* jump to address dest if src1 as real <= src2 as real */
 | 
			
		||||
  OP_REAL_TO_INT,    /* dest = src1 as int  */
 | 
			
		||||
  OP_REAL_TO_UINT,   /* dest = src1 as uint  */
 | 
			
		||||
  OP_MOV,            /* dest = src1	   */
 | 
			
		||||
  OP_JMP,            /* jump to address src1 unconditionally */
 | 
			
		||||
  OP_INT_TO_STRING,  /* dest = src1 as str */
 | 
			
		||||
  OP_UINT_TO_STRING, /* dest = src1 as str */
 | 
			
		||||
  OP_REAL_TO_STRING, /* dest = src1 as str */
 | 
			
		||||
  OP_READ_STRING,    /* dest = read as str */
 | 
			
		||||
  OP_PRINT_STRING,   /* write src1 to stdout */
 | 
			
		||||
  OP_CMP_STRING,     /* dest = (str == src2) as bool */
 | 
			
		||||
  OP_HALT,    /* halt : terminate execution */
 | 
			
		||||
  OP_LOADI,   /* lodi : dest = next memory location as int */
 | 
			
		||||
  OP_LOADU,   /* lodu : dest = next memory location as uint */
 | 
			
		||||
  OP_LOADF,   /* lodf : dest = next memory location as float */
 | 
			
		||||
  OP_STOREI,  /* stri : next memory location = src1 as int */
 | 
			
		||||
  OP_STOREU,  /* stru : next memory location = src1 as uint */
 | 
			
		||||
  OP_STOREF,  /* strf : next memory location = src1 as float */
 | 
			
		||||
  OP_ADD_INT, /* addi : dest = src1 + src2  */
 | 
			
		||||
  OP_SUB_INT, /* subs : dest = src1 - src2  */
 | 
			
		||||
  OP_MUL_INT, /* mulm : dest = src1 * src2  */
 | 
			
		||||
  OP_DIV_INT, /* divd : dest = src1 / src2  */
 | 
			
		||||
  OP_JEQ_INT, /* jeqi : 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, /* jlti : 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, /* jgei : jump to address dest if src1 as int >= src2 as int*/
 | 
			
		||||
  OP_INT_TO_REAL, /* itor : dest = src1 as f32  */
 | 
			
		||||
  OP_ADD_UINT,    /* addu : dest = src1 + src2  */
 | 
			
		||||
  OP_SUB_UINT,    /* subu : dest = src1 - src2  */
 | 
			
		||||
  OP_MUL_UINT,    /* mulu : dest = src1 * src2  */
 | 
			
		||||
  OP_DIV_UINT,    /* divu : dest = src1 / src2  */
 | 
			
		||||
  OP_JEQ_UINT, /* jequ : 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, /* jltu : 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, /* jgeu : jump to address dest if src1 as int >= src2 as uint*/
 | 
			
		||||
  OP_UINT_TO_REAL, /* utor : dest = src1 as f32  */
 | 
			
		||||
  OP_ADD_REAL,     /* addr : dest = src1 + src2  */
 | 
			
		||||
  OP_SUB_REAL,     /* subr : dest = src1 - src2  */
 | 
			
		||||
  OP_MUL_REAL,     /* mulr : dest = src1 * src2  */
 | 
			
		||||
  OP_DIV_REAL,     /* divr : dest = src1 / src2  */
 | 
			
		||||
  OP_JEQ_REAL, /* jeqr : 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, /* jltr : 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, /* jger : jump to address dest if src1 as real <= src2 as real */
 | 
			
		||||
  OP_REAL_TO_INT,    /* rtoi : dest = src1 as int  */
 | 
			
		||||
  OP_REAL_TO_UINT,   /* rtou : dest = src1 as uint  */
 | 
			
		||||
  OP_MOV,            /* move : dest = src1	   */
 | 
			
		||||
  OP_JMP,            /* jump : jump to address src1 unconditionally */
 | 
			
		||||
  OP_CALL,           /* creates a new frame */
 | 
			
		||||
  OP_RETURN,         /* returns from a frame to the parent frame */
 | 
			
		||||
  OP_INT_TO_STRING,  /* itos : dest = src1 as str */
 | 
			
		||||
  OP_UINT_TO_STRING, /* utos : dest = src1 as str */
 | 
			
		||||
  OP_REAL_TO_STRING, /* rtos : dest = src1 as str */
 | 
			
		||||
  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;
 | 
			
		||||
 | 
			
		||||
/* defines a uint32 opcode */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,6 +48,7 @@ void initTokenMap() {
 | 
			
		|||
  put_TokenMap(tokenMap, "ge", TOKEN_GE);
 | 
			
		||||
  put_TokenMap(tokenMap, "srl", TOKEN_SHIFTRIGHT);
 | 
			
		||||
  put_TokenMap(tokenMap, "sll", TOKEN_SHIFTLEFT);
 | 
			
		||||
  put_TokenMap(tokenMap, "toS", TOKEN_TO_S);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct Tokenizer Tokenizer;
 | 
			
		||||
| 
						 | 
				
			
			@ -222,6 +223,10 @@ Token nextToken() {
 | 
			
		|||
    return makeToken(TOKEN_MUL);
 | 
			
		||||
  case ';':
 | 
			
		||||
    return makeToken(TOKEN_SEMICOLON);
 | 
			
		||||
  case '=':
 | 
			
		||||
    return makeToken(TOKEN_EQUALS);
 | 
			
		||||
  case '.':
 | 
			
		||||
    return makeToken(TOKEN_DOT);
 | 
			
		||||
  case '"':
 | 
			
		||||
    return string();
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -234,6 +239,8 @@ void printToken(Token t) {
 | 
			
		|||
  char *str = currentTokenToS();
 | 
			
		||||
 | 
			
		||||
  switch (t.type) {
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_EQUALS)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_DOT)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_LEFT_PAREN)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_RIGHT_PAREN)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_LEFT_BRACE)
 | 
			
		||||
| 
						 | 
				
			
			@ -299,6 +306,7 @@ void printToken(Token t) {
 | 
			
		|||
    PRINT_TOKEN_CASE(TOKEN_BREAK)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_LET)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_PRINT)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_TO_S)
 | 
			
		||||
  }
 | 
			
		||||
  free(str);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,8 @@ typedef enum TokenType
 | 
			
		|||
  TOKEN_LEFT_BRACE,
 | 
			
		||||
  TOKEN_RIGHT_BRACE,
 | 
			
		||||
  TOKEN_SEMICOLON,
 | 
			
		||||
  TOKEN_EQUALS,
 | 
			
		||||
  TOKEN_DOT,
 | 
			
		||||
  /* Literals */
 | 
			
		||||
  TOKEN_IDENTIFIER,
 | 
			
		||||
  TOKEN_STRING,
 | 
			
		||||
| 
						 | 
				
			
			@ -75,6 +77,7 @@ typedef enum TokenType
 | 
			
		|||
  TOKEN_BREAK,
 | 
			
		||||
  TOKEN_LET,
 | 
			
		||||
  TOKEN_PRINT,
 | 
			
		||||
  TOKEN_TO_S,
 | 
			
		||||
} TokenType;
 | 
			
		||||
 | 
			
		||||
#define PRINT_TOKEN_CASE(token_suffix) \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										90
									
								
								src/vm.c
								
								
								
								
							
							
						
						
									
										90
									
								
								src/vm.c
								
								
								
								
							| 
						 | 
				
			
			@ -3,19 +3,21 @@
 | 
			
		|||
 | 
			
		||||
#define COMPARE_AND_JUMP(type, accessor, op)                                   \
 | 
			
		||||
  do {                                                                         \
 | 
			
		||||
    type value = vm->frame->registers[src1].accessor;                          \
 | 
			
		||||
    type value2 = vm->frame->registers[src2].accessor;                         \
 | 
			
		||||
    type value = vm->stack[vm->sp].registers[src1].accessor;                   \
 | 
			
		||||
    type value2 = vm->stack[vm->sp].registers[src2].accessor;                  \
 | 
			
		||||
    vm->pc = (value op value2) ? dest : vm->pc;                                \
 | 
			
		||||
    return true;                                                             \
 | 
			
		||||
    return true;                                                               \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
#define MATH_OP(accessor, op)                                                  \
 | 
			
		||||
  do {                                                                         \
 | 
			
		||||
    vm->frame->registers[dest].accessor =                                      \
 | 
			
		||||
        vm->frame->registers[src1]                                             \
 | 
			
		||||
            .accessor op vm->frame->registers[src2]                            \
 | 
			
		||||
    vm->stack[vm->sp].registers[dest].accessor =                               \
 | 
			
		||||
        vm->stack[vm->sp]                                                      \
 | 
			
		||||
            .registers[src1]                                                   \
 | 
			
		||||
            .accessor op vm->stack[vm->sp]                                     \
 | 
			
		||||
            .registers[src2]                                                   \
 | 
			
		||||
            .accessor;                                                         \
 | 
			
		||||
    return true;                                                             \
 | 
			
		||||
    return true;                                                               \
 | 
			
		||||
  } 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.
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -62,23 +52,37 @@ bool step_vm(VM *vm) {
 | 
			
		|||
  switch (opcode) {
 | 
			
		||||
  case OP_HALT:
 | 
			
		||||
    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:
 | 
			
		||||
    vm->frame->registers[dest].i = vm->memory[vm->pc++].i;
 | 
			
		||||
    vm->stack[vm->sp].registers[dest].i = vm->memory[vm->pc++].i;
 | 
			
		||||
    return true;
 | 
			
		||||
  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;
 | 
			
		||||
  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;
 | 
			
		||||
  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;
 | 
			
		||||
  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;
 | 
			
		||||
  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;
 | 
			
		||||
  case OP_ADD_INT:
 | 
			
		||||
    MATH_OP(i, +);
 | 
			
		||||
| 
						 | 
				
			
			@ -105,22 +109,26 @@ bool step_vm(VM *vm) {
 | 
			
		|||
  case OP_DIV_REAL:
 | 
			
		||||
    MATH_OP(f, /);
 | 
			
		||||
  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;
 | 
			
		||||
  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;
 | 
			
		||||
  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;
 | 
			
		||||
  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;
 | 
			
		||||
  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;
 | 
			
		||||
  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;
 | 
			
		||||
  case OP_JEQ_UINT: {
 | 
			
		||||
    COMPARE_AND_JUMP(uint32_t, u, ==);
 | 
			
		||||
| 
						 | 
				
			
			@ -168,31 +176,31 @@ bool step_vm(VM *vm) {
 | 
			
		|||
    COMPARE_AND_JUMP(float, u, <=);
 | 
			
		||||
  }
 | 
			
		||||
  case OP_INT_TO_STRING: {
 | 
			
		||||
    int32_t a = (int32_t)vm->frame->registers[src1].i;
 | 
			
		||||
    uint32_t str_dest = (uint32_t)vm->frame->registers[dest].u;
 | 
			
		||||
    int32_t a = (int32_t)vm->stack[vm->sp].registers[src1].i;
 | 
			
		||||
    uint32_t str_dest = (uint32_t)vm->stack[vm->sp].registers[dest].u;
 | 
			
		||||
    char buffer[32];
 | 
			
		||||
    int len = sprintf(buffer, "%d", a);
 | 
			
		||||
    mem_strcpy(vm->memory, buffer, len, str_dest);
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  case OP_UINT_TO_STRING: {
 | 
			
		||||
    uint32_t a = (uint32_t)vm->frame->registers[src1].u;
 | 
			
		||||
    uint32_t str_dest = (uint32_t)vm->frame->registers[dest].u;
 | 
			
		||||
    uint32_t a = (uint32_t)vm->stack[vm->sp].registers[src1].u;
 | 
			
		||||
    uint32_t str_dest = (uint32_t)vm->stack[vm->sp].registers[dest].u;
 | 
			
		||||
    char buffer[32];
 | 
			
		||||
    int len = sprintf(buffer, "%d", a);
 | 
			
		||||
    mem_strcpy(vm->memory, buffer, len, str_dest);
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  case OP_REAL_TO_STRING: {
 | 
			
		||||
    float a = (float)vm->frame->registers[src1].f;
 | 
			
		||||
    uint32_t str_dest = (uint32_t)vm->frame->registers[dest].u;
 | 
			
		||||
    float a = (float)vm->stack[vm->sp].registers[src1].f;
 | 
			
		||||
    uint32_t str_dest = (uint32_t)vm->stack[vm->sp].registers[dest].u;
 | 
			
		||||
    char buffer[32];
 | 
			
		||||
    int len = sprintf(buffer, "%f", a);
 | 
			
		||||
    mem_strcpy(vm->memory, buffer, len, str_dest);
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  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 length = 0;
 | 
			
		||||
    while (1) {
 | 
			
		||||
| 
						 | 
				
			
			@ -208,7 +216,7 @@ bool step_vm(VM *vm) {
 | 
			
		|||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  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 str_src = ptr + 1;
 | 
			
		||||
    uint32_t i;
 | 
			
		||||
| 
						 | 
				
			
			@ -222,8 +230,8 @@ bool step_vm(VM *vm) {
 | 
			
		|||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  case OP_CMP_STRING: {
 | 
			
		||||
    uint32_t addr1 = (uint32_t)vm->frame->registers[src1].u;
 | 
			
		||||
    uint32_t addr2 = (uint32_t)vm->frame->registers[src2].u;
 | 
			
		||||
    uint32_t addr1 = (uint32_t)vm->stack[vm->sp].registers[src1].u;
 | 
			
		||||
    uint32_t addr2 = (uint32_t)vm->stack[vm->sp].registers[src2].u;
 | 
			
		||||
    uint32_t length1 = vm->memory[addr1 - 1].u;
 | 
			
		||||
    uint32_t length2 = vm->memory[addr2 - 1].u;
 | 
			
		||||
    uint32_t equal = 1;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1 +1,2 @@
 | 
			
		|||
print(1 + 2);
 | 
			
		||||
let sum = 1 + 2;
 | 
			
		||||
print(sum.toS());
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
fn fib(int n) {
 | 
			
		||||
  if (n < 2) return n;
 | 
			
		||||
  return fib(n - 2) + fib(n - 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
print fib(35);
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
fn add(a int, b int) int {
 | 
			
		||||
  return a + b;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
let sum = add(1, 1);
 | 
			
		||||
print(sum.toS());
 | 
			
		||||
| 
						 | 
				
			
			@ -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();
 | 
			
		||||
		Loading…
	
		Reference in New Issue