Compare commits
2 Commits
9c94e4a6ef
...
49f7189470
Author | SHA1 | Date |
---|---|---|
|
49f7189470 | |
|
fefc9e803a |
|
@ -7,7 +7,7 @@
|
||||||
! Camera .
|
! Camera .
|
||||||
!!
|
!!
|
||||||
type Camera {
|
type Camera {
|
||||||
init(pos [3]real, look [3]real) {
|
init(real[3] pos, real[3] look) {
|
||||||
this.setting = "CAMERA_PERSPECTIVE";
|
this.setting = "CAMERA_PERSPECTIVE";
|
||||||
this.pov = 45.0;
|
this.pov = 45.0;
|
||||||
this.up = [0.0, 1.0, 0.0];
|
this.up = [0.0, 1.0, 0.0];
|
||||||
|
@ -20,7 +20,7 @@ type Camera {
|
||||||
! Player .
|
! Player .
|
||||||
!!
|
!!
|
||||||
type 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.server = Client("tcp://localhost:25565");
|
||||||
this.username = username;
|
this.username = username;
|
||||||
this.pos = pos;
|
this.pos = pos;
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
#define ZRE_DEBUG_H
|
#define ZRE_DEBUG_H
|
||||||
|
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
#include "parser.h"
|
|
||||||
#include "opcodes.h"
|
#include "opcodes.h"
|
||||||
|
|
||||||
int core_dump(VM *vm);
|
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 "debug.h"
|
||||||
#include "parser.h"
|
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -30,27 +26,6 @@ void mainloop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
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.frames_size = FRAMES_SIZE;
|
||||||
vm.stack_size = STACK_SIZE;
|
vm.stack_size = STACK_SIZE;
|
||||||
vm.memory_size = MEMORY_SIZE;
|
vm.memory_size = MEMORY_SIZE;
|
||||||
|
|
|
@ -15,9 +15,9 @@ typedef struct {
|
||||||
uint32_t end;
|
uint32_t end;
|
||||||
} Slice;
|
} Slice;
|
||||||
|
|
||||||
#define MAX_REGS 256
|
#define MAX_REGS 32
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Value registers[MAX_REGS]; /* R0-R255 */
|
Value registers[MAX_REGS]; /* R0-R31 */
|
||||||
uint32_t rp; /* register pointer (last unused) */
|
uint32_t rp; /* register pointer (last unused) */
|
||||||
Slice allocated; /* start and end of global allocated block */
|
Slice allocated; /* start and end of global allocated block */
|
||||||
} Frame;
|
} Frame;
|
||||||
|
@ -55,9 +55,9 @@ typedef enum {
|
||||||
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, /* subs : dest = src1 - src2 */
|
OP_SUB_INT, /* subi : dest = src1 - src2 */
|
||||||
OP_MUL_INT, /* mulm : dest = src1 * src2 */
|
OP_MUL_INT, /* muli : dest = src1 * src2 */
|
||||||
OP_DIV_INT, /* divd : 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_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_JGT_INT, /* jgti : jump to address dest if src1 as int > src2 as int*/
|
||||||
OP_JLT_INT, /* jlti : jump to address dest if src1 as int < src2 as int */
|
OP_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_INT_TO_STRING, /* itos : dest = src1 as str */
|
||||||
OP_UINT_TO_STRING, /* utos : dest = src1 as str */
|
OP_UINT_TO_STRING, /* utos : dest = src1 as str */
|
||||||
OP_REAL_TO_STRING, /* rtos : dest = src1 as str */
|
OP_REAL_TO_STRING, /* rtos : dest = src1 as str */
|
||||||
OP_READ_STRING, /* read : dest = read as str */
|
OP_READ_STRING, /* gets : dest = gets as str */
|
||||||
OP_PRINT_STRING, /* wrte : 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 */
|
||||||
} Opcode;
|
} 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 "test.h"
|
||||||
#include "parser.h"
|
|
||||||
|
|
||||||
uint32_t test_add_compile(Value *memory) {
|
uint32_t test_add_compile(Value *memory) {
|
||||||
uint32_t i = 0;
|
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 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);
|
memory[i++].u = OP(OP_HALT, 0, 0, 0);
|
||||||
return i;
|
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
|
#ifndef ZRE_TEST_H
|
||||||
#define ZRE_COMPILER_H
|
#define ZRE_TEST_H
|
||||||
|
|
||||||
#include "opcodes.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_loop_compile (Value *memory);
|
||||||
uint32_t test_add_function_compile(Value *memory);
|
uint32_t test_add_function_compile(Value *memory);
|
||||||
uint32_t test_recursive_function_compile(Value *memory);
|
uint32_t test_recursive_function_compile(Value *memory);
|
||||||
uint32_t compile (Value* memory, char *buffer);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
3
src/vm.c
3
src/vm.c
|
@ -1,5 +1,6 @@
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#define COMPARE_AND_JUMP(type, accessor, op) \
|
#define COMPARE_AND_JUMP(type, accessor, op) \
|
||||||
do { \
|
do { \
|
||||||
|
@ -258,7 +259,7 @@ bool step_vm(VM *vm) {
|
||||||
}
|
}
|
||||||
vm->memory[str_dest].u = length;
|
vm->memory[str_dest].u = length;
|
||||||
vm->frames[vm->fp].allocated.end +=
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
case OP_PRINT_STRING: {
|
case OP_PRINT_STRING: {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
fn add(int a, int b) int {
|
int add(int a, int b) {
|
||||||
return a + b;
|
return a + b;
|
||||||
}
|
}
|
||||||
|
|
||||||
let sum = add(1, 1);
|
int sum = add(1, 1);
|
||||||
print(sum.toS());
|
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());
|
print(sum.toS());
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
fn fib(int n) {
|
int fib(int n) {
|
||||||
if (n < 2) return n;
|
if (n < 2) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
return fib(n - 2) + fib(n - 1);
|
return fib(n - 2) + fib(n - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
print fib(35);
|
print(fib(35).toS());
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
let a = 5.0;
|
real a = 5.0;
|
||||||
do (i = 5, 0, -1) {
|
do (int i = 5, 0, -1) {
|
||||||
a += 5.0;
|
a += 5.0;
|
||||||
}
|
}
|
||||||
let b = a as nat;
|
nat b = a as nat;
|
||||||
let user_string = gets();
|
str user_string = readln();
|
||||||
print(a.toS());
|
print(a.toS());
|
||||||
print(b.toS());
|
print(b.toS());
|
||||||
print(user_string);
|
print(user_string);
|
||||||
|
|
Loading…
Reference in New Issue