Compare commits
	
		
			3 Commits
		
	
	
		
			70b9a82a97
			...
			cc009b4a4a
		
	
	| Author | SHA1 | Date | 
|---|---|---|
| 
							
							
								
								 | 
						cc009b4a4a | |
| 
							
							
								
								 | 
						b21de2d1fc | |
| 
							
							
								
								 | 
						63d67b5c0d | 
| 
						 | 
				
			
			@ -6,7 +6,7 @@
 | 
			
		|||
!
 | 
			
		||||
! Camera .
 | 
			
		||||
!
 | 
			
		||||
type Camera {
 | 
			
		||||
plex Camera {
 | 
			
		||||
  init(real[3] pos, real[3] look) {
 | 
			
		||||
    this.setting = "CAMERA_PERSPECTIVE";
 | 
			
		||||
    this.pov = 45.0;
 | 
			
		||||
| 
						 | 
				
			
			@ -19,7 +19,7 @@ type Camera {
 | 
			
		|||
!
 | 
			
		||||
! Player .
 | 
			
		||||
!
 | 
			
		||||
type Player {
 | 
			
		||||
plex Player {
 | 
			
		||||
  init(str username, real[3] pos, Color color) {
 | 
			
		||||
    this.server = Client("tcp://localhost:25565");
 | 
			
		||||
    this.username = username;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,157 @@
 | 
			
		|||
#include "../../compiler.h"
 | 
			
		||||
#include "../../vm.h"
 | 
			
		||||
#include <SDL2/SDL.h>
 | 
			
		||||
 | 
			
		||||
#define MAX_SRC_SIZE 16384
 | 
			
		||||
 | 
			
		||||
void compileFile(const char *path, VM *vm) {
 | 
			
		||||
  FILE *f = fopen(path, "rb");
 | 
			
		||||
  if (!f) {
 | 
			
		||||
    perror("fopen");
 | 
			
		||||
    exit(1);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static char source[MAX_SRC_SIZE + 1];
 | 
			
		||||
 | 
			
		||||
  fseek(f, 0, SEEK_END);
 | 
			
		||||
  long len = ftell(f);
 | 
			
		||||
  fseek(f, 0, SEEK_SET);
 | 
			
		||||
  if (len >= MAX_SRC_SIZE) {
 | 
			
		||||
    perror("source is larget than buffer");
 | 
			
		||||
    exit(1);
 | 
			
		||||
  }
 | 
			
		||||
  size_t read = fread(source, 1, len, f);
 | 
			
		||||
  source[read] = '\0';
 | 
			
		||||
  fclose(f);
 | 
			
		||||
 | 
			
		||||
  compile(source, vm);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void repl(VM *vm) {
 | 
			
		||||
  char line[1024];
 | 
			
		||||
  for (;;) {
 | 
			
		||||
    printf("> ");
 | 
			
		||||
 | 
			
		||||
    if (!fgets(line, sizeof(line), stdin)) {
 | 
			
		||||
      printf("\n");
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    /* reset the code counter to 0 */
 | 
			
		||||
    vm->cp = 0;
 | 
			
		||||
    vm->sp = 0;
 | 
			
		||||
    vm->pc = 0;
 | 
			
		||||
    vm->mp = 0;
 | 
			
		||||
 | 
			
		||||
    compile(line, vm);
 | 
			
		||||
    while (step_vm(vm));
 | 
			
		||||
  }
 | 
			
		||||
  exit(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv) {
 | 
			
		||||
  VM vm = {0};
 | 
			
		||||
  vm.frames_size = FRAMES_SIZE;
 | 
			
		||||
  vm.return_stack_size = STACK_SIZE;
 | 
			
		||||
  vm.stack_size = STACK_SIZE;
 | 
			
		||||
  vm.memory_size = MEMORY_SIZE;
 | 
			
		||||
 | 
			
		||||
  if (argc == 1) {
 | 
			
		||||
    repl(&vm);
 | 
			
		||||
  } else if (argc == 2) {
 | 
			
		||||
    compileFile(argv[1], &vm);
 | 
			
		||||
  } else {
 | 
			
		||||
    fprintf(stderr, "Usage: %s <file.zrl>\n", argv[0]);
 | 
			
		||||
    return 64;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  uint32_t buffer_size = 640 * 480 * sizeof(uint32_t);
 | 
			
		||||
 | 
			
		||||
  Device screen;
 | 
			
		||||
  screen.type = SCREEN;
 | 
			
		||||
  screen.s = (Screen){.width = (uint8_t)480,
 | 
			
		||||
                      .height = (uint8_t)640,
 | 
			
		||||
                      .allocated = {vm.mp, buffer_size},
 | 
			
		||||
                      .buffer = &vm.memory[vm.mp]};
 | 
			
		||||
  vm.devices[vm.dp++] = screen;
 | 
			
		||||
  vm.mp += buffer_size;
 | 
			
		||||
 | 
			
		||||
  Device mouse;
 | 
			
		||||
  mouse.type = MOUSE;
 | 
			
		||||
  mouse.m = (Mouse){.x = 0, .y = 0, .btn1 = 0, .btn2 = 0, .btn3 = 0};
 | 
			
		||||
  vm.devices[vm.dp++] = mouse;
 | 
			
		||||
 | 
			
		||||
  Device keyboard;
 | 
			
		||||
  keyboard.type = KEYBOARD;
 | 
			
		||||
  const uint8_t *state = SDL_GetKeyboardState(NULL);
 | 
			
		||||
  keyboard.k = (Keyboard){.length = SDL_NUM_SCANCODES, .keys = state};
 | 
			
		||||
  vm.devices[vm.dp++] = keyboard;
 | 
			
		||||
 | 
			
		||||
  /* Create window and renderer */
 | 
			
		||||
  SDL_Window *window =
 | 
			
		||||
      SDL_CreateWindow("Reality Engine VM", SDL_WINDOWPOS_CENTERED,
 | 
			
		||||
                       SDL_WINDOWPOS_CENTERED, screen.s.width, screen.s.height,
 | 
			
		||||
                       SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI);
 | 
			
		||||
 | 
			
		||||
  SDL_Renderer *renderer = SDL_CreateRenderer(
 | 
			
		||||
      window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
 | 
			
		||||
 | 
			
		||||
  /* Create texture for 640x480 buffer */
 | 
			
		||||
  SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888,
 | 
			
		||||
                                           SDL_TEXTUREACCESS_STREAMING,
 | 
			
		||||
                                           screen.s.width, screen.s.height);
 | 
			
		||||
 | 
			
		||||
  /* Enable nearest-neighbor scaling (preserves pixel art) */
 | 
			
		||||
  SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); /* "0" = nearest-neighbor */
 | 
			
		||||
 | 
			
		||||
  bool running = true;
 | 
			
		||||
  while (running) {
 | 
			
		||||
    step_vm(&vm);
 | 
			
		||||
    SDL_PumpEvents();
 | 
			
		||||
    SDL_Event event;
 | 
			
		||||
    while (SDL_PollEvent(&event)) {
 | 
			
		||||
      switch (event.type) {
 | 
			
		||||
      case SDL_QUIT:
 | 
			
		||||
        running = false;
 | 
			
		||||
        break;
 | 
			
		||||
      case SDL_MOUSEBUTTONDOWN:
 | 
			
		||||
        printf("mouse_down: x=%d, y=%d, btn=%d\n", event.button.x,
 | 
			
		||||
               event.button.y, event.button.button);
 | 
			
		||||
        break;
 | 
			
		||||
      case SDL_MOUSEMOTION:
 | 
			
		||||
        printf("mouse_move: x=%d, y=%d\n", event.motion.x, event.motion.y);
 | 
			
		||||
        break;
 | 
			
		||||
      case SDL_FINGERDOWN:
 | 
			
		||||
        printf("touch_down x=%d, y=%d\n",
 | 
			
		||||
               (int)(event.tfinger.x * screen.s.width),
 | 
			
		||||
               (int)(event.tfinger.y * screen.s.height));
 | 
			
		||||
        break;
 | 
			
		||||
      case SDL_FINGERMOTION:
 | 
			
		||||
        printf("touch_move x=%d, y=%d\n",
 | 
			
		||||
               (int)(event.tfinger.x * screen.s.width),
 | 
			
		||||
               (int)(event.tfinger.y * screen.s.height));
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SDL_UpdateTexture(texture, NULL, screen.s.buffer,
 | 
			
		||||
                      screen.s.width * sizeof(uint32_t));
 | 
			
		||||
 | 
			
		||||
    SDL_RenderClear(renderer);
 | 
			
		||||
 | 
			
		||||
    /* (Scales to fit screen while preserving pixel grid) */
 | 
			
		||||
    SDL_Rect output_rect;
 | 
			
		||||
    SDL_RenderGetViewport(renderer, &output_rect);
 | 
			
		||||
    float scale_x = (float)output_rect.w / screen.s.width;
 | 
			
		||||
    float scale_y = (float)output_rect.h / screen.s.height;
 | 
			
		||||
    float scale = SDL_min(scale_x, scale_y);
 | 
			
		||||
 | 
			
		||||
    SDL_Rect dstrect = {(int)((output_rect.w - screen.s.width * scale) / 2),
 | 
			
		||||
                        (int)((output_rect.h - screen.s.height * scale) / 2),
 | 
			
		||||
                        (int)(screen.s.width * scale),
 | 
			
		||||
                        (int)(screen.s.height * scale)};
 | 
			
		||||
 | 
			
		||||
    SDL_RenderCopy(renderer, texture, NULL, &dstrect);
 | 
			
		||||
    SDL_RenderPresent(renderer);
 | 
			
		||||
  }
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,5 @@
 | 
			
		|||
#include "../../compiler.h"
 | 
			
		||||
#include "../../vm.h"
 | 
			
		||||
#include <SDL2/SDL.h>
 | 
			
		||||
 | 
			
		||||
#define MAX_SRC_SIZE 16384
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -64,94 +63,9 @@ int main(int argc, char **argv) {
 | 
			
		|||
    return 64;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  uint32_t buffer_size = 640 * 480 * sizeof(uint32_t);
 | 
			
		||||
 | 
			
		||||
  Device screen;
 | 
			
		||||
  screen.type = SCREEN;
 | 
			
		||||
  screen.s = (Screen){.width = (uint8_t)480,
 | 
			
		||||
                      .height = (uint8_t)640,
 | 
			
		||||
                      .allocated = {vm.mp, buffer_size},
 | 
			
		||||
                      .buffer = &vm.memory[vm.mp]};
 | 
			
		||||
  vm.devices[vm.dp++] = screen;
 | 
			
		||||
  vm.mp += buffer_size;
 | 
			
		||||
 | 
			
		||||
  Device mouse;
 | 
			
		||||
  mouse.type = MOUSE;
 | 
			
		||||
  mouse.m = (Mouse){.x = 0, .y = 0, .btn1 = 0, .btn2 = 0, .btn3 = 0};
 | 
			
		||||
  vm.devices[vm.dp++] = mouse;
 | 
			
		||||
 | 
			
		||||
  Device keyboard;
 | 
			
		||||
  keyboard.type = KEYBOARD;
 | 
			
		||||
  const uint8_t *state = SDL_GetKeyboardState(NULL);
 | 
			
		||||
  keyboard.k = (Keyboard){.length = SDL_NUM_SCANCODES, .keys = state};
 | 
			
		||||
  vm.devices[vm.dp++] = keyboard;
 | 
			
		||||
 | 
			
		||||
  /* Create window and renderer */
 | 
			
		||||
  SDL_Window *window =
 | 
			
		||||
      SDL_CreateWindow("Reality Engine VM", SDL_WINDOWPOS_CENTERED,
 | 
			
		||||
                       SDL_WINDOWPOS_CENTERED, screen.s.width, screen.s.height,
 | 
			
		||||
                       SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI);
 | 
			
		||||
 | 
			
		||||
  SDL_Renderer *renderer = SDL_CreateRenderer(
 | 
			
		||||
      window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
 | 
			
		||||
 | 
			
		||||
  /* Create texture for 640x480 buffer */
 | 
			
		||||
  SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888,
 | 
			
		||||
                                           SDL_TEXTUREACCESS_STREAMING,
 | 
			
		||||
                                           screen.s.width, screen.s.height);
 | 
			
		||||
 | 
			
		||||
  /* Enable nearest-neighbor scaling (preserves pixel art) */
 | 
			
		||||
  SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); /* "0" = nearest-neighbor */
 | 
			
		||||
 | 
			
		||||
  bool running = true;
 | 
			
		||||
  while (running) {
 | 
			
		||||
    step_vm(&vm);
 | 
			
		||||
    SDL_PumpEvents();
 | 
			
		||||
    SDL_Event event;
 | 
			
		||||
    while (SDL_PollEvent(&event)) {
 | 
			
		||||
      switch (event.type) {
 | 
			
		||||
      case SDL_QUIT:
 | 
			
		||||
        running = false;
 | 
			
		||||
        break;
 | 
			
		||||
      case SDL_MOUSEBUTTONDOWN:
 | 
			
		||||
        printf("mouse_down: x=%d, y=%d, btn=%d\n", event.button.x,
 | 
			
		||||
               event.button.y, event.button.button);
 | 
			
		||||
        break;
 | 
			
		||||
      case SDL_MOUSEMOTION:
 | 
			
		||||
        printf("mouse_move: x=%d, y=%d\n", event.motion.x, event.motion.y);
 | 
			
		||||
        break;
 | 
			
		||||
      case SDL_FINGERDOWN:
 | 
			
		||||
        printf("touch_down x=%d, y=%d\n",
 | 
			
		||||
               (int)(event.tfinger.x * screen.s.width),
 | 
			
		||||
               (int)(event.tfinger.y * screen.s.height));
 | 
			
		||||
        break;
 | 
			
		||||
      case SDL_FINGERMOTION:
 | 
			
		||||
        printf("touch_move x=%d, y=%d\n",
 | 
			
		||||
               (int)(event.tfinger.x * screen.s.width),
 | 
			
		||||
               (int)(event.tfinger.y * screen.s.height));
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SDL_UpdateTexture(texture, NULL, screen.s.buffer,
 | 
			
		||||
                      screen.s.width * sizeof(uint32_t));
 | 
			
		||||
 | 
			
		||||
    SDL_RenderClear(renderer);
 | 
			
		||||
 | 
			
		||||
    /* (Scales to fit screen while preserving pixel grid) */
 | 
			
		||||
    SDL_Rect output_rect;
 | 
			
		||||
    SDL_RenderGetViewport(renderer, &output_rect);
 | 
			
		||||
    float scale_x = (float)output_rect.w / screen.s.width;
 | 
			
		||||
    float scale_y = (float)output_rect.h / screen.s.height;
 | 
			
		||||
    float scale = SDL_min(scale_x, scale_y);
 | 
			
		||||
 | 
			
		||||
    SDL_Rect dstrect = {(int)((output_rect.w - screen.s.width * scale) / 2),
 | 
			
		||||
                        (int)((output_rect.h - screen.s.height * scale) / 2),
 | 
			
		||||
                        (int)(screen.s.width * scale),
 | 
			
		||||
                        (int)(screen.s.height * scale)};
 | 
			
		||||
 | 
			
		||||
    SDL_RenderCopy(renderer, texture, NULL, &dstrect);
 | 
			
		||||
    SDL_RenderPresent(renderer);
 | 
			
		||||
    running = step_vm(&vm);
 | 
			
		||||
  }
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -51,9 +51,7 @@ void errorAt(Token *token, const char *message) {
 | 
			
		|||
 | 
			
		||||
void error(const char *message) { errorAt(&parser.previous, message); }
 | 
			
		||||
 | 
			
		||||
void errorAtCurrent(const char *message) {
 | 
			
		||||
  errorAt(&parser.current, message);
 | 
			
		||||
}
 | 
			
		||||
void errorAtCurrent(const char *message) { errorAt(&parser.current, message); }
 | 
			
		||||
 | 
			
		||||
void advance() {
 | 
			
		||||
  parser.previous = parser.current;
 | 
			
		||||
| 
						 | 
				
			
			@ -76,20 +74,16 @@ void consume(TokenType type, const char *message) {
 | 
			
		|||
  errorAtCurrent(message);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static bool check(TokenType type) {
 | 
			
		||||
  return parser.current.type == type;
 | 
			
		||||
}
 | 
			
		||||
static bool check(TokenType type) { return parser.current.type == type; }
 | 
			
		||||
 | 
			
		||||
static bool match(TokenType type) {
 | 
			
		||||
  if (!check(type)) return false;
 | 
			
		||||
  if (!check(type))
 | 
			
		||||
    return false;
 | 
			
		||||
  advance();
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void emitOp(VM *vm, uint8_t opcode, uint8_t dest, uint8_t src1,
 | 
			
		||||
                   uint8_t src2) {
 | 
			
		||||
void emitOp(VM *vm, uint8_t opcode, uint8_t dest, uint8_t src1, uint8_t src2) {
 | 
			
		||||
  vm->code[vm->cp++].u = OP(opcode, dest, src1, src2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -170,7 +164,8 @@ static void literal(VM *vm) {
 | 
			
		|||
    vm->code[vm->cp++].u = 1;
 | 
			
		||||
    break;
 | 
			
		||||
  }
 | 
			
		||||
    default: return;
 | 
			
		||||
  default:
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -180,25 +175,18 @@ void binary(VM *vm) {
 | 
			
		|||
  parsePrecedence(vm, (Precedence)(rule->precedence + 1));
 | 
			
		||||
  TokenType operandType = parser.previous.type;
 | 
			
		||||
 | 
			
		||||
  Frame f = vm->frames[vm->fp];
 | 
			
		||||
  uint32_t src1 = f.rp--;
 | 
			
		||||
  uint32_t src2 = f.rp--;
 | 
			
		||||
  uint32_t dest = f.rp++;
 | 
			
		||||
 | 
			
		||||
  switch (operatorType) {
 | 
			
		||||
  case TOKEN_PLUS:
 | 
			
		||||
    if (operandType == TOKEN_UINT_LITERAL) {
 | 
			
		||||
      Frame f = vm->frames[vm->fp];
 | 
			
		||||
      uint32_t src1 = f.rp--;
 | 
			
		||||
      uint32_t src2 = f.rp--;
 | 
			
		||||
      uint32_t dest = f.rp++;
 | 
			
		||||
      emitOp(vm, OP_ADD_UINT, dest, src1, src2);
 | 
			
		||||
    } else if (operandType == TOKEN_INT_LITERAL) {
 | 
			
		||||
      Frame f = vm->frames[vm->fp];
 | 
			
		||||
      uint32_t src1 = f.rp--;
 | 
			
		||||
      uint32_t src2 = f.rp--;
 | 
			
		||||
      uint32_t dest = f.rp++;
 | 
			
		||||
      emitOp(vm, OP_ADD_INT, dest, src1, src2);
 | 
			
		||||
    } else if (operandType == TOKEN_FLOAT_LITERAL) {
 | 
			
		||||
      Frame f = vm->frames[vm->fp];
 | 
			
		||||
      uint32_t src1 = f.rp--;
 | 
			
		||||
      uint32_t src2 = f.rp--;
 | 
			
		||||
      uint32_t dest = f.rp++;
 | 
			
		||||
      emitOp(vm, OP_ADD_REAL, dest, src1, src2);
 | 
			
		||||
    } else {
 | 
			
		||||
      error("not numeric");
 | 
			
		||||
| 
						 | 
				
			
			@ -206,22 +194,10 @@ void binary(VM *vm) {
 | 
			
		|||
    break;
 | 
			
		||||
  case TOKEN_MINUS:
 | 
			
		||||
    if (operandType == TOKEN_UINT_LITERAL) {
 | 
			
		||||
      Frame f = vm->frames[vm->fp];
 | 
			
		||||
      uint32_t src1 = f.rp--;
 | 
			
		||||
      uint32_t src2 = f.rp--;
 | 
			
		||||
      uint32_t dest = f.rp++;
 | 
			
		||||
      emitOp(vm, OP_SUB_UINT, dest, src1, src2);
 | 
			
		||||
    } else if (operandType == TOKEN_INT_LITERAL) {
 | 
			
		||||
      Frame f = vm->frames[vm->fp];
 | 
			
		||||
      uint32_t src1 = f.rp--;
 | 
			
		||||
      uint32_t src2 = f.rp--;
 | 
			
		||||
      uint32_t dest = f.rp++;
 | 
			
		||||
      emitOp(vm, OP_SUB_INT, dest, src1, src2);
 | 
			
		||||
    } else if (operandType == TOKEN_FLOAT_LITERAL) {
 | 
			
		||||
      Frame f = vm->frames[vm->fp];
 | 
			
		||||
      uint32_t src1 = f.rp--;
 | 
			
		||||
      uint32_t src2 = f.rp--;
 | 
			
		||||
      uint32_t dest = f.rp++;
 | 
			
		||||
      emitOp(vm, OP_SUB_REAL, dest, src1, src2);
 | 
			
		||||
    } else {
 | 
			
		||||
      error("not numeric");
 | 
			
		||||
| 
						 | 
				
			
			@ -229,22 +205,10 @@ void binary(VM *vm) {
 | 
			
		|||
    break;
 | 
			
		||||
  case TOKEN_STAR:
 | 
			
		||||
    if (operandType == TOKEN_UINT_LITERAL) {
 | 
			
		||||
      Frame f = vm->frames[vm->fp];
 | 
			
		||||
      uint32_t src1 = f.rp--;
 | 
			
		||||
      uint32_t src2 = f.rp--;
 | 
			
		||||
      uint32_t dest = f.rp++;
 | 
			
		||||
      emitOp(vm, OP_MUL_UINT, dest, src1, src2);
 | 
			
		||||
    } else if (operandType == TOKEN_INT_LITERAL) {
 | 
			
		||||
      Frame f = vm->frames[vm->fp];
 | 
			
		||||
      uint32_t src1 = f.rp--;
 | 
			
		||||
      uint32_t src2 = f.rp--;
 | 
			
		||||
      uint32_t dest = f.rp++;
 | 
			
		||||
      emitOp(vm, OP_MUL_INT, dest, src1, src2);
 | 
			
		||||
    } else if (operandType == TOKEN_FLOAT_LITERAL) {
 | 
			
		||||
      Frame f = vm->frames[vm->fp];
 | 
			
		||||
      uint32_t src1 = f.rp--;
 | 
			
		||||
      uint32_t src2 = f.rp--;
 | 
			
		||||
      uint32_t dest = f.rp++;
 | 
			
		||||
      emitOp(vm, OP_MUL_REAL, dest, src1, src2);
 | 
			
		||||
    } else {
 | 
			
		||||
      error("not numeric");
 | 
			
		||||
| 
						 | 
				
			
			@ -252,22 +216,10 @@ void binary(VM *vm) {
 | 
			
		|||
    break;
 | 
			
		||||
  case TOKEN_SLASH:
 | 
			
		||||
    if (operandType == TOKEN_UINT_LITERAL) {
 | 
			
		||||
      Frame f = vm->frames[vm->fp];
 | 
			
		||||
      uint32_t src1 = f.rp--;
 | 
			
		||||
      uint32_t src2 = f.rp--;
 | 
			
		||||
      uint32_t dest = f.rp++;
 | 
			
		||||
      emitOp(vm, OP_DIV_UINT, dest, src1, src2);
 | 
			
		||||
    } else if (operandType == TOKEN_INT_LITERAL) {
 | 
			
		||||
      Frame f = vm->frames[vm->fp];
 | 
			
		||||
      uint32_t src1 = f.rp--;
 | 
			
		||||
      uint32_t src2 = f.rp--;
 | 
			
		||||
      uint32_t dest = f.rp++;
 | 
			
		||||
      emitOp(vm, OP_DIV_INT, dest, src1, src2);
 | 
			
		||||
    } else if (operandType == TOKEN_FLOAT_LITERAL) {
 | 
			
		||||
      Frame f = vm->frames[vm->fp];
 | 
			
		||||
      uint32_t src1 = f.rp--;
 | 
			
		||||
      uint32_t src2 = f.rp--;
 | 
			
		||||
      uint32_t dest = f.rp++;
 | 
			
		||||
      emitOp(vm, OP_DIV_REAL, dest, src1, src2);
 | 
			
		||||
    } else {
 | 
			
		||||
      error("not numeric");
 | 
			
		||||
| 
						 | 
				
			
			@ -355,18 +307,29 @@ static void expressionStatement(VM *vm) {
 | 
			
		|||
  consume(TOKEN_SEMICOLON, "Expect ';' after expression.");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void intDeclaration(VM *vm) {
 | 
			
		||||
  /* insert variable name in symbol table */
 | 
			
		||||
 | 
			
		||||
  if (match(TOKEN_EQ)) {
 | 
			
		||||
    expression(vm);
 | 
			
		||||
  } else {
 | 
			
		||||
    /* not sure here yet */
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  consume(TOKEN_SEMICOLON, "Expect ';' after expression.");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void statement(VM *vm) {
 | 
			
		||||
  if (match(TOKEN_KEYWORD_PRINT)) {
 | 
			
		||||
    printStatement(vm);
 | 
			
		||||
  } else if (match(TOKEN_TYPE_INT)) {
 | 
			
		||||
    intDeclaration(vm);
 | 
			
		||||
  } else {
 | 
			
		||||
    expressionStatement(vm);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void declaration(VM *vm) {
 | 
			
		||||
  statement(vm);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void declaration(VM *vm) { statement(vm); }
 | 
			
		||||
 | 
			
		||||
bool compile(const char *source, VM *vm) {
 | 
			
		||||
  initLexer(source);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,42 @@
 | 
			
		|||
#include "lexer.h"
 | 
			
		||||
#include "opcodes.h"
 | 
			
		||||
 | 
			
		||||
typedef enum { INT, REAL, NATURAL, POINTER, STRING, ARRAY, PLEX } SymbolType;
 | 
			
		||||
 | 
			
		||||
bool compile(const char* source, VM* vm);
 | 
			
		||||
typedef struct plex_def_t {
 | 
			
		||||
  SymbolType subtype;
 | 
			
		||||
  uint32_t size; 
 | 
			
		||||
} PlexDef;
 | 
			
		||||
 | 
			
		||||
typedef struct array_def_t {
 | 
			
		||||
  SymbolType subtype;
 | 
			
		||||
  uint32_t length; 
 | 
			
		||||
} ArrayDef;
 | 
			
		||||
 | 
			
		||||
#define SYMBOL_NAME_SIZE 24
 | 
			
		||||
 | 
			
		||||
typedef struct symbol_table_t {
 | 
			
		||||
  char name[SYMBOL_NAME_SIZE];
 | 
			
		||||
  SymbolType type;
 | 
			
		||||
  union {
 | 
			
		||||
    PlexDef pd;
 | 
			
		||||
    ArrayDef ad;
 | 
			
		||||
  };
 | 
			
		||||
  int8_t reg;
 | 
			
		||||
  union {
 | 
			
		||||
    uint32_t frame;
 | 
			
		||||
    uint32_t ptr;
 | 
			
		||||
  };
 | 
			
		||||
} Symbol;
 | 
			
		||||
 | 
			
		||||
#define MODULE_NAME_SIZE 32
 | 
			
		||||
#define SYMBOL_COUNT 256
 | 
			
		||||
 | 
			
		||||
typedef struct module_t {
 | 
			
		||||
  char name[MODULE_NAME_SIZE];
 | 
			
		||||
  Symbol symbols[SYMBOL_COUNT];
 | 
			
		||||
} Module;
 | 
			
		||||
 | 
			
		||||
bool compile(const char *source, VM *vm);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										10
									
								
								src/debug.c
								
								
								
								
							
							
						
						
									
										10
									
								
								src/debug.c
								
								
								
								
							| 
						 | 
				
			
			@ -172,8 +172,14 @@ void printOp(uint8_t op, uint8_t dest, uint8_t src1, uint8_t src2) {
 | 
			
		|||
  case OP_REAL_TO_UINT:
 | 
			
		||||
    printf("[REAL_TO_UINT] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_MOV:
 | 
			
		||||
    printf("[MOV] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
  case OP_MEM_MOV:
 | 
			
		||||
    printf("[MEM_MOV] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_MEM_ALLOC:
 | 
			
		||||
    printf("[MEM_ALLOC] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_MEM_SWAP:
 | 
			
		||||
    printf("[MEM_SWP] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
    break;
 | 
			
		||||
  case OP_JMP:
 | 
			
		||||
    printf("[JMP] $%d, $%d, $%d\n", dest, src1, src2);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										12
									
								
								src/lexer.c
								
								
								
								
							
							
						
						
									
										12
									
								
								src/lexer.c
								
								
								
								
							| 
						 | 
				
			
			@ -127,7 +127,15 @@ static TokenType identifierType() {
 | 
			
		|||
  case 'o':
 | 
			
		||||
    return checkKeyword(1, 1, "r", TOKEN_OPERATOR_OR);
 | 
			
		||||
  case 'p':
 | 
			
		||||
    return checkKeyword(1, 4, "rint", TOKEN_KEYWORD_PRINT);
 | 
			
		||||
    if (lexer.current - lexer.start > 1) {
 | 
			
		||||
      switch (lexer.start[1]) {
 | 
			
		||||
      case 'l':
 | 
			
		||||
        return checkKeyword(2, 2, "ex", TOKEN_KEYWORD_PLEX);
 | 
			
		||||
      case 'r':
 | 
			
		||||
        return checkKeyword(2, 3, "int", TOKEN_KEYWORD_PRINT);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    break;
 | 
			
		||||
  case 'r':
 | 
			
		||||
    return checkKeyword(1, 5, "eturn", TOKEN_KEYWORD_RETURN);
 | 
			
		||||
  case 't':
 | 
			
		||||
| 
						 | 
				
			
			@ -137,8 +145,6 @@ static TokenType identifierType() {
 | 
			
		|||
        return checkKeyword(2, 2, "is", TOKEN_KEYWORD_THIS);
 | 
			
		||||
      case 'r':
 | 
			
		||||
        return checkKeyword(2, 2, "ue", TOKEN_KEYWORD_TRUE);
 | 
			
		||||
      case 'y':
 | 
			
		||||
        return checkKeyword(2, 2, "pe", TOKEN_KEYWORD_TYPE);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    break;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,7 +12,7 @@ typedef enum {
 | 
			
		|||
  TOKEN_TYPE_NAT,
 | 
			
		||||
  TOKEN_TYPE_REAL,
 | 
			
		||||
  TOKEN_TYPE_STR,
 | 
			
		||||
  TOKEN_KEYWORD_TYPE,
 | 
			
		||||
  TOKEN_KEYWORD_PLEX,
 | 
			
		||||
  TOKEN_KEYWORD_FN,
 | 
			
		||||
  TOKEN_KEYWORD_LET,
 | 
			
		||||
  TOKEN_KEYWORD_CONST,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,6 +47,8 @@ typedef union device_u {
 | 
			
		|||
  Screen s;
 | 
			
		||||
  Mouse m;
 | 
			
		||||
  Keyboard k;
 | 
			
		||||
  /* File f; */
 | 
			
		||||
  /* Tunnel t; */
 | 
			
		||||
} Device;
 | 
			
		||||
 | 
			
		||||
#define MEMORY_SIZE 65536
 | 
			
		||||
| 
						 | 
				
			
			@ -123,7 +125,8 @@ typedef enum {
 | 
			
		|||
  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_REG_MOV,        /* rmov : dest = src1	   */
 | 
			
		||||
  OP_REG_SWAP,       /* rswp : dest = src1, src1 = dest	   */
 | 
			
		||||
  OP_JMP,            /* jump : jump to address src1 unconditionally */
 | 
			
		||||
  OP_CALL,           /* call : creates a new frame */
 | 
			
		||||
  OP_RETURN,         /* retn : returns from a frame to the parent frame */
 | 
			
		||||
| 
						 | 
				
			
			@ -133,7 +136,10 @@ typedef enum {
 | 
			
		|||
  OP_READ_STRING,    /* gets : dest = gets as str */
 | 
			
		||||
  OP_PRINT_STRING,   /* puts : write src1 to stdout */
 | 
			
		||||
  OP_CMP_STRING,     /* cmps : dest = (str == src2) as bool */
 | 
			
		||||
  OP_NOT,
 | 
			
		||||
  OP_NOT,            /* not   : dest = not src1 */
 | 
			
		||||
  OP_MEM_ALLOC,      /* alloc : dest = &ptr */
 | 
			
		||||
  OP_MEM_SWAP,       /* swap : &dest = &src1, &src1 = &dest */
 | 
			
		||||
  OP_MEM_MOV,        /* mov  : &dest = &src1 */
 | 
			
		||||
} Opcode;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										37
									
								
								src/vm.c
								
								
								
								
							
							
						
						
									
										37
									
								
								src/vm.c
								
								
								
								
							| 
						 | 
				
			
			@ -150,8 +150,16 @@ bool step_vm(VM *vm) {
 | 
			
		|||
    vm->frames[vm->fp].registers[dest].f =
 | 
			
		||||
        (float)(vm->frames[vm->fp].registers[src1].u);
 | 
			
		||||
    return true;
 | 
			
		||||
  case OP_MOV:
 | 
			
		||||
    vm->frames[vm->fp].registers[dest] = vm->frames[vm->fp].registers[src1];
 | 
			
		||||
  case OP_REG_SWAP:
 | 
			
		||||
    vm->frames[vm->fp].registers[dest].u ^=
 | 
			
		||||
        vm->frames[vm->fp].registers[src1].u;
 | 
			
		||||
    vm->frames[vm->fp].registers[src1].u ^=
 | 
			
		||||
        vm->frames[vm->fp].registers[dest].u;
 | 
			
		||||
    vm->frames[vm->fp].registers[dest].u ^=
 | 
			
		||||
        vm->frames[vm->fp].registers[src1].u;
 | 
			
		||||
    return true;
 | 
			
		||||
  case OP_REG_MOV:
 | 
			
		||||
    vm->frames[vm->fp].registers[dest].i = vm->code[vm->pc++].i;
 | 
			
		||||
    return true;
 | 
			
		||||
  case OP_JMP:
 | 
			
		||||
    vm->pc = vm->frames[vm->fp].registers[dest].u; /* Jump to address */
 | 
			
		||||
| 
						 | 
				
			
			@ -288,6 +296,31 @@ bool step_vm(VM *vm) {
 | 
			
		|||
    vm->memory[dest].u = equal;
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  case OP_MEM_ALLOC: {
 | 
			
		||||
    uint32_t mem_dest = (uint32_t)vm->frames[vm->fp]
 | 
			
		||||
                            .allocated.end; /* get start of unallocated */
 | 
			
		||||
    vm->frames[vm->fp].registers[dest].u =
 | 
			
		||||
        mem_dest; /* store ptr of array to dest register */
 | 
			
		||||
    uint32_t length = vm->code[vm->pc++].u;
 | 
			
		||||
    vm->memory[mem_dest].u = length;
 | 
			
		||||
    if (src1) { /* if has inline data */
 | 
			
		||||
      uint32_t i = 0;
 | 
			
		||||
      for (i = 0; i < length; i++) {
 | 
			
		||||
        vm->memory[mem_dest + i] = vm->code[vm->pc++];
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    vm->frames[vm->fp].allocated.end +=
 | 
			
		||||
        length; /* increment to end of allocated */
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  case OP_MEM_MOV:
 | 
			
		||||
    vm->memory[dest] = vm->memory[src1];
 | 
			
		||||
    return true;
 | 
			
		||||
  case OP_MEM_SWAP:
 | 
			
		||||
    vm->memory[dest].u ^= vm->memory[src1].u;
 | 
			
		||||
    vm->memory[src1].u ^= vm->memory[dest].u;
 | 
			
		||||
    vm->memory[dest].u ^= vm->memory[src1].u;
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  return false; /* something bad happened */
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,4 +3,4 @@ fn add(int a, int b) int {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
int sum = add(1, 1);
 | 
			
		||||
print(sum.toS());
 | 
			
		||||
print(sum.str);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1 +1 @@
 | 
			
		|||
print("nuqheH 'u'?");
 | 
			
		||||
print("nuqneH 'u'?");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,2 +1,2 @@
 | 
			
		|||
int sum = 1 + 2;
 | 
			
		||||
print(sum.toS());
 | 
			
		||||
print(sum.str);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue