Compare commits
	
		
			No commits in common. "cc009b4a4a9b4322472bc3d1f030b6d9117f207d" and "70b9a82a971f3425e62257c0e92b16e88bf0b420" have entirely different histories.
		
	
	
		
			cc009b4a4a
			...
			70b9a82a97
		
	
		| 
						 | 
					@ -6,7 +6,7 @@
 | 
				
			||||||
!
 | 
					!
 | 
				
			||||||
! Camera .
 | 
					! Camera .
 | 
				
			||||||
!
 | 
					!
 | 
				
			||||||
plex Camera {
 | 
					type Camera {
 | 
				
			||||||
  init(real[3] pos, real[3] look) {
 | 
					  init(real[3] pos, real[3] look) {
 | 
				
			||||||
    this.setting = "CAMERA_PERSPECTIVE";
 | 
					    this.setting = "CAMERA_PERSPECTIVE";
 | 
				
			||||||
    this.pov = 45.0;
 | 
					    this.pov = 45.0;
 | 
				
			||||||
| 
						 | 
					@ -19,7 +19,7 @@ plex Camera {
 | 
				
			||||||
!
 | 
					!
 | 
				
			||||||
! Player .
 | 
					! Player .
 | 
				
			||||||
!
 | 
					!
 | 
				
			||||||
plex Player {
 | 
					type Player {
 | 
				
			||||||
  init(str username, real[3] pos, Color color) {
 | 
					  init(str username, real[3] pos, Color color) {
 | 
				
			||||||
    this.server = Client("tcp://localhost:25565");
 | 
					    this.server = Client("tcp://localhost:25565");
 | 
				
			||||||
    this.username = username;
 | 
					    this.username = username;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,157 +0,0 @@
 | 
				
			||||||
#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,5 +1,6 @@
 | 
				
			||||||
#include "../../compiler.h"
 | 
					#include "../../compiler.h"
 | 
				
			||||||
#include "../../vm.h"
 | 
					#include "../../vm.h"
 | 
				
			||||||
 | 
					#include <SDL2/SDL.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MAX_SRC_SIZE 16384
 | 
					#define MAX_SRC_SIZE 16384
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -63,9 +64,94 @@ int main(int argc, char **argv) {
 | 
				
			||||||
    return 64;
 | 
					    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;
 | 
					  bool running = true;
 | 
				
			||||||
  while (running) {
 | 
					  while (running) {
 | 
				
			||||||
    running = step_vm(&vm);
 | 
					    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;
 | 
					  return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										123
									
								
								src/compiler.c
								
								
								
								
							
							
						
						
									
										123
									
								
								src/compiler.c
								
								
								
								
							| 
						 | 
					@ -51,7 +51,9 @@ void errorAt(Token *token, const char *message) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void error(const char *message) { errorAt(&parser.previous, 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() {
 | 
					void advance() {
 | 
				
			||||||
  parser.previous = parser.current;
 | 
					  parser.previous = parser.current;
 | 
				
			||||||
| 
						 | 
					@ -74,16 +76,20 @@ void consume(TokenType type, const char *message) {
 | 
				
			||||||
  errorAtCurrent(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) {
 | 
					static bool match(TokenType type) {
 | 
				
			||||||
  if (!check(type))
 | 
					  if (!check(type)) return false;
 | 
				
			||||||
    return false;
 | 
					 | 
				
			||||||
  advance();
 | 
					  advance();
 | 
				
			||||||
  return true;
 | 
					  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);
 | 
					  vm->code[vm->cp++].u = OP(opcode, dest, src1, src2);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -149,23 +155,22 @@ void unary(VM *vm) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void literal(VM *vm) {
 | 
					static void literal(VM *vm) {
 | 
				
			||||||
  switch (parser.previous.type) {
 | 
					  switch (parser.previous.type) {
 | 
				
			||||||
  case TOKEN_KEYWORD_NIL: {
 | 
					    case TOKEN_KEYWORD_NIL: {
 | 
				
			||||||
    emitOp(vm, OP_LOADU, vm->frames[vm->fp].rp++, 0, 0);
 | 
					      emitOp(vm, OP_LOADU, vm->frames[vm->fp].rp++, 0, 0);
 | 
				
			||||||
    vm->code[vm->cp++].u = 0;
 | 
					      vm->code[vm->cp++].u = 0; 
 | 
				
			||||||
    break;
 | 
					      break;
 | 
				
			||||||
  }
 | 
					    }    
 | 
				
			||||||
  case TOKEN_KEYWORD_FALSE: {
 | 
					    case TOKEN_KEYWORD_FALSE: {
 | 
				
			||||||
    emitOp(vm, OP_LOADU, vm->frames[vm->fp].rp++, 0, 0);
 | 
					      emitOp(vm, OP_LOADU, vm->frames[vm->fp].rp++, 0, 0);
 | 
				
			||||||
    vm->code[vm->cp++].u = 0;
 | 
					      vm->code[vm->cp++].u = 0; 
 | 
				
			||||||
    break;
 | 
					      break;
 | 
				
			||||||
  }
 | 
					    }
 | 
				
			||||||
  case TOKEN_KEYWORD_TRUE: {
 | 
					    case TOKEN_KEYWORD_TRUE: {
 | 
				
			||||||
    emitOp(vm, OP_LOADU, vm->frames[vm->fp].rp++, 0, 0);
 | 
					       emitOp(vm, OP_LOADU, vm->frames[vm->fp].rp++, 0, 0);
 | 
				
			||||||
    vm->code[vm->cp++].u = 1;
 | 
					       vm->code[vm->cp++].u = 1;
 | 
				
			||||||
    break;
 | 
					       break;
 | 
				
			||||||
  }
 | 
					    }
 | 
				
			||||||
  default:
 | 
					    default: return;
 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -175,18 +180,25 @@ void binary(VM *vm) {
 | 
				
			||||||
  parsePrecedence(vm, (Precedence)(rule->precedence + 1));
 | 
					  parsePrecedence(vm, (Precedence)(rule->precedence + 1));
 | 
				
			||||||
  TokenType operandType = parser.previous.type;
 | 
					  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) {
 | 
					  switch (operatorType) {
 | 
				
			||||||
  case TOKEN_PLUS:
 | 
					  case TOKEN_PLUS:
 | 
				
			||||||
    if (operandType == TOKEN_UINT_LITERAL) {
 | 
					    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);
 | 
					      emitOp(vm, OP_ADD_UINT, dest, src1, src2);
 | 
				
			||||||
    } else if (operandType == TOKEN_INT_LITERAL) {
 | 
					    } 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);
 | 
					      emitOp(vm, OP_ADD_INT, dest, src1, src2);
 | 
				
			||||||
    } else if (operandType == TOKEN_FLOAT_LITERAL) {
 | 
					    } 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);
 | 
					      emitOp(vm, OP_ADD_REAL, dest, src1, src2);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      error("not numeric");
 | 
					      error("not numeric");
 | 
				
			||||||
| 
						 | 
					@ -194,10 +206,22 @@ void binary(VM *vm) {
 | 
				
			||||||
    break;
 | 
					    break;
 | 
				
			||||||
  case TOKEN_MINUS:
 | 
					  case TOKEN_MINUS:
 | 
				
			||||||
    if (operandType == TOKEN_UINT_LITERAL) {
 | 
					    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);
 | 
					      emitOp(vm, OP_SUB_UINT, dest, src1, src2);
 | 
				
			||||||
    } else if (operandType == TOKEN_INT_LITERAL) {
 | 
					    } 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);
 | 
					      emitOp(vm, OP_SUB_INT, dest, src1, src2);
 | 
				
			||||||
    } else if (operandType == TOKEN_FLOAT_LITERAL) {
 | 
					    } 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);
 | 
					      emitOp(vm, OP_SUB_REAL, dest, src1, src2);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      error("not numeric");
 | 
					      error("not numeric");
 | 
				
			||||||
| 
						 | 
					@ -205,10 +229,22 @@ void binary(VM *vm) {
 | 
				
			||||||
    break;
 | 
					    break;
 | 
				
			||||||
  case TOKEN_STAR:
 | 
					  case TOKEN_STAR:
 | 
				
			||||||
    if (operandType == TOKEN_UINT_LITERAL) {
 | 
					    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);
 | 
					      emitOp(vm, OP_MUL_UINT, dest, src1, src2);
 | 
				
			||||||
    } else if (operandType == TOKEN_INT_LITERAL) {
 | 
					    } 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);
 | 
					      emitOp(vm, OP_MUL_INT, dest, src1, src2);
 | 
				
			||||||
    } else if (operandType == TOKEN_FLOAT_LITERAL) {
 | 
					    } 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);
 | 
					      emitOp(vm, OP_MUL_REAL, dest, src1, src2);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      error("not numeric");
 | 
					      error("not numeric");
 | 
				
			||||||
| 
						 | 
					@ -216,10 +252,22 @@ void binary(VM *vm) {
 | 
				
			||||||
    break;
 | 
					    break;
 | 
				
			||||||
  case TOKEN_SLASH:
 | 
					  case TOKEN_SLASH:
 | 
				
			||||||
    if (operandType == TOKEN_UINT_LITERAL) {
 | 
					    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);
 | 
					      emitOp(vm, OP_DIV_UINT, dest, src1, src2);
 | 
				
			||||||
    } else if (operandType == TOKEN_INT_LITERAL) {
 | 
					    } 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);
 | 
					      emitOp(vm, OP_DIV_INT, dest, src1, src2);
 | 
				
			||||||
    } else if (operandType == TOKEN_FLOAT_LITERAL) {
 | 
					    } 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);
 | 
					      emitOp(vm, OP_DIV_REAL, dest, src1, src2);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      error("not numeric");
 | 
					      error("not numeric");
 | 
				
			||||||
| 
						 | 
					@ -299,7 +347,7 @@ void printStatement(VM *vm) {
 | 
				
			||||||
  expression(vm);
 | 
					  expression(vm);
 | 
				
			||||||
  consume(TOKEN_SEMICOLON, "Expect ';' after value.");
 | 
					  consume(TOKEN_SEMICOLON, "Expect ';' after value.");
 | 
				
			||||||
  Frame f = vm->frames[vm->fp];
 | 
					  Frame f = vm->frames[vm->fp];
 | 
				
			||||||
  vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, f.rp--, 0);
 | 
					  vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, f.rp--, 0); 
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void expressionStatement(VM *vm) {
 | 
					static void expressionStatement(VM *vm) {
 | 
				
			||||||
| 
						 | 
					@ -307,29 +355,18 @@ static void expressionStatement(VM *vm) {
 | 
				
			||||||
  consume(TOKEN_SEMICOLON, "Expect ';' after expression.");
 | 
					  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) {
 | 
					void statement(VM *vm) {
 | 
				
			||||||
  if (match(TOKEN_KEYWORD_PRINT)) {
 | 
					  if (match(TOKEN_KEYWORD_PRINT)) {
 | 
				
			||||||
    printStatement(vm);
 | 
					    printStatement(vm);
 | 
				
			||||||
  } else if (match(TOKEN_TYPE_INT)) {
 | 
					 | 
				
			||||||
    intDeclaration(vm);
 | 
					 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    expressionStatement(vm);
 | 
					    expressionStatement(vm);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void declaration(VM *vm) { statement(vm); }
 | 
					void declaration(VM *vm) {
 | 
				
			||||||
 | 
					  statement(vm);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool compile(const char *source, VM *vm) {
 | 
					bool compile(const char *source, VM *vm) {
 | 
				
			||||||
  initLexer(source);
 | 
					  initLexer(source);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,42 +4,7 @@
 | 
				
			||||||
#include "lexer.h"
 | 
					#include "lexer.h"
 | 
				
			||||||
#include "opcodes.h"
 | 
					#include "opcodes.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef enum { INT, REAL, NATURAL, POINTER, STRING, ARRAY, PLEX } SymbolType;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct plex_def_t {
 | 
					bool compile(const char* source, VM* vm);
 | 
				
			||||||
  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
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										10
									
								
								src/debug.c
								
								
								
								
							
							
						
						
									
										10
									
								
								src/debug.c
								
								
								
								
							| 
						 | 
					@ -172,14 +172,8 @@ void printOp(uint8_t op, uint8_t dest, uint8_t src1, uint8_t src2) {
 | 
				
			||||||
  case OP_REAL_TO_UINT:
 | 
					  case OP_REAL_TO_UINT:
 | 
				
			||||||
    printf("[REAL_TO_UINT] $%d, $%d, $%d\n", dest, src1, src2);
 | 
					    printf("[REAL_TO_UINT] $%d, $%d, $%d\n", dest, src1, src2);
 | 
				
			||||||
    break;
 | 
					    break;
 | 
				
			||||||
  case OP_MEM_MOV:
 | 
					  case OP_MOV:
 | 
				
			||||||
    printf("[MEM_MOV] $%d, $%d, $%d\n", dest, src1, src2);
 | 
					    printf("[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;
 | 
					    break;
 | 
				
			||||||
  case OP_JMP:
 | 
					  case OP_JMP:
 | 
				
			||||||
    printf("[JMP] $%d, $%d, $%d\n", dest, src1, src2);
 | 
					    printf("[JMP] $%d, $%d, $%d\n", dest, src1, src2);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										12
									
								
								src/lexer.c
								
								
								
								
							
							
						
						
									
										12
									
								
								src/lexer.c
								
								
								
								
							| 
						 | 
					@ -127,15 +127,7 @@ static TokenType identifierType() {
 | 
				
			||||||
  case 'o':
 | 
					  case 'o':
 | 
				
			||||||
    return checkKeyword(1, 1, "r", TOKEN_OPERATOR_OR);
 | 
					    return checkKeyword(1, 1, "r", TOKEN_OPERATOR_OR);
 | 
				
			||||||
  case 'p':
 | 
					  case 'p':
 | 
				
			||||||
    if (lexer.current - lexer.start > 1) {
 | 
					    return checkKeyword(1, 4, "rint", TOKEN_KEYWORD_PRINT);
 | 
				
			||||||
      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':
 | 
					  case 'r':
 | 
				
			||||||
    return checkKeyword(1, 5, "eturn", TOKEN_KEYWORD_RETURN);
 | 
					    return checkKeyword(1, 5, "eturn", TOKEN_KEYWORD_RETURN);
 | 
				
			||||||
  case 't':
 | 
					  case 't':
 | 
				
			||||||
| 
						 | 
					@ -145,6 +137,8 @@ static TokenType identifierType() {
 | 
				
			||||||
        return checkKeyword(2, 2, "is", TOKEN_KEYWORD_THIS);
 | 
					        return checkKeyword(2, 2, "is", TOKEN_KEYWORD_THIS);
 | 
				
			||||||
      case 'r':
 | 
					      case 'r':
 | 
				
			||||||
        return checkKeyword(2, 2, "ue", TOKEN_KEYWORD_TRUE);
 | 
					        return checkKeyword(2, 2, "ue", TOKEN_KEYWORD_TRUE);
 | 
				
			||||||
 | 
					      case 'y':
 | 
				
			||||||
 | 
					        return checkKeyword(2, 2, "pe", TOKEN_KEYWORD_TYPE);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    break;
 | 
					    break;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@ typedef enum {
 | 
				
			||||||
  TOKEN_TYPE_NAT,
 | 
					  TOKEN_TYPE_NAT,
 | 
				
			||||||
  TOKEN_TYPE_REAL,
 | 
					  TOKEN_TYPE_REAL,
 | 
				
			||||||
  TOKEN_TYPE_STR,
 | 
					  TOKEN_TYPE_STR,
 | 
				
			||||||
  TOKEN_KEYWORD_PLEX,
 | 
					  TOKEN_KEYWORD_TYPE,
 | 
				
			||||||
  TOKEN_KEYWORD_FN,
 | 
					  TOKEN_KEYWORD_FN,
 | 
				
			||||||
  TOKEN_KEYWORD_LET,
 | 
					  TOKEN_KEYWORD_LET,
 | 
				
			||||||
  TOKEN_KEYWORD_CONST,
 | 
					  TOKEN_KEYWORD_CONST,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,7 +37,7 @@ typedef struct mouse_t {
 | 
				
			||||||
  uint8_t btn3;
 | 
					  uint8_t btn3;
 | 
				
			||||||
} Mouse;
 | 
					} Mouse;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct keyboard_t {
 | 
					typedef struct keyboard_t {   
 | 
				
			||||||
  uint32_t length;
 | 
					  uint32_t length;
 | 
				
			||||||
  const uint8_t *keys;
 | 
					  const uint8_t *keys;
 | 
				
			||||||
} Keyboard;
 | 
					} Keyboard;
 | 
				
			||||||
| 
						 | 
					@ -47,13 +47,11 @@ typedef union device_u {
 | 
				
			||||||
  Screen s;
 | 
					  Screen s;
 | 
				
			||||||
  Mouse m;
 | 
					  Mouse m;
 | 
				
			||||||
  Keyboard k;
 | 
					  Keyboard k;
 | 
				
			||||||
  /* File f; */
 | 
					 | 
				
			||||||
  /* Tunnel t; */
 | 
					 | 
				
			||||||
} Device;
 | 
					} Device;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MEMORY_SIZE 65536
 | 
					#define MEMORY_SIZE 65536
 | 
				
			||||||
#define CODE_SIZE 8192
 | 
					#define CODE_SIZE 8192
 | 
				
			||||||
#define FRAMES_SIZE 128
 | 
					#define FRAMES_SIZE 128 
 | 
				
			||||||
#define STACK_SIZE 256
 | 
					#define STACK_SIZE 256
 | 
				
			||||||
#define DEVICES_SIZE 8
 | 
					#define DEVICES_SIZE 8
 | 
				
			||||||
typedef struct vm_s {
 | 
					typedef struct vm_s {
 | 
				
			||||||
| 
						 | 
					@ -79,21 +77,21 @@ typedef struct vm_s {
 | 
				
			||||||
} VM;
 | 
					} VM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
  OP_HALT,   /* halt : terminate execution */
 | 
					  OP_HALT,    /* halt : terminate execution */
 | 
				
			||||||
  OP_LOADI,  /* lodi : dest = next memory location as int */
 | 
					  OP_LOADI,   /* lodi : dest = next memory location as int */
 | 
				
			||||||
  OP_LOADU,  /* lodu : dest = next memory location as uint */
 | 
					  OP_LOADU,   /* lodu : dest = next memory location as uint */
 | 
				
			||||||
  OP_LOADF,  /* lodf : dest = next memory location as float */
 | 
					  OP_LOADF,   /* lodf : dest = next memory location as float */
 | 
				
			||||||
  OP_STOREI, /* stri : next memory location = src1 as int */
 | 
					  OP_STOREI,  /* stri : next memory location = src1 as int */
 | 
				
			||||||
  OP_STOREU, /* stru : next memory location = src1 as uint */
 | 
					  OP_STOREU,  /* stru : next memory location = src1 as uint */
 | 
				
			||||||
  OP_STOREF, /* strf : next memory location = src1 as float */
 | 
					  OP_STOREF,  /* strf : next memory location = src1 as float */
 | 
				
			||||||
  OP_PUSHI,  /* pshi : push int from register onto the stack */
 | 
					  OP_PUSHI,   /* pshi : push int from register onto the stack */
 | 
				
			||||||
  OP_PUSHU,  /* pshu : push uint from register onto the stack */
 | 
					  OP_PUSHU,   /* pshu : push uint from register onto the stack */
 | 
				
			||||||
  OP_PUSHF,  /* pshf : push float from register onto the stack */
 | 
					  OP_PUSHF,   /* pshf : push float from register onto the stack */
 | 
				
			||||||
  OP_PUSHS, /* pshs : push str ref from register onto the stack and copy str  */
 | 
					  OP_PUSHS,   /* pshs : push str ref from register onto the stack and copy str  */
 | 
				
			||||||
  OP_POPI,  /* popi : pop int from stack onto the register */
 | 
					  OP_POPI,    /* popi : pop int from stack onto the register */
 | 
				
			||||||
  OP_POPU,  /* popu : pop uint from stack onto the register */
 | 
					  OP_POPU,    /* popu : pop uint from stack onto the register */
 | 
				
			||||||
  OP_POPF,  /* popf : pop float from stack onto the register */
 | 
					  OP_POPF,    /* popf : pop float from stack onto the register */
 | 
				
			||||||
  OP_POPS,  /* pops : pop str ref from stack and move/copy to register */
 | 
					  OP_POPS,    /* pops : pop str ref from stack and move/copy to register */
 | 
				
			||||||
  OP_ADD_INT, /* addi : dest = src1 + src2  */
 | 
					  OP_ADD_INT, /* addi : dest = src1 + src2  */
 | 
				
			||||||
  OP_SUB_INT, /* subi : dest = src1 - src2  */
 | 
					  OP_SUB_INT, /* subi : dest = src1 - src2  */
 | 
				
			||||||
  OP_MUL_INT, /* muli : dest = src1 * src2  */
 | 
					  OP_MUL_INT, /* muli : dest = src1 * src2  */
 | 
				
			||||||
| 
						 | 
					@ -125,8 +123,7 @@ typedef enum {
 | 
				
			||||||
  OP_JLE_REAL, /* jger : 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_INT,    /* rtoi : dest = src1 as int  */
 | 
				
			||||||
  OP_REAL_TO_UINT,   /* rtou : dest = src1 as uint  */
 | 
					  OP_REAL_TO_UINT,   /* rtou : dest = src1 as uint  */
 | 
				
			||||||
  OP_REG_MOV,        /* rmov : dest = src1	   */
 | 
					  OP_MOV,            /* move : dest = src1	   */
 | 
				
			||||||
  OP_REG_SWAP,       /* rswp : dest = src1, src1 = dest	   */
 | 
					 | 
				
			||||||
  OP_JMP,            /* jump : jump to address src1 unconditionally */
 | 
					  OP_JMP,            /* jump : jump to address src1 unconditionally */
 | 
				
			||||||
  OP_CALL,           /* call : creates a new frame */
 | 
					  OP_CALL,           /* call : creates a new frame */
 | 
				
			||||||
  OP_RETURN,         /* retn : returns from a frame to the parent frame */
 | 
					  OP_RETURN,         /* retn : returns from a frame to the parent frame */
 | 
				
			||||||
| 
						 | 
					@ -136,10 +133,7 @@ typedef enum {
 | 
				
			||||||
  OP_READ_STRING,    /* gets : dest = gets as str */
 | 
					  OP_READ_STRING,    /* gets : dest = gets as str */
 | 
				
			||||||
  OP_PRINT_STRING,   /* puts : write src1 to stdout */
 | 
					  OP_PRINT_STRING,   /* puts : write src1 to stdout */
 | 
				
			||||||
  OP_CMP_STRING,     /* cmps : dest = (str == src2) as bool */
 | 
					  OP_CMP_STRING,     /* cmps : dest = (str == src2) as bool */
 | 
				
			||||||
  OP_NOT,            /* not   : dest = not src1 */
 | 
					  OP_NOT,
 | 
				
			||||||
  OP_MEM_ALLOC,      /* alloc : dest = &ptr */
 | 
					 | 
				
			||||||
  OP_MEM_SWAP,       /* swap : &dest = &src1, &src1 = &dest */
 | 
					 | 
				
			||||||
  OP_MEM_MOV,        /* mov  : &dest = &src1 */
 | 
					 | 
				
			||||||
} Opcode;
 | 
					} Opcode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										37
									
								
								src/vm.c
								
								
								
								
							
							
						
						
									
										37
									
								
								src/vm.c
								
								
								
								
							| 
						 | 
					@ -150,16 +150,8 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
    vm->frames[vm->fp].registers[dest].f =
 | 
					    vm->frames[vm->fp].registers[dest].f =
 | 
				
			||||||
        (float)(vm->frames[vm->fp].registers[src1].u);
 | 
					        (float)(vm->frames[vm->fp].registers[src1].u);
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
  case OP_REG_SWAP:
 | 
					  case OP_MOV:
 | 
				
			||||||
    vm->frames[vm->fp].registers[dest].u ^=
 | 
					    vm->frames[vm->fp].registers[dest] = vm->frames[vm->fp].registers[src1];
 | 
				
			||||||
        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;
 | 
					    return true;
 | 
				
			||||||
  case OP_JMP:
 | 
					  case OP_JMP:
 | 
				
			||||||
    vm->pc = vm->frames[vm->fp].registers[dest].u; /* Jump to address */
 | 
					    vm->pc = vm->frames[vm->fp].registers[dest].u; /* Jump to address */
 | 
				
			||||||
| 
						 | 
					@ -296,31 +288,6 @@ bool step_vm(VM *vm) {
 | 
				
			||||||
    vm->memory[dest].u = equal;
 | 
					    vm->memory[dest].u = equal;
 | 
				
			||||||
    return true;
 | 
					    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 */
 | 
					  return false; /* something bad happened */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,4 +3,4 @@ fn add(int a, int b) int {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int sum = add(1, 1);
 | 
					int sum = add(1, 1);
 | 
				
			||||||
print(sum.str);
 | 
					print(sum.toS());
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1 +1 @@
 | 
				
			||||||
print("nuqneH 'u'?");
 | 
					print("nuqheH 'u'?");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,2 +1,2 @@
 | 
				
			||||||
int sum = 1 + 2;
 | 
					int sum = 1 + 2;
 | 
				
			||||||
print(sum.str);
 | 
					print(sum.toS());
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue