get rid of all static functions and all globals, use pointers instead. fix alignment bug in aalloc
This commit is contained in:
parent
63a5b737fc
commit
aee7191f59
|
|
@ -72,7 +72,7 @@ main(int argc, char **argv)
|
||||||
List *memory = List_init(&a);
|
List *memory = List_init(&a);
|
||||||
|
|
||||||
char *source = readFile(argv[2]);
|
char *source = readFile(argv[2]);
|
||||||
compile(&a, code, memory, e, source);
|
compile(&a, code, memory, &e, source);
|
||||||
|
|
||||||
Node *curr = code->head;
|
Node *curr = code->head;
|
||||||
while (curr) {
|
while (curr) {
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,9 @@ static void list2buffer(List *list, char *buffer, size_t *offset) {
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE
|
EMSCRIPTEN_KEEPALIVE
|
||||||
char *undar_compile(int emitter_type, char *source) {
|
char *undar_compile(int emitter_type, char *source) {
|
||||||
|
u8 tape[MEM_SIZE];
|
||||||
|
Arena a = {tape, 0, MEM_SIZE};
|
||||||
|
|
||||||
Emitter e;
|
Emitter e;
|
||||||
if (emitter_type == 0) {
|
if (emitter_type == 0) {
|
||||||
e = rer_emitter();
|
e = rer_emitter();
|
||||||
|
|
@ -37,13 +40,10 @@ char *undar_compile(int emitter_type, char *source) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 tape[MEM_SIZE];
|
|
||||||
Arena a = {tape, 0, MEM_SIZE};
|
|
||||||
|
|
||||||
List *code = List_init(&a);
|
List *code = List_init(&a);
|
||||||
List *memory = List_init(&a);
|
List *memory = List_init(&a);
|
||||||
|
|
||||||
compile(&a, code, memory, e, source);
|
compile(&a, code, memory, &e, source);
|
||||||
|
|
||||||
size_t code_size = List_size(code);
|
size_t code_size = List_size(code);
|
||||||
size_t mem_size = List_size(memory);
|
size_t mem_size = List_size(memory);
|
||||||
|
|
|
||||||
340
compiler.c
340
compiler.c
|
|
@ -5,8 +5,8 @@
|
||||||
#include "libc.h"
|
#include "libc.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
|
||||||
Emitter emitter = {0};
|
Parser *parser;
|
||||||
Parser parser = {0};
|
Emitter *emitter;
|
||||||
Arena *arena;
|
Arena *arena;
|
||||||
List *code;
|
List *code;
|
||||||
List *memory;
|
List *memory;
|
||||||
|
|
@ -22,8 +22,8 @@ scopes_init(void)
|
||||||
child.symbols = List_init(arena);
|
child.symbols = List_init(arena);
|
||||||
child.locals_offset = 0;
|
child.locals_offset = 0;
|
||||||
|
|
||||||
current = (Scope *)List_push(arena, parser.scopes, &child, sizeof(Scope));
|
current = (Scope *)List_push(arena, parser->scopes, &child, sizeof(Scope));
|
||||||
parser.current_scope = current;
|
parser->current_scope = current;
|
||||||
}
|
}
|
||||||
|
|
||||||
Scope *
|
Scope *
|
||||||
|
|
@ -32,32 +32,32 @@ scope_new(void)
|
||||||
Scope *current;
|
Scope *current;
|
||||||
Scope child = {0};
|
Scope child = {0};
|
||||||
child.symbols = List_init(arena);
|
child.symbols = List_init(arena);
|
||||||
child.parent = parser.current_scope;
|
child.parent = parser->current_scope;
|
||||||
child.locals_offset = 0;
|
child.locals_offset = 0;
|
||||||
|
|
||||||
current = (Scope *)List_push(arena, parser.scopes, &child, sizeof(Scope));
|
current = (Scope *)List_push(arena, parser->scopes, &child, sizeof(Scope));
|
||||||
parser.current_scope = current;
|
parser->current_scope = current;
|
||||||
parser.scope_idx++;
|
parser->scope_idx++;
|
||||||
parser.depth++;
|
parser->depth++;
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
scope_pop(void)
|
scope_pop(void)
|
||||||
{
|
{
|
||||||
if(parser.current_scope) {
|
if(parser->current_scope) {
|
||||||
parser.current_scope = parser.current_scope->parent;
|
parser->current_scope = parser->current_scope->parent;
|
||||||
parser.depth--;
|
parser->depth--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
scope_push(void)
|
scope_push(void)
|
||||||
{
|
{
|
||||||
Scope *scope = List_get(parser.scopes, parser.scope_idx);
|
Scope *scope = List_get(parser->scopes, parser->scope_idx);
|
||||||
parser.current_scope = scope;
|
parser->current_scope = scope;
|
||||||
parser.depth++;
|
parser->depth++;
|
||||||
parser.scope_idx++;
|
parser->scope_idx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol *
|
Symbol *
|
||||||
|
|
@ -80,12 +80,12 @@ Symbol *
|
||||||
scope_add_symbol(const char *name, u32 name_length, SymbolType type, u32 size)
|
scope_add_symbol(const char *name, u32 name_length, SymbolType type, u32 size)
|
||||||
{
|
{
|
||||||
Symbol new_sym = {0};
|
Symbol new_sym = {0};
|
||||||
Symbol *sym = scope_get_symbol(parser.current_scope, name, name_length);
|
Symbol *sym = scope_get_symbol(parser->current_scope, name, name_length);
|
||||||
if(sym != nil) {
|
if(sym != nil) {
|
||||||
if(parser.pass)
|
if(parser->pass)
|
||||||
return sym;
|
return sym;
|
||||||
else
|
else
|
||||||
emitter.error("duplicate found", 14, parser.previous.line);
|
emitter->error("duplicate found", 14, parser->previous.line);
|
||||||
}
|
}
|
||||||
|
|
||||||
scpy(new_sym.name, name, name_length);
|
scpy(new_sym.name, name, name_length);
|
||||||
|
|
@ -93,9 +93,9 @@ scope_add_symbol(const char *name, u32 name_length, SymbolType type, u32 size)
|
||||||
new_sym.type = type;
|
new_sym.type = type;
|
||||||
new_sym.secondary_type = SYMBOL_VOID;
|
new_sym.secondary_type = SYMBOL_VOID;
|
||||||
new_sym.size = size;
|
new_sym.size = size;
|
||||||
new_sym.ref = parser.current_scope->locals_offset;
|
new_sym.ref = parser->current_scope->locals_offset;
|
||||||
new_sym.scope = parser.scope_idx;
|
new_sym.scope = parser->scope_idx;
|
||||||
parser.current_scope->locals_offset += size;
|
parser->current_scope->locals_offset += size;
|
||||||
if(type == SYMBOL_PLEX || type == SYMBOL_METHOD || type == SYMBOL_TRAIT ||
|
if(type == SYMBOL_PLEX || type == SYMBOL_METHOD || type == SYMBOL_TRAIT ||
|
||||||
type == SYMBOL_FUNCTION) {
|
type == SYMBOL_FUNCTION) {
|
||||||
new_sym.args = List_init(arena);
|
new_sym.args = List_init(arena);
|
||||||
|
|
@ -104,21 +104,21 @@ scope_add_symbol(const char *name, u32 name_length, SymbolType type, u32 size)
|
||||||
if(type == SYMBOL_PLEX || type == SYMBOL_METHOD || type == SYMBOL_TRAIT)
|
if(type == SYMBOL_PLEX || type == SYMBOL_METHOD || type == SYMBOL_TRAIT)
|
||||||
new_sym.fields = List_init(arena);
|
new_sym.fields = List_init(arena);
|
||||||
|
|
||||||
return List_push(arena, parser.current_scope->symbols, &new_sym,
|
return List_push(arena, parser->current_scope->symbols, &new_sym,
|
||||||
sizeof(Symbol));
|
sizeof(Symbol));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_global(void)
|
is_global(void)
|
||||||
{
|
{
|
||||||
return parser.current_scope != nil && parser.current_scope->parent == nil;
|
return parser->current_scope != nil && parser->current_scope->parent == nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_type(void)
|
is_type(void)
|
||||||
{
|
{
|
||||||
return parser.previous.type >= TOKEN_TYPE_I8 &&
|
return parser->previous.type >= TOKEN_TYPE_I8 &&
|
||||||
parser.previous.type <= TOKEN_TYPE_PTR;
|
parser->previous.type <= TOKEN_TYPE_PTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
SymbolType
|
SymbolType
|
||||||
|
|
@ -158,11 +158,11 @@ token_type_to_sym_type(TokenType t)
|
||||||
bool
|
bool
|
||||||
advance(void)
|
advance(void)
|
||||||
{
|
{
|
||||||
parser.previous = parser.current;
|
parser->previous = parser->current;
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
parser.current = next_token();
|
parser->current = next_token();
|
||||||
if(parser.current.type != TOKEN_ERROR) return true;
|
if(parser->current.type != TOKEN_ERROR) return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -170,7 +170,7 @@ advance(void)
|
||||||
bool
|
bool
|
||||||
check(TokenType type)
|
check(TokenType type)
|
||||||
{
|
{
|
||||||
return parser.current.type == type;
|
return parser->current.type == type;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
@ -207,8 +207,8 @@ void
|
||||||
expect(TokenType type)
|
expect(TokenType type)
|
||||||
{
|
{
|
||||||
if(!consume(type)) {
|
if(!consume(type)) {
|
||||||
emitter.error(parser.previous.start, parser.previous.length,
|
emitter->error(parser->previous.start, parser->previous.length,
|
||||||
parser.previous.line);
|
parser->previous.line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -230,7 +230,7 @@ define_function(void)
|
||||||
Symbol *fn;
|
Symbol *fn;
|
||||||
u32 size = 0;
|
u32 size = 0;
|
||||||
advance();
|
advance();
|
||||||
fn = scope_add_symbol(parser.previous.start, parser.previous.length,
|
fn = scope_add_symbol(parser->previous.start, parser->previous.length,
|
||||||
SYMBOL_FUNCTION, 0);
|
SYMBOL_FUNCTION, 0);
|
||||||
|
|
||||||
/* need to push scope early because the variables need to be a part of the fn
|
/* need to push scope early because the variables need to be a part of the fn
|
||||||
|
|
@ -250,20 +250,20 @@ define_function(void)
|
||||||
|
|
||||||
if(is_type()) {
|
if(is_type()) {
|
||||||
/* get return slot */
|
/* get return slot */
|
||||||
fn->secondary_type = token_type_to_sym_type(parser.previous.type);
|
fn->secondary_type = token_type_to_sym_type(parser->previous.type);
|
||||||
/* now parse the fn body */
|
/* now parse the fn body */
|
||||||
}
|
}
|
||||||
expect(TOKEN_LBRACE);
|
expect(TOKEN_LBRACE);
|
||||||
|
|
||||||
/* get the size of all the locals for the function in the body */
|
/* get the size of all the locals for the function in the body */
|
||||||
while(parser.depth > 0) {
|
while(parser->depth > 0) {
|
||||||
if(match(TOKEN_LBRACE)) {
|
if(match(TOKEN_LBRACE)) {
|
||||||
scope_new();
|
scope_new();
|
||||||
continue;
|
continue;
|
||||||
} else if(match(TOKEN_RBRACE)) {
|
} else if(match(TOKEN_RBRACE)) {
|
||||||
scope_pop();
|
scope_pop();
|
||||||
continue;
|
continue;
|
||||||
} else if(is_type() && parser.current.type == TOKEN_IDENTIFIER)
|
} else if(is_type() && parser->current.type == TOKEN_IDENTIFIER)
|
||||||
size += variable_declaration(nil);
|
size += variable_declaration(nil);
|
||||||
advance();
|
advance();
|
||||||
}
|
}
|
||||||
|
|
@ -292,7 +292,7 @@ calculate_strides(List *dims, List *strides)
|
||||||
if (num){
|
if (num){
|
||||||
current_stride *= (*num);
|
current_stride *= (*num);
|
||||||
} else {
|
} else {
|
||||||
emitter.error("Tried to get a dimension that did not exist", 43, parser.previous.line);
|
emitter->error("Tried to get a dimension that did not exist", 43, parser->previous.line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -301,7 +301,7 @@ void
|
||||||
define_array(void)
|
define_array(void)
|
||||||
{
|
{
|
||||||
i32 size = 0, n = 0, flat_array_length = 1;
|
i32 size = 0, n = 0, flat_array_length = 1;
|
||||||
TokenType tt = parser.previous.type;
|
TokenType tt = parser->previous.type;
|
||||||
SymbolType st = token_type_to_sym_type(tt);
|
SymbolType st = token_type_to_sym_type(tt);
|
||||||
Symbol *array;
|
Symbol *array;
|
||||||
|
|
||||||
|
|
@ -310,8 +310,8 @@ define_array(void)
|
||||||
advance();
|
advance();
|
||||||
|
|
||||||
while(!match(TOKEN_RBRACKET)) {
|
while(!match(TOKEN_RBRACKET)) {
|
||||||
if(parser.current.type == TOKEN_LITERAL_INT) {
|
if(parser->current.type == TOKEN_LITERAL_INT) {
|
||||||
n = ston(parser.current.start, parser.current.length);
|
n = ston(parser->current.start, parser->current.length);
|
||||||
flat_array_length *= n;
|
flat_array_length *= n;
|
||||||
List_push(arena, dims, &n, sizeof(u32));
|
List_push(arena, dims, &n, sizeof(u32));
|
||||||
}
|
}
|
||||||
|
|
@ -322,9 +322,9 @@ define_array(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size = emitter.get_size(st) * flat_array_length;
|
size = emitter->get_size(st) * flat_array_length;
|
||||||
|
|
||||||
array = scope_add_symbol(parser.current.start, parser.current.length,
|
array = scope_add_symbol(parser->current.start, parser->current.length,
|
||||||
SYMBOL_ARRAY, size);
|
SYMBOL_ARRAY, size);
|
||||||
array->secondary_type = st;
|
array->secondary_type = st;
|
||||||
calculate_strides(dims, strides);
|
calculate_strides(dims, strides);
|
||||||
|
|
@ -351,8 +351,8 @@ build_symbol_table(char *source)
|
||||||
define_plex();
|
define_plex();
|
||||||
} else if(match(TOKEN_KEYWORD_TRAIT)) {
|
} else if(match(TOKEN_KEYWORD_TRAIT)) {
|
||||||
define_trait();
|
define_trait();
|
||||||
} else if (parser.current.type >= TOKEN_TYPE_I8 &&
|
} else if (parser->current.type >= TOKEN_TYPE_I8 &&
|
||||||
parser.current.type <= TOKEN_TYPE_PTR) {
|
parser->current.type <= TOKEN_TYPE_PTR) {
|
||||||
advance();
|
advance();
|
||||||
if (check(TOKEN_LBRACKET)) {
|
if (check(TOKEN_LBRACKET)) {
|
||||||
define_array();
|
define_array();
|
||||||
|
|
@ -375,22 +375,22 @@ u32
|
||||||
variable_declaration(Symbol *def)
|
variable_declaration(Symbol *def)
|
||||||
{
|
{
|
||||||
i32 size = 0;
|
i32 size = 0;
|
||||||
TokenType tt = parser.previous.type;
|
TokenType tt = parser->previous.type;
|
||||||
SymbolType st = token_type_to_sym_type(tt);
|
SymbolType st = token_type_to_sym_type(tt);
|
||||||
Symbol *variable;
|
Symbol *variable;
|
||||||
List *array_literal;
|
List *array_literal;
|
||||||
|
|
||||||
if (parser.current.type == TOKEN_LBRACKET) {
|
if (parser->current.type == TOKEN_LBRACKET) {
|
||||||
while(!check(TOKEN_RBRACKET)) {
|
while(!check(TOKEN_RBRACKET)) {
|
||||||
advance();
|
advance();
|
||||||
}
|
}
|
||||||
advance();
|
advance();
|
||||||
|
|
||||||
variable = scope_get_symbol(parser.current_scope,
|
variable = scope_get_symbol(parser->current_scope,
|
||||||
parser.current.start,
|
parser->current.start,
|
||||||
parser.current.length);
|
parser->current.length);
|
||||||
if (!variable) {
|
if (!variable) {
|
||||||
emitter.error("cannot find array symbol", 24, parser.current.line);
|
emitter->error("cannot find array symbol", 24, parser->current.line);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance();
|
advance();
|
||||||
|
|
@ -401,119 +401,119 @@ variable_declaration(Symbol *def)
|
||||||
|
|
||||||
while (!match(TOKEN_RBRACKET)) {
|
while (!match(TOKEN_RBRACKET)) {
|
||||||
StrBuf_append_exactly(arena, array_literal,
|
StrBuf_append_exactly(arena, array_literal,
|
||||||
(char*)parser.current.start,
|
(char*)parser->current.start,
|
||||||
parser.current.length);
|
parser->current.length);
|
||||||
advance();
|
advance();
|
||||||
if(match(TOKEN_RBRACKET)) break;
|
if(match(TOKEN_RBRACKET)) break;
|
||||||
expect(TOKEN_COMMA);
|
expect(TOKEN_COMMA);
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(TOKEN_SEMICOLON);
|
expect(TOKEN_SEMICOLON);
|
||||||
emitter.emit_array(arena, memory, variable, array_literal);
|
emitter->emit_array(arena, memory, variable, array_literal);
|
||||||
} else {
|
} else {
|
||||||
expect(TOKEN_SEMICOLON);
|
expect(TOKEN_SEMICOLON);
|
||||||
|
|
||||||
emitter.emit_array(arena, memory, variable, nil);
|
emitter->emit_array(arena, memory, variable, nil);
|
||||||
emitter.emit_zero_block(arena, memory, variable->size * emitter.get_size(variable->secondary_type));
|
emitter->emit_zero_block(arena, memory, variable->size * emitter->get_size(variable->secondary_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
return variable->size;
|
return variable->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(st != SYMBOL_UNDEFINED) {
|
if(st != SYMBOL_UNDEFINED) {
|
||||||
size = emitter.get_size(st);
|
size = emitter->get_size(st);
|
||||||
|
|
||||||
variable = scope_add_symbol(parser.current.start, parser.current.length, st, size);
|
variable = scope_add_symbol(parser->current.start, parser->current.length, st, size);
|
||||||
|
|
||||||
if(!def && (parser.pass == 0)) return size;
|
if(!def && (parser->pass == 0)) return size;
|
||||||
|
|
||||||
if(def) {
|
if(def) {
|
||||||
List_push(arena, def->args, variable, sizeof(Symbol));
|
List_push(arena, def->args, variable, sizeof(Symbol));
|
||||||
} else {
|
} else {
|
||||||
emitter.emit_type(arena, code, variable, parser.depth);
|
emitter->emit_type(arena, code, variable, parser->depth);
|
||||||
parser.current_type = st;
|
parser->current_type = st;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* we need to look up the type */
|
/* we need to look up the type */
|
||||||
emitter.error("Not implemented", 16, parser.previous.line);
|
emitter->error("Not implemented", 16, parser->previous.line);
|
||||||
}
|
}
|
||||||
|
|
||||||
advance();
|
advance();
|
||||||
|
|
||||||
if(def && (check(TOKEN_COMMA) || check(TOKEN_RPAREN))) return size;
|
if(def && (check(TOKEN_COMMA) || check(TOKEN_RPAREN))) return size;
|
||||||
if(def)
|
if(def)
|
||||||
emitter.error(parser.previous.start, parser.previous.length,
|
emitter->error(parser->previous.start, parser->previous.length,
|
||||||
parser.previous.line);
|
parser->previous.line);
|
||||||
if(parser.pass == 0) return size;
|
if(parser->pass == 0) return size;
|
||||||
|
|
||||||
if(match(TOKEN_EQ)) {
|
if(match(TOKEN_EQ)) {
|
||||||
emitter.emit_set_value(arena, code);
|
emitter->emit_set_value(arena, code);
|
||||||
expression();
|
expression();
|
||||||
emitter.emit_constant(arena, code, variable, parser.depth);
|
emitter->emit_constant(arena, code, variable, parser->depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
consume(TOKEN_SEMICOLON);
|
consume(TOKEN_SEMICOLON);
|
||||||
emitter.emit_end_statement(arena, code);
|
emitter->emit_end_statement(arena, code);
|
||||||
parser.current_type = SYMBOL_UNDEFINED;
|
parser->current_type = SYMBOL_UNDEFINED;
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
binary(void)
|
binary(void)
|
||||||
{
|
{
|
||||||
TokenType operatorType = parser.previous.type;
|
TokenType operatorType = parser->previous.type;
|
||||||
ParseRule *rule = get_rule(operatorType);
|
ParseRule *rule = get_rule(operatorType);
|
||||||
|
|
||||||
parse_precedence((Precedence)(rule->precedence + 1));
|
parse_precedence((Precedence)(rule->precedence + 1));
|
||||||
|
|
||||||
switch(operatorType) {
|
switch(operatorType) {
|
||||||
case TOKEN_BANG_EQ:
|
case TOKEN_BANG_EQ:
|
||||||
emitter.emit_ne(arena, code);
|
emitter->emit_ne(arena, code);
|
||||||
break;
|
break;
|
||||||
case TOKEN_EQ_EQ:
|
case TOKEN_EQ_EQ:
|
||||||
emitter.emit_eq(arena, code);
|
emitter->emit_eq(arena, code);
|
||||||
break;
|
break;
|
||||||
case TOKEN_GT:
|
case TOKEN_GT:
|
||||||
emitter.emit_gt(arena, code);
|
emitter->emit_gt(arena, code);
|
||||||
break;
|
break;
|
||||||
case TOKEN_GTE:
|
case TOKEN_GTE:
|
||||||
emitter.emit_ge(arena, code);
|
emitter->emit_ge(arena, code);
|
||||||
break;
|
break;
|
||||||
case TOKEN_LT:
|
case TOKEN_LT:
|
||||||
emitter.emit_lt(arena, code);
|
emitter->emit_lt(arena, code);
|
||||||
break;
|
break;
|
||||||
case TOKEN_LTE:
|
case TOKEN_LTE:
|
||||||
emitter.emit_le(arena, code);
|
emitter->emit_le(arena, code);
|
||||||
break;
|
break;
|
||||||
case TOKEN_PLUS:
|
case TOKEN_PLUS:
|
||||||
emitter.emit_add(arena, code);
|
emitter->emit_add(arena, code);
|
||||||
break;
|
break;
|
||||||
case TOKEN_MINUS:
|
case TOKEN_MINUS:
|
||||||
emitter.emit_sub(arena, code);
|
emitter->emit_sub(arena, code);
|
||||||
break;
|
break;
|
||||||
case TOKEN_STAR:
|
case TOKEN_STAR:
|
||||||
emitter.emit_mul(arena, code);
|
emitter->emit_mul(arena, code);
|
||||||
break;
|
break;
|
||||||
case TOKEN_SLASH:
|
case TOKEN_SLASH:
|
||||||
emitter.emit_div(arena, code);
|
emitter->emit_div(arena, code);
|
||||||
break;
|
break;
|
||||||
case TOKEN_OPERATOR_AND:
|
case TOKEN_OPERATOR_AND:
|
||||||
emitter.emit_and(arena, code);
|
emitter->emit_and(arena, code);
|
||||||
break;
|
break;
|
||||||
case TOKEN_OPERATOR_OR:
|
case TOKEN_OPERATOR_OR:
|
||||||
emitter.emit_or(arena, code);
|
emitter->emit_or(arena, code);
|
||||||
break;
|
break;
|
||||||
case TOKEN_OPERATOR_XOR:
|
case TOKEN_OPERATOR_XOR:
|
||||||
emitter.emit_xor(arena, code);
|
emitter->emit_xor(arena, code);
|
||||||
break;
|
break;
|
||||||
case TOKEN_OPERATOR_MOD:
|
case TOKEN_OPERATOR_MOD:
|
||||||
emitter.emit_mod(arena, code);
|
emitter->emit_mod(arena, code);
|
||||||
break;
|
break;
|
||||||
case TOKEN_SLL:
|
case TOKEN_SLL:
|
||||||
emitter.emit_sll(arena, code);
|
emitter->emit_sll(arena, code);
|
||||||
break;
|
break;
|
||||||
case TOKEN_SRL:
|
case TOKEN_SRL:
|
||||||
emitter.emit_srl(arena, code);
|
emitter->emit_srl(arena, code);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
|
|
@ -523,15 +523,15 @@ binary(void)
|
||||||
void
|
void
|
||||||
literal(void)
|
literal(void)
|
||||||
{
|
{
|
||||||
switch(parser.previous.type) {
|
switch(parser->previous.type) {
|
||||||
case TOKEN_KEYWORD_FALSE:
|
case TOKEN_KEYWORD_FALSE:
|
||||||
emitter.emit_false(arena, code);
|
emitter->emit_false(arena, code);
|
||||||
break;
|
break;
|
||||||
case TOKEN_KEYWORD_TRUE:
|
case TOKEN_KEYWORD_TRUE:
|
||||||
emitter.emit_true(arena, code);
|
emitter->emit_true(arena, code);
|
||||||
break;
|
break;
|
||||||
case TOKEN_KEYWORD_NIL:
|
case TOKEN_KEYWORD_NIL:
|
||||||
emitter.emit_nil(arena, code);
|
emitter->emit_nil(arena, code);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
|
|
@ -547,83 +547,83 @@ expression(void)
|
||||||
void
|
void
|
||||||
variable(void)
|
variable(void)
|
||||||
{
|
{
|
||||||
Symbol *sym = scope_get_symbol(parser.current_scope, parser.previous.start,
|
Symbol *sym = scope_get_symbol(parser->current_scope, parser->previous.start,
|
||||||
parser.previous.length);
|
parser->previous.length);
|
||||||
if(sym == nil) {
|
if(sym == nil) {
|
||||||
emitter.error(parser.previous.start, parser.previous.length,
|
emitter->error(parser->previous.start, parser->previous.length,
|
||||||
parser.previous.line);
|
parser->previous.line);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sym->type == SYMBOL_FUNCTION) {
|
if(sym->type == SYMBOL_FUNCTION) {
|
||||||
parser.call_fn = sym;
|
parser->call_fn = sym;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sym->type == SYMBOL_ARRAY) {
|
if (sym->type == SYMBOL_ARRAY) {
|
||||||
emitter.emit_deref_prolog(arena, code, sym);
|
emitter->emit_deref_prolog(arena, code, sym);
|
||||||
|
|
||||||
if (match(TOKEN_LBRACKET)) {
|
if (match(TOKEN_LBRACKET)) {
|
||||||
expression();
|
expression();
|
||||||
emitter.emit_address(arena, code, emitter.get_size(sym->secondary_type));
|
emitter->emit_address(arena, code, emitter->get_size(sym->secondary_type));
|
||||||
emitter.emit_mul(arena, code);
|
emitter->emit_mul(arena, code);
|
||||||
emitter.emit_add(arena, code);
|
emitter->emit_add(arena, code);
|
||||||
/* add offset of "length"*/
|
/* add offset of "length"*/
|
||||||
emitter.emit_nat(arena, code, "2", 1);
|
emitter->emit_nat(arena, code, "2", 1);
|
||||||
emitter.emit_add(arena, code);
|
emitter->emit_add(arena, code);
|
||||||
emitter.emit_deref(arena, code);
|
emitter->emit_deref(arena, code);
|
||||||
while (!match(TOKEN_RBRACKET)) {
|
while (!match(TOKEN_RBRACKET)) {
|
||||||
}
|
}
|
||||||
} else if (match(TOKEN_DOT)) {
|
} else if (match(TOKEN_DOT)) {
|
||||||
if (sleq("length", parser.current.start, parser.current.length)) {
|
if (sleq("length", parser->current.start, parser->current.length)) {
|
||||||
emitter.emit_deref(arena, code);
|
emitter->emit_deref(arena, code);
|
||||||
} else {
|
} else {
|
||||||
emitter.error("arrays currently can only get their length, don't do anything fancy yet...", 75, parser.current.line);
|
emitter->error("arrays currently can only get their length, don't do anything fancy yet...", 75, parser->current.line);
|
||||||
}
|
}
|
||||||
advance();
|
advance();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
parser.current_type = sym->type;
|
parser->current_type = sym->type;
|
||||||
if(match(TOKEN_EQ)) {
|
if(match(TOKEN_EQ)) {
|
||||||
expression();
|
expression();
|
||||||
emitter.emit_set_variable(arena, code, sym, sym->scope);
|
emitter->emit_set_variable(arena, code, sym, sym->scope);
|
||||||
} else {
|
} else {
|
||||||
emitter.emit_variable(arena, code, sym, sym->scope);
|
emitter->emit_variable(arena, code, sym, sym->scope);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cast_type(void)
|
cast_type(void)
|
||||||
{
|
{
|
||||||
SymbolType st = parser.current_type;
|
SymbolType st = parser->current_type;
|
||||||
TokenType cast_type;
|
TokenType cast_type;
|
||||||
if(!(parser.current.type >= TOKEN_TYPE_I8 &&
|
if(!(parser->current.type >= TOKEN_TYPE_I8 &&
|
||||||
parser.current.type <= TOKEN_TYPE_PTR)) {
|
parser->current.type <= TOKEN_TYPE_PTR)) {
|
||||||
emitter.error("Expect type name after 'as'.", 26, parser.current.line);
|
emitter->error("Expect type name after 'as'.", 26, parser->current.line);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cast_type = parser.current.type;
|
cast_type = parser->current.type;
|
||||||
advance();
|
advance();
|
||||||
|
|
||||||
switch(st) {
|
switch(st) {
|
||||||
case SYMBOL_INT: {
|
case SYMBOL_INT: {
|
||||||
switch(cast_type) {
|
switch(cast_type) {
|
||||||
case TOKEN_TYPE_NAT: {
|
case TOKEN_TYPE_NAT: {
|
||||||
emitter.emit_cast_int_to_nat(arena, code);
|
emitter->emit_cast_int_to_nat(arena, code);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TOKEN_TYPE_REAL: {
|
case TOKEN_TYPE_REAL: {
|
||||||
emitter.emit_cast_int_to_real(arena, code);
|
emitter->emit_cast_int_to_real(arena, code);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TOKEN_TYPE_STR: {
|
case TOKEN_TYPE_STR: {
|
||||||
emitter.emit_cast_int_to_str(arena, code);
|
emitter->emit_cast_int_to_str(arena, code);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
emitter.error("Not castable to int", 19, parser.previous.line);
|
emitter->error("Not castable to int", 19, parser->previous.line);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
@ -631,69 +631,69 @@ cast_type(void)
|
||||||
case SYMBOL_NAT: {
|
case SYMBOL_NAT: {
|
||||||
switch(cast_type) {
|
switch(cast_type) {
|
||||||
case TOKEN_TYPE_INT: {
|
case TOKEN_TYPE_INT: {
|
||||||
emitter.emit_cast_nat_to_int(arena, code);
|
emitter->emit_cast_nat_to_int(arena, code);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TOKEN_TYPE_REAL: {
|
case TOKEN_TYPE_REAL: {
|
||||||
emitter.emit_cast_nat_to_real(arena, code);
|
emitter->emit_cast_nat_to_real(arena, code);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TOKEN_TYPE_STR: {
|
case TOKEN_TYPE_STR: {
|
||||||
emitter.emit_cast_nat_to_str(arena, code);
|
emitter->emit_cast_nat_to_str(arena, code);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
emitter.error("Not castable to nat", 19, parser.previous.line);
|
emitter->error("Not castable to nat", 19, parser->previous.line);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SYMBOL_REAL: {
|
case SYMBOL_REAL: {
|
||||||
switch(cast_type) {
|
switch(cast_type) {
|
||||||
case TOKEN_TYPE_NAT: {
|
case TOKEN_TYPE_NAT: {
|
||||||
emitter.emit_cast_real_to_nat(arena, code);
|
emitter->emit_cast_real_to_nat(arena, code);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TOKEN_TYPE_INT: {
|
case TOKEN_TYPE_INT: {
|
||||||
emitter.emit_cast_real_to_int(arena, code);
|
emitter->emit_cast_real_to_int(arena, code);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TOKEN_TYPE_STR: {
|
case TOKEN_TYPE_STR: {
|
||||||
emitter.emit_cast_real_to_str(arena, code);
|
emitter->emit_cast_real_to_str(arena, code);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
emitter.error("Not castable to real", 20, parser.previous.line);
|
emitter->error("Not castable to real", 20, parser->previous.line);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SYMBOL_STR: {
|
case SYMBOL_STR: {
|
||||||
switch(cast_type) {
|
switch(cast_type) {
|
||||||
case TOKEN_TYPE_NAT: {
|
case TOKEN_TYPE_NAT: {
|
||||||
emitter.emit_cast_str_to_nat(arena, code);
|
emitter->emit_cast_str_to_nat(arena, code);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TOKEN_TYPE_REAL: {
|
case TOKEN_TYPE_REAL: {
|
||||||
emitter.emit_cast_str_to_real(arena, code);
|
emitter->emit_cast_str_to_real(arena, code);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TOKEN_TYPE_INT: {
|
case TOKEN_TYPE_INT: {
|
||||||
emitter.emit_cast_str_to_int(arena, code);
|
emitter->emit_cast_str_to_int(arena, code);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
emitter.error("Not castable to str", 19, parser.previous.line);
|
emitter->error("Not castable to str", 19, parser->previous.line);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
emitter.error("Type cast not implemented for this type (oops)", 46, parser.previous.line);
|
emitter->error("Type cast not implemented for this type (oops)", 46, parser->previous.line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
declaration(void)
|
declaration(void)
|
||||||
{
|
{
|
||||||
if(is_type() && (parser.current.type == TOKEN_IDENTIFIER || parser.current.type == TOKEN_LBRACKET) )
|
if(is_type() && (parser->current.type == TOKEN_IDENTIFIER || parser->current.type == TOKEN_LBRACKET) )
|
||||||
variable_declaration(nil);
|
variable_declaration(nil);
|
||||||
else
|
else
|
||||||
statement();
|
statement();
|
||||||
|
|
@ -704,8 +704,8 @@ print_statement(void)
|
||||||
{
|
{
|
||||||
expression();
|
expression();
|
||||||
consume(TOKEN_SEMICOLON);
|
consume(TOKEN_SEMICOLON);
|
||||||
emitter.emit_print(arena, code);
|
emitter->emit_print(arena, code);
|
||||||
emitter.emit_end_statement(arena, code);
|
emitter->emit_end_statement(arena, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -714,29 +714,29 @@ if_statement(void)
|
||||||
consume(TOKEN_LPAREN);
|
consume(TOKEN_LPAREN);
|
||||||
expression();
|
expression();
|
||||||
consume(TOKEN_RPAREN);
|
consume(TOKEN_RPAREN);
|
||||||
emitter.emit_if(arena, code);
|
emitter->emit_if(arena, code);
|
||||||
statement();
|
statement();
|
||||||
|
|
||||||
emitter.emit_patch_if(arena, code, emitter.ifs);
|
emitter->emit_patch_if(arena, code, emitter->ifs);
|
||||||
if(match(TOKEN_KEYWORD_ELSE)) {
|
if(match(TOKEN_KEYWORD_ELSE)) {
|
||||||
emitter.else_if_depth++;
|
emitter->else_if_depth++;
|
||||||
statement();
|
statement();
|
||||||
emitter.else_if_depth--;
|
emitter->else_if_depth--;
|
||||||
}
|
}
|
||||||
if(emitter.else_if_depth == 0) emitter.emit_patch_if_done(arena, code, emitter.ifs++);
|
if(emitter->else_if_depth == 0) emitter->emit_patch_if_done(arena, code, emitter->ifs++);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
while_statement(void)
|
while_statement(void)
|
||||||
{
|
{
|
||||||
u32 this_while = emitter.loops++;
|
u32 this_while = emitter->loops++;
|
||||||
emitter.emit_while(arena, code, this_while);
|
emitter->emit_while(arena, code, this_while);
|
||||||
consume(TOKEN_LPAREN);
|
consume(TOKEN_LPAREN);
|
||||||
expression();
|
expression();
|
||||||
consume(TOKEN_RPAREN);
|
consume(TOKEN_RPAREN);
|
||||||
emitter.emit_while_postfix(arena, code);
|
emitter->emit_while_postfix(arena, code);
|
||||||
statement();
|
statement();
|
||||||
emitter.emit_patch_while(arena, code, this_while);
|
emitter->emit_patch_while(arena, code, this_while);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -750,15 +750,15 @@ block(void)
|
||||||
void
|
void
|
||||||
function(void)
|
function(void)
|
||||||
{
|
{
|
||||||
Symbol *sym = scope_get_symbol(parser.current_scope, parser.previous.start,
|
Symbol *sym = scope_get_symbol(parser->current_scope, parser->previous.start,
|
||||||
parser.previous.length);
|
parser->previous.length);
|
||||||
emitter.emit_function(arena, code, sym);
|
emitter->emit_function(arena, code, sym);
|
||||||
scope_push();
|
scope_push();
|
||||||
while(!check(TOKEN_RPAREN)) advance();
|
while(!check(TOKEN_RPAREN)) advance();
|
||||||
consume(TOKEN_RPAREN);
|
consume(TOKEN_RPAREN);
|
||||||
consume(TOKEN_LBRACE);
|
consume(TOKEN_LBRACE);
|
||||||
block();
|
block();
|
||||||
emitter.emit_arena_fn_return(arena, code);
|
emitter->emit_arena_fn_return(arena, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -771,8 +771,8 @@ call(void)
|
||||||
}
|
}
|
||||||
consume(TOKEN_RPAREN);
|
consume(TOKEN_RPAREN);
|
||||||
|
|
||||||
emitter.emit_arena_fn_call(arena, code, parser.call_fn);
|
emitter->emit_arena_fn_call(arena, code, parser->call_fn);
|
||||||
parser.current_type = parser.call_fn->secondary_type;
|
parser->current_type = parser->call_fn->secondary_type;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -780,11 +780,11 @@ void
|
||||||
return_statement(void)
|
return_statement(void)
|
||||||
{
|
{
|
||||||
if(match(TOKEN_SEMICOLON)) {
|
if(match(TOKEN_SEMICOLON)) {
|
||||||
emitter.emit_early_return(arena, code);
|
emitter->emit_early_return(arena, code);
|
||||||
} else {
|
} else {
|
||||||
expression();
|
expression();
|
||||||
consume(TOKEN_SEMICOLON);
|
consume(TOKEN_SEMICOLON);
|
||||||
emitter.emit_early_return(arena, code);
|
emitter->emit_early_return(arena, code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -807,7 +807,7 @@ statement(void)
|
||||||
} else if(match(TOKEN_KEYWORD_PRINT)) {
|
} else if(match(TOKEN_KEYWORD_PRINT)) {
|
||||||
print_statement();
|
print_statement();
|
||||||
} else if(match(TOKEN_KEYWORD_HALT)) {
|
} else if(match(TOKEN_KEYWORD_HALT)) {
|
||||||
emitter.emit_halt(arena, code);
|
emitter->emit_halt(arena, code);
|
||||||
} else {
|
} else {
|
||||||
expression();
|
expression();
|
||||||
}
|
}
|
||||||
|
|
@ -816,44 +816,44 @@ statement(void)
|
||||||
void
|
void
|
||||||
grouping(void)
|
grouping(void)
|
||||||
{
|
{
|
||||||
emitter.emit_open_paren(arena, code);
|
emitter->emit_open_paren(arena, code);
|
||||||
|
|
||||||
expression();
|
expression();
|
||||||
|
|
||||||
emitter.emit_close_paren(arena, code);
|
emitter->emit_close_paren(arena, code);
|
||||||
consume(TOKEN_RPAREN);
|
consume(TOKEN_RPAREN);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
number(void)
|
number(void)
|
||||||
{
|
{
|
||||||
emitter.emit_int(arena, code, parser.previous.start, parser.previous.length);
|
emitter->emit_int(arena, code, parser->previous.start, parser->previous.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
string(void)
|
string(void)
|
||||||
{
|
{
|
||||||
emitter.emit_str(arena, code, parser.previous.start, parser.previous.length);
|
emitter->emit_str(arena, code, parser->previous.start, parser->previous.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
character(void)
|
character(void)
|
||||||
{
|
{
|
||||||
emitter.emit_char(arena, code, parser.previous.start, parser.previous.length);
|
emitter->emit_char(arena, code, parser->previous.start, parser->previous.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
unary(void)
|
unary(void)
|
||||||
{
|
{
|
||||||
TokenType operatorType = parser.previous.type;
|
TokenType operatorType = parser->previous.type;
|
||||||
parse_precedence(PREC_UNARY);
|
parse_precedence(PREC_UNARY);
|
||||||
|
|
||||||
switch(operatorType) {
|
switch(operatorType) {
|
||||||
case TOKEN_MINUS:
|
case TOKEN_MINUS:
|
||||||
emitter.emit_neg(arena, code);
|
emitter->emit_neg(arena, code);
|
||||||
break;
|
break;
|
||||||
case TOKEN_BANG:
|
case TOKEN_BANG:
|
||||||
emitter.emit_not(arena, code);
|
emitter->emit_not(arena, code);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
|
|
@ -863,7 +863,7 @@ unary(void)
|
||||||
void
|
void
|
||||||
read(void)
|
read(void)
|
||||||
{
|
{
|
||||||
emitter.emit_read(arena, code);
|
emitter->emit_read(arena, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -872,7 +872,7 @@ write(void)
|
||||||
consume(TOKEN_EQ);
|
consume(TOKEN_EQ);
|
||||||
advance();
|
advance();
|
||||||
variable();
|
variable();
|
||||||
emitter.emit_write(arena, code);
|
emitter->emit_write(arena, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
ParseRule rules[] = {
|
ParseRule rules[] = {
|
||||||
|
|
@ -971,14 +971,14 @@ parse_precedence(Precedence precedence)
|
||||||
ParseFn infixRule;
|
ParseFn infixRule;
|
||||||
|
|
||||||
advance();
|
advance();
|
||||||
prefixRule = get_rule(parser.previous.type)->prefix;
|
prefixRule = get_rule(parser->previous.type)->prefix;
|
||||||
if(prefixRule == nil) return;
|
if(prefixRule == nil) return;
|
||||||
|
|
||||||
prefixRule();
|
prefixRule();
|
||||||
|
|
||||||
while(precedence <= get_rule(parser.current.type)->precedence) {
|
while(precedence <= get_rule(parser->current.type)->precedence) {
|
||||||
advance();
|
advance();
|
||||||
infixRule = get_rule(parser.previous.type)->infix;
|
infixRule = get_rule(parser->previous.type)->infix;
|
||||||
infixRule();
|
infixRule();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -995,25 +995,27 @@ emit_program(char *source)
|
||||||
init_lexer(source);
|
init_lexer(source);
|
||||||
advance();
|
advance();
|
||||||
|
|
||||||
emitter.prolog(arena, code);
|
emitter->prolog(arena, code);
|
||||||
|
|
||||||
while(!match(TOKEN_EOF)) declaration();
|
while(!match(TOKEN_EOF)) declaration();
|
||||||
|
|
||||||
emitter.epilogue(arena, code);
|
emitter->epilogue(arena, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
compile(Arena *a, List *c, List* m, Emitter e, char *source)
|
compile(Arena *a, List *c, List* m, Emitter *e, char *source)
|
||||||
{
|
{
|
||||||
|
Parser p = {0};
|
||||||
arena = a;
|
arena = a;
|
||||||
emitter = e;
|
emitter = e;
|
||||||
code = c;
|
code = c;
|
||||||
memory = m;
|
memory = m;
|
||||||
parser.scopes = List_init(arena);
|
parser = &p;
|
||||||
|
parser->scopes = List_init(arena);
|
||||||
|
|
||||||
build_symbol_table(source);
|
build_symbol_table(source);
|
||||||
parser.pass++;
|
parser->pass++;
|
||||||
parser.scope_idx = 0;
|
parser->scope_idx = 0;
|
||||||
emit_program(source);
|
emit_program(source);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,6 @@ struct parser_s {
|
||||||
u8 pass;
|
u8 pass;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool compile(Arena *a, List *c, List *m, Emitter e, char *source);
|
bool compile(Arena *a, List *c, List *m, Emitter *e, char *source);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
108
lexer.c
108
lexer.c
|
|
@ -17,26 +17,26 @@ init_lexer(const char *source)
|
||||||
lexer.line = 1;
|
lexer.line = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
bool
|
||||||
is_alpha(char c)
|
lex_is_alpha(char c)
|
||||||
{
|
{
|
||||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
|
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
bool
|
||||||
is_digit(char c)
|
lex_is_digit(char c)
|
||||||
{
|
{
|
||||||
return c >= '0' && c <= '9';
|
return c >= '0' && c <= '9';
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
bool
|
||||||
is_at_end(void)
|
is_at_end(void)
|
||||||
{
|
{
|
||||||
return *lexer.current == '\0';
|
return *lexer.current == '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
static char
|
char
|
||||||
advance(void)
|
lex_advance(void)
|
||||||
{
|
{
|
||||||
lexer.current++;
|
lexer.current++;
|
||||||
return lexer.current[-1];
|
return lexer.current[-1];
|
||||||
|
|
@ -48,15 +48,15 @@ peek(void)
|
||||||
return *lexer.current;
|
return *lexer.current;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char
|
char
|
||||||
peek_next(void)
|
peek_next(void)
|
||||||
{
|
{
|
||||||
if(is_at_end()) return '\0';
|
if(is_at_end()) return '\0';
|
||||||
return lexer.current[1];
|
return lexer.current[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
bool
|
||||||
match(char expected)
|
lex_match(char expected)
|
||||||
{
|
{
|
||||||
if(is_at_end()) return false;
|
if(is_at_end()) return false;
|
||||||
if(*lexer.current != expected) return false;
|
if(*lexer.current != expected) return false;
|
||||||
|
|
@ -64,7 +64,7 @@ match(char expected)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Token
|
Token
|
||||||
make_token(TokenType type)
|
make_token(TokenType type)
|
||||||
{
|
{
|
||||||
Token token;
|
Token token;
|
||||||
|
|
@ -75,7 +75,7 @@ make_token(TokenType type)
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Token
|
Token
|
||||||
error_token(const char *message)
|
error_token(const char *message)
|
||||||
{
|
{
|
||||||
Token token;
|
Token token;
|
||||||
|
|
@ -86,7 +86,7 @@ error_token(const char *message)
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
skip_whitespace(void)
|
skip_whitespace(void)
|
||||||
{
|
{
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
|
@ -95,29 +95,29 @@ skip_whitespace(void)
|
||||||
case ' ':
|
case ' ':
|
||||||
case '\r':
|
case '\r':
|
||||||
case '\t':
|
case '\t':
|
||||||
advance();
|
lex_advance();
|
||||||
break;
|
break;
|
||||||
case '\n':
|
case '\n':
|
||||||
lexer.line++;
|
lexer.line++;
|
||||||
advance();
|
lex_advance();
|
||||||
break;
|
break;
|
||||||
case '/':
|
case '/':
|
||||||
if(peek_next() == '/') {
|
if(peek_next() == '/') {
|
||||||
/* Single-line comment: skip until newline or end of file */
|
/* Single-line comment: skip until newline or end of file */
|
||||||
advance();
|
lex_advance();
|
||||||
while(peek() != '\n' && !is_at_end()) advance();
|
while(peek() != '\n' && !is_at_end()) lex_advance();
|
||||||
} else if(peek_next() == '*') {
|
} else if(peek_next() == '*') {
|
||||||
/* Multi-line comment: skip until '* /' or end of file */
|
/* Multi-line comment: skip until '* /' or end of file */
|
||||||
advance();
|
lex_advance();
|
||||||
advance();
|
lex_advance();
|
||||||
while(!is_at_end()) {
|
while(!is_at_end()) {
|
||||||
if(peek() == '\n') lexer.line++;
|
if(peek() == '\n') lexer.line++;
|
||||||
if(peek() == '*' && peek_next() == '/') {
|
if(peek() == '*' && peek_next() == '/') {
|
||||||
advance();
|
lex_advance();
|
||||||
advance();
|
lex_advance();
|
||||||
break; /* Exit loop, comment ended */
|
break; /* Exit loop, comment ended */
|
||||||
}
|
}
|
||||||
advance();
|
lex_advance();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return; /* Not a comment, let tokenization handle it */
|
return; /* Not a comment, let tokenization handle it */
|
||||||
|
|
@ -129,7 +129,7 @@ skip_whitespace(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static TokenType
|
TokenType
|
||||||
check_keyword(i32 start, i32 length, const char *rest, TokenType type)
|
check_keyword(i32 start, i32 length, const char *rest, TokenType type)
|
||||||
{
|
{
|
||||||
i32 s1 = lexer.current - lexer.start;
|
i32 s1 = lexer.current - lexer.start;
|
||||||
|
|
@ -139,7 +139,7 @@ check_keyword(i32 start, i32 length, const char *rest, TokenType type)
|
||||||
return TOKEN_IDENTIFIER;
|
return TOKEN_IDENTIFIER;
|
||||||
}
|
}
|
||||||
|
|
||||||
static TokenType
|
TokenType
|
||||||
identifierType(void)
|
identifierType(void)
|
||||||
{
|
{
|
||||||
switch(lexer.start[0]) {
|
switch(lexer.start[0]) {
|
||||||
|
|
@ -342,24 +342,24 @@ identifierType(void)
|
||||||
return TOKEN_IDENTIFIER;
|
return TOKEN_IDENTIFIER;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Token
|
Token
|
||||||
identifier(void)
|
identifier(void)
|
||||||
{
|
{
|
||||||
while(is_alpha(peek()) || is_digit(peek())) advance();
|
while(lex_is_alpha(peek()) || lex_is_digit(peek())) lex_advance();
|
||||||
return make_token(identifierType());
|
return make_token(identifierType());
|
||||||
}
|
}
|
||||||
|
|
||||||
static Token
|
Token
|
||||||
number(void)
|
lex_number(void)
|
||||||
{
|
{
|
||||||
while(is_digit(peek())) advance();
|
while(lex_is_digit(peek())) lex_advance();
|
||||||
|
|
||||||
/* Look for a fractional part. */
|
/* Look for a fractional part. */
|
||||||
if(peek() == '.' && is_digit(peek_next())) {
|
if(peek() == '.' && lex_is_digit(peek_next())) {
|
||||||
/* Consume the ".". */
|
/* Consume the ".". */
|
||||||
advance();
|
lex_advance();
|
||||||
|
|
||||||
while(is_digit(peek())) advance();
|
while(lex_is_digit(peek())) lex_advance();
|
||||||
|
|
||||||
return make_token(TOKEN_LITERAL_REAL);
|
return make_token(TOKEN_LITERAL_REAL);
|
||||||
}
|
}
|
||||||
|
|
@ -367,33 +367,33 @@ number(void)
|
||||||
return make_token(TOKEN_LITERAL_INT);
|
return make_token(TOKEN_LITERAL_INT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Token
|
Token
|
||||||
string(void)
|
lex_string(void)
|
||||||
{
|
{
|
||||||
while(peek() != '"' && !is_at_end()) {
|
while(peek() != '"' && !is_at_end()) {
|
||||||
if(peek() == '\n') lexer.line++;
|
if(peek() == '\n') lexer.line++;
|
||||||
advance();
|
lex_advance();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(is_at_end()) return error_token("Unterminated string.");
|
if(is_at_end()) return error_token("Unterminated string.");
|
||||||
|
|
||||||
/* The closing quote. */
|
/* The closing quote. */
|
||||||
advance();
|
lex_advance();
|
||||||
return make_token(TOKEN_LITERAL_STR);
|
return make_token(TOKEN_LITERAL_STR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Token
|
Token
|
||||||
character(void)
|
lex_character(void)
|
||||||
{
|
{
|
||||||
advance();
|
lex_advance();
|
||||||
if(peek() != '\'' && !is_at_end()) {
|
if(peek() != '\'' && !is_at_end()) {
|
||||||
advance();
|
lex_advance();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(is_at_end()) return error_token("Unterminated string.");
|
if(is_at_end()) return error_token("Unterminated string.");
|
||||||
|
|
||||||
/* The closing quote. */
|
/* The closing quote. */
|
||||||
advance();
|
lex_advance();
|
||||||
return make_token(TOKEN_LITERAL_CHAR);
|
return make_token(TOKEN_LITERAL_CHAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -407,10 +407,10 @@ next_token(void)
|
||||||
|
|
||||||
if(is_at_end()) return make_token(TOKEN_EOF);
|
if(is_at_end()) return make_token(TOKEN_EOF);
|
||||||
|
|
||||||
c = advance();
|
c = lex_advance();
|
||||||
if(is_alpha(c)) return identifier();
|
if(lex_is_alpha(c)) return identifier();
|
||||||
next = peek();
|
next = peek();
|
||||||
if((c == '-' && is_digit(next)) || is_digit(c)) return number();
|
if((c == '-' && lex_is_digit(next)) || lex_is_digit(c)) return lex_number();
|
||||||
|
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case '(':
|
case '(':
|
||||||
|
|
@ -432,13 +432,13 @@ next_token(void)
|
||||||
case '.':
|
case '.':
|
||||||
return make_token(TOKEN_DOT);
|
return make_token(TOKEN_DOT);
|
||||||
case '-':
|
case '-':
|
||||||
return make_token(match('>') ? TOKEN_ARROW_RIGHT : TOKEN_MINUS);
|
return make_token(lex_match('>') ? TOKEN_ARROW_RIGHT : TOKEN_MINUS);
|
||||||
case '+':
|
case '+':
|
||||||
return make_token(TOKEN_PLUS);
|
return make_token(TOKEN_PLUS);
|
||||||
case '/':
|
case '/':
|
||||||
return make_token(TOKEN_SLASH);
|
return make_token(TOKEN_SLASH);
|
||||||
case '&':
|
case '&':
|
||||||
return make_token(match('&') ? TOKEN_AND_AND : TOKEN_AND);
|
return make_token(lex_match('&') ? TOKEN_AND_AND : TOKEN_AND);
|
||||||
case '#':
|
case '#':
|
||||||
return make_token(TOKEN_MESH);
|
return make_token(TOKEN_MESH);
|
||||||
case '$':
|
case '$':
|
||||||
|
|
@ -446,21 +446,21 @@ next_token(void)
|
||||||
case '*':
|
case '*':
|
||||||
return make_token(TOKEN_STAR);
|
return make_token(TOKEN_STAR);
|
||||||
case '!':
|
case '!':
|
||||||
return make_token(match('=') ? TOKEN_BANG_EQ : TOKEN_BANG);
|
return make_token(lex_match('=') ? TOKEN_BANG_EQ : TOKEN_BANG);
|
||||||
case '=':
|
case '=':
|
||||||
return make_token(match('=') ? TOKEN_EQ_EQ : TOKEN_EQ);
|
return make_token(lex_match('=') ? TOKEN_EQ_EQ : TOKEN_EQ);
|
||||||
case '<':
|
case '<':
|
||||||
return make_token(match('=') ? TOKEN_LTE
|
return make_token(lex_match('=') ? TOKEN_LTE
|
||||||
: match('<') ? TOKEN_SLL
|
: lex_match('<') ? TOKEN_SLL
|
||||||
: TOKEN_LT);
|
: TOKEN_LT);
|
||||||
case '>':
|
case '>':
|
||||||
return make_token(match('=') ? TOKEN_GTE
|
return make_token(lex_match('=') ? TOKEN_GTE
|
||||||
: match('>') ? TOKEN_SRL
|
: lex_match('>') ? TOKEN_SRL
|
||||||
: TOKEN_GT);
|
: TOKEN_GT);
|
||||||
case '"':
|
case '"':
|
||||||
return string();
|
return lex_string();
|
||||||
case '\'':
|
case '\'':
|
||||||
return character();
|
return lex_character();
|
||||||
}
|
}
|
||||||
|
|
||||||
return error_token("Unexpected character.");
|
return error_token("Unexpected character.");
|
||||||
|
|
|
||||||
11
libc.c
11
libc.c
|
|
@ -78,12 +78,15 @@ snlen(const char *str, u32 max_len)
|
||||||
void *
|
void *
|
||||||
aalloc(Arena *arena, u32 size)
|
aalloc(Arena *arena, u32 size)
|
||||||
{
|
{
|
||||||
u32 pos;
|
u32 pos, aligned;
|
||||||
if(arena == nil) return nil;
|
if(arena == nil) return nil;
|
||||||
if(arena->count + size > arena->capacity) return nil;
|
|
||||||
|
|
||||||
pos = arena->count;
|
aligned = (arena->count + 7) & ~7;
|
||||||
arena->count += size;
|
|
||||||
|
if(aligned + size > arena->capacity) return nil;
|
||||||
|
|
||||||
|
pos = aligned;
|
||||||
|
arena->count = pos + size;
|
||||||
return (void *)&arena->tape[pos];
|
return (void *)&arena->tape[pos];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue