Compare commits
	
		
			2 Commits
		
	
	
		
			9c94e4a6ef
			...
			49f7189470
		
	
	| Author | SHA1 | Date | 
|---|---|---|
| 
							
							
								
								 | 
						49f7189470 | |
| 
							
							
								
								 | 
						fefc9e803a | 
| 
						 | 
				
			
			@ -7,7 +7,7 @@
 | 
			
		|||
! Camera .
 | 
			
		||||
!!
 | 
			
		||||
type Camera {
 | 
			
		||||
  init(pos [3]real, look [3]real) {
 | 
			
		||||
  init(real[3] pos, real[3] look) {
 | 
			
		||||
    this.setting = "CAMERA_PERSPECTIVE";
 | 
			
		||||
    this.pov = 45.0;
 | 
			
		||||
    this.up = [0.0, 1.0, 0.0];
 | 
			
		||||
| 
						 | 
				
			
			@ -20,7 +20,7 @@ type Camera {
 | 
			
		|||
! Player .
 | 
			
		||||
!!
 | 
			
		||||
type Player {
 | 
			
		||||
  init(username str, pos real[3], color Color) {
 | 
			
		||||
  init(str username, real[3] pos, Color color) {
 | 
			
		||||
    this.server = Client("tcp://localhost:25565");
 | 
			
		||||
    this.username = username;
 | 
			
		||||
    this.pos = pos;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,6 @@
 | 
			
		|||
#define ZRE_DEBUG_H
 | 
			
		||||
 | 
			
		||||
#include "vm.h"
 | 
			
		||||
#include "parser.h"
 | 
			
		||||
#include "opcodes.h"
 | 
			
		||||
 | 
			
		||||
int core_dump(VM *vm);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,89 +0,0 @@
 | 
			
		|||
#ifndef HASHMAP_H
 | 
			
		||||
#define HASHMAP_H
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
char *strdup(const char *s) {
 | 
			
		||||
  size_t len = strlen(s) + 1;
 | 
			
		||||
  char *copy = (char*)malloc(len);
 | 
			
		||||
  if (copy) {
 | 
			
		||||
    memcpy(copy, s, len);
 | 
			
		||||
  }
 | 
			
		||||
  return copy;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define DEFINE_HASHMAP(StructType, HASHSIZE) \
 | 
			
		||||
unsigned int hash_##StructType(char *s) { \
 | 
			
		||||
  unsigned int hashval; \
 | 
			
		||||
  for (hashval = 0; *s != '\0'; s++) \
 | 
			
		||||
    hashval = *s + 31 * hashval; \
 | 
			
		||||
  return hashval % HASHSIZE; \
 | 
			
		||||
} \
 | 
			
		||||
\
 | 
			
		||||
StructType *get_##StructType(StructType **map, char *s) { \
 | 
			
		||||
  StructType *np; \
 | 
			
		||||
  for (np = map[hash_##StructType(s)]; np != NULL; np = np->next) \
 | 
			
		||||
    if (strcmp(s, np->keyword) == 0) \
 | 
			
		||||
      return np; \
 | 
			
		||||
  return NULL; \
 | 
			
		||||
} \
 | 
			
		||||
\
 | 
			
		||||
StructType *put_##StructType(StructType **map, char *keyword, TokenType token) { \
 | 
			
		||||
  StructType *np; \
 | 
			
		||||
  unsigned int hashval; \
 | 
			
		||||
  if ((np = get_##StructType(map, keyword)) == NULL) { \
 | 
			
		||||
    np = (StructType *)malloc(sizeof(*np)); \
 | 
			
		||||
    if (np == NULL || (np->keyword = strdup(keyword)) == NULL) \
 | 
			
		||||
      return NULL; \
 | 
			
		||||
    hashval = hash_##StructType(keyword); \
 | 
			
		||||
    np->next = map[hashval]; \
 | 
			
		||||
    map[hashval] = np; \
 | 
			
		||||
  } \
 | 
			
		||||
  np->token = token; \
 | 
			
		||||
  return np; \
 | 
			
		||||
} \
 | 
			
		||||
\
 | 
			
		||||
int delete_##StructType(StructType **map, char *keyword) { \
 | 
			
		||||
  unsigned int hashval = hash_##StructType(keyword); \
 | 
			
		||||
  StructType *current = map[hashval]; \
 | 
			
		||||
  StructType *prev = NULL; \
 | 
			
		||||
  while (current) { \
 | 
			
		||||
    if (strcmp(current->keyword, keyword) == 0) { \
 | 
			
		||||
      if (prev) { \
 | 
			
		||||
        prev->next = current->next; \
 | 
			
		||||
      } else { \
 | 
			
		||||
        map[hashval] = current->next; \
 | 
			
		||||
      } \
 | 
			
		||||
      free(current->keyword); \
 | 
			
		||||
      free(current); \
 | 
			
		||||
      return 1; \
 | 
			
		||||
    } \
 | 
			
		||||
    prev = current; \
 | 
			
		||||
    current = current->next; \
 | 
			
		||||
  } \
 | 
			
		||||
  return 0; \
 | 
			
		||||
} \
 | 
			
		||||
\
 | 
			
		||||
StructType **new_##StructType() { \
 | 
			
		||||
  StructType **map = (StructType **)calloc(HASHSIZE, sizeof(StructType *)); \
 | 
			
		||||
  if (!map) return NULL; \
 | 
			
		||||
  return map; \
 | 
			
		||||
} \
 | 
			
		||||
\
 | 
			
		||||
void free_##StructType(StructType **map) { \
 | 
			
		||||
  if (!map) return; \
 | 
			
		||||
  int i; \
 | 
			
		||||
  for (i = 0; i < HASHSIZE; i++) { \
 | 
			
		||||
    StructType *current = map[i]; \
 | 
			
		||||
    while (current) { \
 | 
			
		||||
      StructType *next = current->next; \
 | 
			
		||||
      free(current->keyword); \
 | 
			
		||||
      free(current); \
 | 
			
		||||
      current = next; \
 | 
			
		||||
    } \
 | 
			
		||||
  } \
 | 
			
		||||
  free(map); \
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										27
									
								
								src/main.c
								
								
								
								
							
							
						
						
									
										27
									
								
								src/main.c
								
								
								
								
							| 
						 | 
				
			
			@ -1,14 +1,10 @@
 | 
			
		|||
#include "compiler.h"
 | 
			
		||||
#include "test.h"
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
#include "parser.h"
 | 
			
		||||
#include "vm.h"
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/uio.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -30,27 +26,6 @@ void mainloop() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv) {
 | 
			
		||||
  if (argc != 2) {
 | 
			
		||||
    printf("usage: zre input.zre");
 | 
			
		||||
    return EXIT_FAILURE;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  char *buffer;
 | 
			
		||||
  int length = 0;
 | 
			
		||||
  int sp = open(argv[1], O_RDONLY);
 | 
			
		||||
 | 
			
		||||
  if (sp) {
 | 
			
		||||
    length = lseek(sp, (size_t)0, SEEK_END);
 | 
			
		||||
    lseek(sp, (size_t)0, SEEK_SET);
 | 
			
		||||
    buffer = malloc(length);
 | 
			
		||||
    if (buffer) {
 | 
			
		||||
      read(sp, buffer, length * sizeof(char));
 | 
			
		||||
    }
 | 
			
		||||
    close(sp);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  initTokenMap();
 | 
			
		||||
  compile(vm.memory, buffer);
 | 
			
		||||
  vm.frames_size = FRAMES_SIZE;
 | 
			
		||||
  vm.stack_size = STACK_SIZE;
 | 
			
		||||
  vm.memory_size = MEMORY_SIZE;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,9 +15,9 @@ typedef struct {
 | 
			
		|||
  uint32_t end;
 | 
			
		||||
} Slice;
 | 
			
		||||
 | 
			
		||||
#define MAX_REGS 256
 | 
			
		||||
#define MAX_REGS 32
 | 
			
		||||
typedef struct {
 | 
			
		||||
  Value registers[MAX_REGS]; /* R0-R255 */
 | 
			
		||||
  Value registers[MAX_REGS]; /* R0-R31 */
 | 
			
		||||
  uint32_t rp;               /* register pointer (last unused) */
 | 
			
		||||
  Slice allocated;           /* start and end of global allocated block */
 | 
			
		||||
} Frame;
 | 
			
		||||
| 
						 | 
				
			
			@ -55,9 +55,9 @@ typedef enum {
 | 
			
		|||
  OP_POPF,    /* popf : pop float from stack onto the register */
 | 
			
		||||
  OP_POPS,    /* pops : pop str ref from stack and move/copy to register */
 | 
			
		||||
  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_SUB_INT, /* subi : dest = src1 - src2  */
 | 
			
		||||
  OP_MUL_INT, /* muli : dest = src1 * src2  */
 | 
			
		||||
  OP_DIV_INT, /* divi : 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 */
 | 
			
		||||
| 
						 | 
				
			
			@ -92,8 +92,8 @@ typedef enum {
 | 
			
		|||
  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_READ_STRING,    /* gets : dest = gets as str */
 | 
			
		||||
  OP_PRINT_STRING,   /* puts : write src1 to stdout */
 | 
			
		||||
  OP_CMP_STRING,     /* cmps : dest = (str == src2) as bool */
 | 
			
		||||
} Opcode;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										312
									
								
								src/parser.c
								
								
								
								
							
							
						
						
									
										312
									
								
								src/parser.c
								
								
								
								
							| 
						 | 
				
			
			@ -1,312 +0,0 @@
 | 
			
		|||
#include "parser.h"
 | 
			
		||||
#include "hashmap.h"
 | 
			
		||||
 | 
			
		||||
DEFINE_HASHMAP(TokenMap, 150);
 | 
			
		||||
 | 
			
		||||
TokenMap **tokenMap;
 | 
			
		||||
 | 
			
		||||
void initTokenMap() {
 | 
			
		||||
  tokenMap = new_TokenMap();
 | 
			
		||||
 | 
			
		||||
  put_TokenMap(tokenMap, "fn", TOKEN_FN);
 | 
			
		||||
  put_TokenMap(tokenMap, "to", TOKEN_TO);
 | 
			
		||||
  put_TokenMap(tokenMap, "in", TOKEN_IN);
 | 
			
		||||
  put_TokenMap(tokenMap, "is", TOKEN_IS);
 | 
			
		||||
  put_TokenMap(tokenMap, "as", TOKEN_AS);
 | 
			
		||||
  put_TokenMap(tokenMap, "use", TOKEN_USE);
 | 
			
		||||
  put_TokenMap(tokenMap, "if", TOKEN_IF);
 | 
			
		||||
  put_TokenMap(tokenMap, "else", TOKEN_ELSE);
 | 
			
		||||
  put_TokenMap(tokenMap, "default", TOKEN_DEFAULT);
 | 
			
		||||
  put_TokenMap(tokenMap, "for", TOKEN_FOR);
 | 
			
		||||
  put_TokenMap(tokenMap, "try", TOKEN_TRY);
 | 
			
		||||
  put_TokenMap(tokenMap, "catch", TOKEN_CATCH);
 | 
			
		||||
  put_TokenMap(tokenMap, "while", TOKEN_WHILE);
 | 
			
		||||
  put_TokenMap(tokenMap, "do", TOKEN_DO);
 | 
			
		||||
  put_TokenMap(tokenMap, "exit", TOKEN_EXIT);
 | 
			
		||||
  put_TokenMap(tokenMap, "switch", TOKEN_SWITCH);
 | 
			
		||||
  put_TokenMap(tokenMap, "return", TOKEN_RETURN);
 | 
			
		||||
  put_TokenMap(tokenMap, "const", TOKEN_CONST);
 | 
			
		||||
  put_TokenMap(tokenMap, "type", TOKEN_TYPE);
 | 
			
		||||
  put_TokenMap(tokenMap, "this", TOKEN_THIS);
 | 
			
		||||
  put_TokenMap(tokenMap, "yield", TOKEN_YIELD);
 | 
			
		||||
  put_TokenMap(tokenMap, "case", TOKEN_CASE);
 | 
			
		||||
  put_TokenMap(tokenMap, "assert", TOKEN_ASSERT);
 | 
			
		||||
  put_TokenMap(tokenMap, "break", TOKEN_BREAK);
 | 
			
		||||
  put_TokenMap(tokenMap, "let", TOKEN_LET);
 | 
			
		||||
  put_TokenMap(tokenMap, "print", TOKEN_PRINT);
 | 
			
		||||
  put_TokenMap(tokenMap, "nil", TOKEN_NULL);
 | 
			
		||||
  put_TokenMap(tokenMap, "and", TOKEN_AND);
 | 
			
		||||
  put_TokenMap(tokenMap, "or", TOKEN_OR);
 | 
			
		||||
  put_TokenMap(tokenMap, "xor", TOKEN_XOR);
 | 
			
		||||
  put_TokenMap(tokenMap, "mod", TOKEN_MOD);
 | 
			
		||||
  put_TokenMap(tokenMap, "eq", TOKEN_EQ);
 | 
			
		||||
  put_TokenMap(tokenMap, "ge", TOKEN_GE);
 | 
			
		||||
  put_TokenMap(tokenMap, "lt", TOKEN_LT);
 | 
			
		||||
  put_TokenMap(tokenMap, "le", TOKEN_LE);
 | 
			
		||||
  put_TokenMap(tokenMap, "ne", TOKEN_NE);
 | 
			
		||||
  put_TokenMap(tokenMap, "gt", TOKEN_GT);
 | 
			
		||||
  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;
 | 
			
		||||
struct Tokenizer {
 | 
			
		||||
  char *start;
 | 
			
		||||
  char *current;
 | 
			
		||||
  int32_t line;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Tokenizer tokenizer;
 | 
			
		||||
 | 
			
		||||
void initTokenizer(char *src) {
 | 
			
		||||
  tokenizer.start = src;
 | 
			
		||||
  tokenizer.current = src;
 | 
			
		||||
  tokenizer.line = 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool isAlpha(char c) {
 | 
			
		||||
  return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' ||
 | 
			
		||||
         c == '\'' || c == '?';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool isDigit(char c) { return (c >= '0' && c <= '9') || c == '-'; }
 | 
			
		||||
 | 
			
		||||
static bool isAtEnd() { return *tokenizer.current == '\0'; }
 | 
			
		||||
 | 
			
		||||
static Token makeToken(TokenType type) {
 | 
			
		||||
  Token token;
 | 
			
		||||
  token.type = type;
 | 
			
		||||
  token.start = tokenizer.start;
 | 
			
		||||
  token.length = (int32_t)(tokenizer.current - tokenizer.start);
 | 
			
		||||
  token.line = tokenizer.line;
 | 
			
		||||
  return token;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Token errorToken(char *msg) {
 | 
			
		||||
  Token token;
 | 
			
		||||
  token.type = TOKEN_ERROR;
 | 
			
		||||
  token.start = msg;
 | 
			
		||||
  token.length = (int32_t)strlen(msg);
 | 
			
		||||
  token.line = tokenizer.line;
 | 
			
		||||
  return token;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char advance() {
 | 
			
		||||
  tokenizer.current++;
 | 
			
		||||
  return tokenizer.current[-1];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char peek() { return *tokenizer.current; }
 | 
			
		||||
 | 
			
		||||
static char peekNext() {
 | 
			
		||||
  if (isAtEnd())
 | 
			
		||||
    return '\0';
 | 
			
		||||
  return tokenizer.current[1];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void skipWhitespace() {
 | 
			
		||||
  for (;;) {
 | 
			
		||||
    char c = peek();
 | 
			
		||||
    switch (c) {
 | 
			
		||||
    case ' ':
 | 
			
		||||
    case '\r':
 | 
			
		||||
    case '\t':
 | 
			
		||||
      advance();
 | 
			
		||||
      break;
 | 
			
		||||
    case '\n':
 | 
			
		||||
      tokenizer.line++;
 | 
			
		||||
      advance();
 | 
			
		||||
      break;
 | 
			
		||||
    case '!':
 | 
			
		||||
      while (peek() != '\n' && !isAtEnd())
 | 
			
		||||
        advance();
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char *currentTokenToS() {
 | 
			
		||||
  int32_t size = tokenizer.current - tokenizer.start;
 | 
			
		||||
  char *str = (char *)malloc(sizeof(size));
 | 
			
		||||
  strncpy(str, tokenizer.start, size);
 | 
			
		||||
  str[size] = '\0';
 | 
			
		||||
  return str;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TokenType getToken(char *s) {
 | 
			
		||||
  TokenMap *np;
 | 
			
		||||
  for (np = tokenMap[hash_TokenMap(s)]; np != NULL; np = np->next)
 | 
			
		||||
    if (strcmp(s, np->keyword) == 0)
 | 
			
		||||
      return np->token;
 | 
			
		||||
  return TOKEN_IDENTIFIER;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static TokenType identifierType() {
 | 
			
		||||
  char *check = currentTokenToS();
 | 
			
		||||
  TokenType t = getToken(check);
 | 
			
		||||
  free(check);
 | 
			
		||||
  return t;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Token identifier() {
 | 
			
		||||
  while (isAlpha(peek()) || isDigit(peek()))
 | 
			
		||||
    advance();
 | 
			
		||||
  return makeToken(identifierType());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Token number() {
 | 
			
		||||
  bool is_float = false;
 | 
			
		||||
  while (isDigit(peek()))
 | 
			
		||||
    advance();
 | 
			
		||||
 | 
			
		||||
  /* Look for a fractional part. */
 | 
			
		||||
  if (peek() == '.' && isDigit(peekNext())) {
 | 
			
		||||
    is_float = true;
 | 
			
		||||
    /* Consume the ".". */
 | 
			
		||||
    advance();
 | 
			
		||||
 | 
			
		||||
    while (isDigit(peek()))
 | 
			
		||||
      advance();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return makeToken((is_float)
 | 
			
		||||
                       ? TOKEN_FLOAT
 | 
			
		||||
                       : TOKEN_INT); /* or measure if ends in postscript */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Token string() {
 | 
			
		||||
  while (peek() != '"' && !isAtEnd()) {
 | 
			
		||||
    if (peek() == '\n')
 | 
			
		||||
      tokenizer.line++;
 | 
			
		||||
    advance();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (isAtEnd())
 | 
			
		||||
    return errorToken("Unterminated string.");
 | 
			
		||||
 | 
			
		||||
  /* The closing quote. */
 | 
			
		||||
  advance();
 | 
			
		||||
  return makeToken(TOKEN_STRING);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Token nextToken() {
 | 
			
		||||
  skipWhitespace();
 | 
			
		||||
  tokenizer.start = tokenizer.current;
 | 
			
		||||
  if (isAtEnd())
 | 
			
		||||
    return makeToken(TOKEN_EOF);
 | 
			
		||||
 | 
			
		||||
  char c = advance();
 | 
			
		||||
  if (isAlpha(c))
 | 
			
		||||
    return identifier();
 | 
			
		||||
  if (isDigit(c))
 | 
			
		||||
    return number();
 | 
			
		||||
  switch (c) {
 | 
			
		||||
  case '(':
 | 
			
		||||
    return makeToken(TOKEN_LEFT_PAREN);
 | 
			
		||||
  case ')':
 | 
			
		||||
    return makeToken(TOKEN_RIGHT_PAREN);
 | 
			
		||||
  case '{':
 | 
			
		||||
    return makeToken(TOKEN_LEFT_BRACE);
 | 
			
		||||
  case '}':
 | 
			
		||||
    return makeToken(TOKEN_RIGHT_BRACE);
 | 
			
		||||
  case '+':
 | 
			
		||||
    return makeToken(TOKEN_ADD);
 | 
			
		||||
  case '/':
 | 
			
		||||
    return makeToken(TOKEN_DIV);
 | 
			
		||||
  case '-':
 | 
			
		||||
    return makeToken(TOKEN_SUB);
 | 
			
		||||
  case '*':
 | 
			
		||||
    return makeToken(TOKEN_MUL);
 | 
			
		||||
  case ';':
 | 
			
		||||
    return makeToken(TOKEN_SEMICOLON);
 | 
			
		||||
  case '=':
 | 
			
		||||
    return makeToken(TOKEN_EQUALS);
 | 
			
		||||
  case '.':
 | 
			
		||||
    return makeToken(TOKEN_DOT);
 | 
			
		||||
  case '"':
 | 
			
		||||
    return string();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return errorToken("Unexpected character.");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_RIGHT_BRACE)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_SEMICOLON)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_IDENTIFIER)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_STRING)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_FLOAT)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_U8)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_I8)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_U16)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_I16)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_U64)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_I64)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_INT)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_UINT)
 | 
			
		||||
    /* PRINT_TOKEN_CASE(TOKEN_ARRAY) */
 | 
			
		||||
    /* PRINT_TOKEN_CASE(TOKEN_MAP) */
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_FALSE)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_TRUE)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_NULL)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_EOF)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_ERROR)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_ADD)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_SUB)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_MUL)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_DIV)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_MOD)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_GT)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_LT)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_EQ)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_GE)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_LE)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_NE)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_AND)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_OR)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_XOR)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_SHIFTRIGHT)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_SHIFTLEFT)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_FN)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_TO)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_IN)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_IS)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_AS)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_USE)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_IF)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_ELSE)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_DEFAULT)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_FOR)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_TRY)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_CATCH)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_WHILE)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_DO)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_EXIT)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_SWITCH)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_RETURN)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_CONST)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_TYPE)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_THIS)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_YIELD)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_CASE)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_ASSERT)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_BREAK)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_LET)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_PRINT)
 | 
			
		||||
    PRINT_TOKEN_CASE(TOKEN_TO_S)
 | 
			
		||||
  }
 | 
			
		||||
  free(str);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										118
									
								
								src/parser.h
								
								
								
								
							
							
						
						
									
										118
									
								
								src/parser.h
								
								
								
								
							| 
						 | 
				
			
			@ -1,118 +0,0 @@
 | 
			
		|||
#ifndef ZRE_PARSER_H
 | 
			
		||||
#define ZRE_PARSER_H
 | 
			
		||||
 | 
			
		||||
#include "common.h"
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
typedef enum TokenType
 | 
			
		||||
{
 | 
			
		||||
  /* Single char tokens */
 | 
			
		||||
  TOKEN_LEFT_PAREN,
 | 
			
		||||
  TOKEN_RIGHT_PAREN,
 | 
			
		||||
  TOKEN_LEFT_BRACE,
 | 
			
		||||
  TOKEN_RIGHT_BRACE,
 | 
			
		||||
  TOKEN_SEMICOLON,
 | 
			
		||||
  TOKEN_EQUALS,
 | 
			
		||||
  TOKEN_DOT,
 | 
			
		||||
  /* Literals */
 | 
			
		||||
  TOKEN_IDENTIFIER,
 | 
			
		||||
  TOKEN_STRING,
 | 
			
		||||
  TOKEN_FLOAT,
 | 
			
		||||
  TOKEN_U8,
 | 
			
		||||
  TOKEN_I8,
 | 
			
		||||
  TOKEN_U16,
 | 
			
		||||
  TOKEN_I16,
 | 
			
		||||
  TOKEN_U64,
 | 
			
		||||
  TOKEN_I64,
 | 
			
		||||
  TOKEN_INT,
 | 
			
		||||
  TOKEN_UINT,
 | 
			
		||||
  /* TOKEN_ARRAY, */
 | 
			
		||||
  /* TOKEN_MAP, */
 | 
			
		||||
  TOKEN_FALSE,
 | 
			
		||||
  TOKEN_TRUE,
 | 
			
		||||
  TOKEN_NULL,
 | 
			
		||||
  TOKEN_EOF,
 | 
			
		||||
  TOKEN_ERROR,
 | 
			
		||||
  /* Operators */
 | 
			
		||||
  TOKEN_ADD,
 | 
			
		||||
  TOKEN_SUB,
 | 
			
		||||
  TOKEN_MUL,
 | 
			
		||||
  TOKEN_DIV,
 | 
			
		||||
  TOKEN_MOD,
 | 
			
		||||
  TOKEN_GT,
 | 
			
		||||
  TOKEN_LT,
 | 
			
		||||
  TOKEN_EQ,
 | 
			
		||||
  TOKEN_GE,
 | 
			
		||||
  TOKEN_LE,
 | 
			
		||||
  TOKEN_NE,
 | 
			
		||||
  TOKEN_AND,
 | 
			
		||||
  TOKEN_OR,
 | 
			
		||||
  TOKEN_XOR,
 | 
			
		||||
  TOKEN_SHIFTRIGHT,
 | 
			
		||||
  TOKEN_SHIFTLEFT,
 | 
			
		||||
  /* Keywords */
 | 
			
		||||
  TOKEN_FN,
 | 
			
		||||
  TOKEN_TO,
 | 
			
		||||
  TOKEN_IN,
 | 
			
		||||
  TOKEN_IS,
 | 
			
		||||
  TOKEN_AS,
 | 
			
		||||
  TOKEN_USE,
 | 
			
		||||
  TOKEN_IF,
 | 
			
		||||
  TOKEN_ELSE,
 | 
			
		||||
  TOKEN_DEFAULT,
 | 
			
		||||
  TOKEN_FOR,
 | 
			
		||||
  TOKEN_TRY,
 | 
			
		||||
  TOKEN_CATCH,
 | 
			
		||||
  TOKEN_WHILE,
 | 
			
		||||
  TOKEN_DO,
 | 
			
		||||
  TOKEN_EXIT,
 | 
			
		||||
  TOKEN_SWITCH,
 | 
			
		||||
  TOKEN_RETURN,
 | 
			
		||||
  TOKEN_CONST,
 | 
			
		||||
  TOKEN_TYPE,
 | 
			
		||||
  TOKEN_THIS,
 | 
			
		||||
  TOKEN_YIELD,
 | 
			
		||||
  TOKEN_CASE,
 | 
			
		||||
  TOKEN_ASSERT,
 | 
			
		||||
  TOKEN_BREAK,
 | 
			
		||||
  TOKEN_LET,
 | 
			
		||||
  TOKEN_PRINT,
 | 
			
		||||
  TOKEN_TO_S,
 | 
			
		||||
} TokenType;
 | 
			
		||||
 | 
			
		||||
#define PRINT_TOKEN_CASE(token_suffix) \
 | 
			
		||||
  case token_suffix: \
 | 
			
		||||
    printf("" #token_suffix " %s line_no=%d\n", str, t.line); \
 | 
			
		||||
    break;
 | 
			
		||||
 | 
			
		||||
typedef struct Token Token;
 | 
			
		||||
struct Token
 | 
			
		||||
{
 | 
			
		||||
  TokenType type;
 | 
			
		||||
  char *start;
 | 
			
		||||
  int32_t length;
 | 
			
		||||
  int32_t line;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct SourceCode SourceCode;
 | 
			
		||||
struct SourceCode
 | 
			
		||||
{
 | 
			
		||||
  size_t size;
 | 
			
		||||
  char *buf;
 | 
			
		||||
  int count;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct TokenMap TokenMap;
 | 
			
		||||
struct TokenMap
 | 
			
		||||
{
 | 
			
		||||
  struct TokenMap* next;
 | 
			
		||||
  char* keyword;
 | 
			
		||||
  TokenType token;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void initTokenMap(); 
 | 
			
		||||
void initTokenizer (char *src);
 | 
			
		||||
void printToken (Token t);
 | 
			
		||||
Token nextToken();
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +1,4 @@
 | 
			
		|||
#include "compiler.h"
 | 
			
		||||
#include "parser.h"
 | 
			
		||||
#include "test.h"
 | 
			
		||||
 | 
			
		||||
uint32_t test_add_compile(Value *memory) {
 | 
			
		||||
  uint32_t i = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -76,44 +75,32 @@ uint32_t test_add_function_compile(Value *memory) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
uint32_t test_recursive_function_compile(Value *memory) {
 | 
			
		||||
  uint32_t i = 0;
 | 
			
		||||
  uint32_t i = 3;
 | 
			
		||||
  memory[i++].u = OP(OP_POPU, 0, 0, 0); /* return ptr */
 | 
			
		||||
  memory[i++].u = OP(OP_POPI, 1, 0, 0); /* n int */
 | 
			
		||||
  /* if (n < 2) */
 | 
			
		||||
  /* return n; */
 | 
			
		||||
  memory[i++].u = OP(OP_POPI, 2, 0, 0); /* fib(n - 2) */
 | 
			
		||||
  memory[i++].u = OP(OP_POPI, 3, 0, 0); /* fib(n - 1) */
 | 
			
		||||
  memory[i++].u = OP(OP_ADD_INT, 4, 3, 2); /* add */
 | 
			
		||||
  memory[i++].u = OP(OP_PUSHI, 4, 0, 0); /* return */
 | 
			
		||||
  memory[i++].u = OP(OP_RETURN, 0, 0, 0);
 | 
			
		||||
  uint32_t main = i;
 | 
			
		||||
  memory[0].u = OP(OP_LOADF, 0, 0, 0);
 | 
			
		||||
  memory[1].u = main;
 | 
			
		||||
  memory[2].u = OP(OP_JMP, 0, 0, 0); /* jump to 'main' */
 | 
			
		||||
  memory[i++].u = OP(OP_LOADI, 0, 0, 0); /* 35 */
 | 
			
		||||
  memory[i++].i = 35;
 | 
			
		||||
  memory[i++].u = OP(OP_PUSHI, 0, 0, 0);
 | 
			
		||||
  uint32_t add_fn_return = i + 6; /* after the call */
 | 
			
		||||
  memory[i++].u = OP(OP_LOADI, 0, 0, 0); /* return */
 | 
			
		||||
  memory[i++].u = add_fn_return;
 | 
			
		||||
  memory[i++].u = OP(OP_PUSHU, 0, 0, 0); 
 | 
			
		||||
  memory[i++].u = OP(OP_LOADU, 0, 0, 0); /* add fn ptr */
 | 
			
		||||
  memory[i++].u = 3;
 | 
			
		||||
  memory[i++].u = OP(OP_CALL, 0, 0, 0); /* ); */
 | 
			
		||||
  memory[i++].u = OP(OP_POPI, 0, 0, 0); /* get return value */
 | 
			
		||||
  memory[i++].u = OP(OP_INT_TO_STRING, 1, 0, 0);
 | 
			
		||||
  memory[i++].u = OP(OP_HALT, 0, 0, 0);
 | 
			
		||||
  return i;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
 */
 | 
			
		||||
uint32_t compile(Value *memory, char *buffer) {
 | 
			
		||||
  uint32_t i = 0;
 | 
			
		||||
  initTokenizer(buffer);
 | 
			
		||||
  Token t = nextToken();
 | 
			
		||||
  while (t.type != TOKEN_EOF) {
 | 
			
		||||
    printToken(t);
 | 
			
		||||
    declaration(t);
 | 
			
		||||
    t = nextToken();
 | 
			
		||||
  }
 | 
			
		||||
  return i;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
#ifndef ZRE_COMPILER_H
 | 
			
		||||
#define ZRE_COMPILER_H
 | 
			
		||||
#ifndef ZRE_TEST_H
 | 
			
		||||
#define ZRE_TEST_H
 | 
			
		||||
 | 
			
		||||
#include "opcodes.h"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -7,6 +7,5 @@ uint32_t test_add_compile (Value *memory);
 | 
			
		|||
uint32_t test_loop_compile (Value *memory);
 | 
			
		||||
uint32_t test_add_function_compile(Value *memory);
 | 
			
		||||
uint32_t test_recursive_function_compile(Value *memory);
 | 
			
		||||
uint32_t compile (Value* memory, char *buffer);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										3
									
								
								src/vm.c
								
								
								
								
							
							
						
						
									
										3
									
								
								src/vm.c
								
								
								
								
							| 
						 | 
				
			
			@ -1,5 +1,6 @@
 | 
			
		|||
#include "vm.h"
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#define COMPARE_AND_JUMP(type, accessor, op)                                   \
 | 
			
		||||
  do {                                                                         \
 | 
			
		||||
| 
						 | 
				
			
			@ -258,7 +259,7 @@ bool step_vm(VM *vm) {
 | 
			
		|||
    }
 | 
			
		||||
    vm->memory[str_dest].u = length;
 | 
			
		||||
    vm->frames[vm->fp].allocated.end +=
 | 
			
		||||
        length + 1; /* increment to end of allocated */
 | 
			
		||||
        ((length / 4) + (length % 4) + 1); /* increment to end of allocated */
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  case OP_PRINT_STRING: {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
fn add(int a, int b) int {
 | 
			
		||||
int add(int a, int b) {
 | 
			
		||||
  return a + b;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
let sum = add(1, 1);
 | 
			
		||||
int sum = add(1, 1);
 | 
			
		||||
print(sum.toS());
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,18 @@
 | 
			
		|||
main:
 | 
			
		||||
	loadi $0 1		;load 1 into r0
 | 
			
		||||
	pushi $0 		;push onto stack
 | 
			
		||||
	loadi $0 1		;1
 | 
			
		||||
	pushi $0
 | 
			
		||||
	call &add		; call memory location for tag "add"
 | 
			
		||||
	popi $0			;get value from function call "add"
 | 
			
		||||
	itos $1 $0		;convert int to string
 | 
			
		||||
	puts $1			;print string to stdout
 | 
			
		||||
	halt
 | 
			
		||||
 | 
			
		||||
add:
 | 
			
		||||
	popu $0 		; pop unsigned int
 | 
			
		||||
	popi $1			; int a
 | 
			
		||||
	popi $2			; int b
 | 
			
		||||
	addi $3 $2 $1		; a + b
 | 
			
		||||
	pushi $3		; push a + b onto stack for return
 | 
			
		||||
	return $0 		; actually do the return
 | 
			
		||||
| 
						 | 
				
			
			@ -1,2 +1,2 @@
 | 
			
		|||
let sum = 1 + 2;
 | 
			
		||||
int sum = 1 + 2;
 | 
			
		||||
print(sum.toS());
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,8 @@
 | 
			
		|||
fn fib(int n) {
 | 
			
		||||
  if (n < 2) return n;
 | 
			
		||||
int fib(int n) {
 | 
			
		||||
  if (n < 2) {
 | 
			
		||||
    return n;
 | 
			
		||||
  }
 | 
			
		||||
  return fib(n - 2) + fib(n - 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
print fib(35);
 | 
			
		||||
print(fib(35).toS());
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,9 @@
 | 
			
		|||
let a = 5.0;
 | 
			
		||||
do (i = 5, 0, -1) {
 | 
			
		||||
real a = 5.0;
 | 
			
		||||
do (int i = 5, 0, -1) {
 | 
			
		||||
  a += 5.0;
 | 
			
		||||
}
 | 
			
		||||
let b = a as nat;
 | 
			
		||||
let user_string = gets();
 | 
			
		||||
nat b = a as nat;
 | 
			
		||||
str user_string = readln();
 | 
			
		||||
print(a.toS());
 | 
			
		||||
print(b.toS());
 | 
			
		||||
print(user_string);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue