wip string and array indexing, need to do setting index array yet
This commit is contained in:
parent
b8899d8bc9
commit
23bb9f73e7
|
|
@ -3,7 +3,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
static char *
|
char *
|
||||||
readFile(const char *path)
|
readFile(const char *path)
|
||||||
{
|
{
|
||||||
FILE *file = fopen(path, "rb");
|
FILE *file = fopen(path, "rb");
|
||||||
|
|
@ -75,18 +75,18 @@ main(int argc, char **argv)
|
||||||
compile(&a, code, memory, &e, source);
|
compile(&a, code, memory, &e, source);
|
||||||
|
|
||||||
Node *curr = code->head;
|
Node *curr = code->head;
|
||||||
while (curr) {
|
while(curr) {
|
||||||
char* tmp_str = node_value(curr);
|
char *tmp_str = node_value(curr);
|
||||||
printf("%.*s", curr->size, tmp_str);
|
printf("%.*s", curr->size, tmp_str);
|
||||||
curr = curr->next;
|
curr = curr->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
curr = memory->head;
|
curr = memory->head;
|
||||||
while (curr) {
|
while(curr) {
|
||||||
char* tmp_str = node_value(curr);
|
char *tmp_str = node_value(curr);
|
||||||
printf("%.*s", curr->size, tmp_str);
|
printf("%.*s", curr->size, tmp_str);
|
||||||
curr = curr->next;
|
curr = curr->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
afree(&a);
|
afree(&a);
|
||||||
free(source);
|
free(source);
|
||||||
|
|
|
||||||
|
|
@ -6,58 +6,67 @@
|
||||||
|
|
||||||
#define MEM_SIZE (1 << 16)
|
#define MEM_SIZE (1 << 16)
|
||||||
|
|
||||||
static size_t List_size(List *list) {
|
size_t
|
||||||
size_t total = 0;
|
List_size(List *list)
|
||||||
Node *curr = list->head;
|
{
|
||||||
while (curr) {
|
size_t total = 0;
|
||||||
total += curr->size;
|
Node *curr = list->head;
|
||||||
curr = curr->next;
|
while(curr) {
|
||||||
}
|
total += curr->size;
|
||||||
return total;
|
curr = curr->next;
|
||||||
|
}
|
||||||
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void list2buffer(List *list, char *buffer, size_t *offset) {
|
void
|
||||||
Node *curr = list->head;
|
list2buffer(List *list, char *buffer, size_t *offset)
|
||||||
while (curr) {
|
{
|
||||||
char *tmp_str = node_value(curr);
|
Node *curr = list->head;
|
||||||
memcpy(buffer + *offset, tmp_str, curr->size);
|
while(curr) {
|
||||||
*offset += curr->size;
|
char *tmp_str = node_value(curr);
|
||||||
curr = curr->next;
|
memcpy(buffer + *offset, tmp_str, curr->size);
|
||||||
}
|
*offset += curr->size;
|
||||||
|
curr = curr->next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE
|
EMSCRIPTEN_KEEPALIVE
|
||||||
char *undar_compile(int emitter_type, char *source) {
|
char *
|
||||||
u8 tape[MEM_SIZE];
|
undar_compile(int emitter_type, char *source)
|
||||||
Arena a = {tape, 0, MEM_SIZE};
|
{
|
||||||
|
u8 tape[MEM_SIZE];
|
||||||
|
Arena a = {tape, 0, MEM_SIZE};
|
||||||
|
|
||||||
Emitter e;
|
Emitter e;
|
||||||
if (emitter_type == 0) {
|
switch(emitter_type) {
|
||||||
e = rer_emitter();
|
case 0:
|
||||||
} else if (emitter_type == 1) {
|
e = rer_emitter();
|
||||||
e = uxn_emitter();
|
break;
|
||||||
} else {
|
case 1:
|
||||||
return NULL;
|
e = uxn_emitter();
|
||||||
}
|
break;
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
size_t total_size = code_size + mem_size + 1;
|
size_t total_size = code_size + mem_size + 1;
|
||||||
|
|
||||||
char *result = (char *)malloc(total_size);
|
char *result = (char *)malloc(total_size);
|
||||||
if (result == NULL) return NULL;
|
if(result == NULL) return NULL;
|
||||||
|
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
list2buffer(code, result, &offset);
|
list2buffer(code, result, &offset);
|
||||||
list2buffer(memory, result, &offset);
|
list2buffer(memory, result, &offset);
|
||||||
result[offset] = '\0';
|
result[offset] = '\0';
|
||||||
|
|
||||||
afree(&a);
|
afree(&a);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
130
compiler.c
130
compiler.c
|
|
@ -158,6 +158,7 @@ token_type_to_sym_type(TokenType t)
|
||||||
bool
|
bool
|
||||||
advance(void)
|
advance(void)
|
||||||
{
|
{
|
||||||
|
parser->before = parser->previous;
|
||||||
parser->previous = parser->current;
|
parser->previous = parser->current;
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
|
@ -241,11 +242,9 @@ define_function(void)
|
||||||
advance();
|
advance();
|
||||||
|
|
||||||
/* parse the args */
|
/* parse the args */
|
||||||
while(!check(TOKEN_LBRACE)) {
|
while(!match(TOKEN_RPAREN)) {
|
||||||
size += variable_declaration(fn);
|
size += variable_declaration(fn);
|
||||||
advance();
|
if(match(TOKEN_RPAREN)) break;
|
||||||
if(check(TOKEN_LBRACE)) break;
|
|
||||||
advance();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(is_type()) {
|
if(is_type()) {
|
||||||
|
|
@ -332,6 +331,14 @@ define_array(void)
|
||||||
array->fields = strides;
|
array->fields = strides;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
define_string(void)
|
||||||
|
{
|
||||||
|
scope_add_symbol(parser->current.start,
|
||||||
|
parser->current.length,
|
||||||
|
SYMBOL_STR, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
build_symbol_table(char *source)
|
build_symbol_table(char *source)
|
||||||
{
|
{
|
||||||
|
|
@ -351,6 +358,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->previous.type != TOKEN_KEYWORD_AS && match(TOKEN_TYPE_STR)) {
|
||||||
|
define_string();
|
||||||
} 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();
|
||||||
|
|
@ -379,6 +388,28 @@ variable_declaration(Symbol *def)
|
||||||
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 (tt == TOKEN_TYPE_STR) {
|
||||||
|
variable = scope_get_symbol(parser->current_scope,
|
||||||
|
parser->current.start,
|
||||||
|
parser->current.length);
|
||||||
|
if (!variable) {
|
||||||
|
emitter->error("cannot find str symbol", 23, parser->current.line);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
advance();
|
||||||
|
|
||||||
|
if (match(TOKEN_EQ)) {
|
||||||
|
expect(TOKEN_LITERAL_STR);
|
||||||
|
variable->size = parser->previous.length - 2;
|
||||||
|
emitter->emit_str(arena, memory, variable, parser->previous.start, parser->previous.length);
|
||||||
|
expect(TOKEN_SEMICOLON);
|
||||||
|
}
|
||||||
|
|
||||||
|
parser->current_type = st;
|
||||||
|
return emitter->get_size(st);
|
||||||
|
}
|
||||||
|
|
||||||
if (parser->current.type == TOKEN_LBRACKET) {
|
if (parser->current.type == TOKEN_LBRACKET) {
|
||||||
while(!check(TOKEN_RBRACKET)) {
|
while(!check(TOKEN_RBRACKET)) {
|
||||||
|
|
@ -390,7 +421,7 @@ variable_declaration(Symbol *def)
|
||||||
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", 25, parser->current.line);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
advance();
|
advance();
|
||||||
|
|
@ -416,8 +447,9 @@ variable_declaration(Symbol *def)
|
||||||
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;
|
parser->current_type = st;
|
||||||
|
return emitter->get_size(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(st != SYMBOL_UNDEFINED) {
|
if(st != SYMBOL_UNDEFINED) {
|
||||||
|
|
@ -468,34 +500,34 @@ binary(void)
|
||||||
|
|
||||||
switch(operatorType) {
|
switch(operatorType) {
|
||||||
case TOKEN_BANG_EQ:
|
case TOKEN_BANG_EQ:
|
||||||
emitter->emit_ne(arena, code);
|
emitter->emit_ne(arena, code, emitter->get_size(parser->current_type));
|
||||||
break;
|
break;
|
||||||
case TOKEN_EQ_EQ:
|
case TOKEN_EQ_EQ:
|
||||||
emitter->emit_eq(arena, code);
|
emitter->emit_eq(arena, code, emitter->get_size(parser->current_type));
|
||||||
break;
|
break;
|
||||||
case TOKEN_GT:
|
case TOKEN_GT:
|
||||||
emitter->emit_gt(arena, code);
|
emitter->emit_gt(arena, code, emitter->get_size(parser->current_type));
|
||||||
break;
|
break;
|
||||||
case TOKEN_GTE:
|
case TOKEN_GTE:
|
||||||
emitter->emit_ge(arena, code);
|
emitter->emit_ge(arena, code, emitter->get_size(parser->current_type));
|
||||||
break;
|
break;
|
||||||
case TOKEN_LT:
|
case TOKEN_LT:
|
||||||
emitter->emit_lt(arena, code);
|
emitter->emit_lt(arena, code, emitter->get_size(parser->current_type));
|
||||||
break;
|
break;
|
||||||
case TOKEN_LTE:
|
case TOKEN_LTE:
|
||||||
emitter->emit_le(arena, code);
|
emitter->emit_le(arena, code, emitter->get_size(parser->current_type));
|
||||||
break;
|
break;
|
||||||
case TOKEN_PLUS:
|
case TOKEN_PLUS:
|
||||||
emitter->emit_add(arena, code);
|
emitter->emit_add(arena, code, emitter->get_size(parser->current_type));
|
||||||
break;
|
break;
|
||||||
case TOKEN_MINUS:
|
case TOKEN_MINUS:
|
||||||
emitter->emit_sub(arena, code);
|
emitter->emit_sub(arena, code, emitter->get_size(parser->current_type));
|
||||||
break;
|
break;
|
||||||
case TOKEN_STAR:
|
case TOKEN_STAR:
|
||||||
emitter->emit_mul(arena, code);
|
emitter->emit_mul(arena, code, emitter->get_size(parser->current_type));
|
||||||
break;
|
break;
|
||||||
case TOKEN_SLASH:
|
case TOKEN_SLASH:
|
||||||
emitter->emit_div(arena, code);
|
emitter->emit_div(arena, code, emitter->get_size(parser->current_type));
|
||||||
break;
|
break;
|
||||||
case TOKEN_OPERATOR_AND:
|
case TOKEN_OPERATOR_AND:
|
||||||
emitter->emit_and(arena, code);
|
emitter->emit_and(arena, code);
|
||||||
|
|
@ -544,12 +576,24 @@ expression(void)
|
||||||
parse_precedence(PREC_ASSIGNMENT);
|
parse_precedence(PREC_ASSIGNMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
dot(void)
|
||||||
|
{
|
||||||
|
Symbol *sym = scope_get_symbol(parser->current_scope, parser->before.start,
|
||||||
|
parser->before.length);
|
||||||
|
if(sym == nil) {
|
||||||
|
emitter->error(parser->current.start, parser->current.length,
|
||||||
|
parser->current.line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
return;
|
||||||
emitter->error(parser->previous.start, parser->previous.length,
|
emitter->error(parser->previous.start, parser->previous.length,
|
||||||
parser->previous.line);
|
parser->previous.line);
|
||||||
}
|
}
|
||||||
|
|
@ -559,26 +603,59 @@ variable(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sym->type == SYMBOL_STR) {
|
||||||
|
emitter->emit_deref_prolog(arena, code, sym);
|
||||||
|
|
||||||
|
if (match(TOKEN_LBRACKET)) {
|
||||||
|
/* add offset of "length"*/
|
||||||
|
emitter->emit_nat(arena, code, "2", 1);
|
||||||
|
emitter->emit_add(arena, code, 2);
|
||||||
|
expression();
|
||||||
|
emitter->emit_add(arena, code, 2);
|
||||||
|
emitter->emit_deref(arena, code, 1);
|
||||||
|
while (!match(TOKEN_RBRACKET)) {
|
||||||
|
}
|
||||||
|
parser->current_type = SYMBOL_BYTE;
|
||||||
|
} else if (match(TOKEN_DOT)) {
|
||||||
|
if (sleq("length", parser->current.start, parser->current.length)) {
|
||||||
|
emitter->emit_deref(arena, code, 2);
|
||||||
|
} else {
|
||||||
|
emitter->error("arrays currently can only get their length, don't do anything fancy yet...", 75, parser->current.line);
|
||||||
|
}
|
||||||
|
parser->current_type = SYMBOL_NAT;
|
||||||
|
advance();
|
||||||
|
} else {
|
||||||
|
emitter->emit_nat(arena, code, "2", 1);
|
||||||
|
emitter->emit_add(arena, code, 2);
|
||||||
|
/* emitter->emit_deref(arena, code); */
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (sym->type == SYMBOL_ARRAY) {
|
if (sym->type == SYMBOL_ARRAY) {
|
||||||
|
u32 size = emitter->get_size(sym->secondary_type);
|
||||||
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, size);
|
||||||
emitter->emit_mul(arena, code);
|
emitter->emit_mul(arena, code, size);
|
||||||
emitter->emit_add(arena, code);
|
emitter->emit_add(arena, code, size);
|
||||||
/* 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, size);
|
||||||
emitter->emit_deref(arena, code);
|
emitter->emit_deref(arena, code, size);
|
||||||
|
parser->current_type = sym->secondary_type;
|
||||||
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, size);
|
||||||
} 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);
|
||||||
}
|
}
|
||||||
|
parser->current_type = SYMBOL_NAT;
|
||||||
advance();
|
advance();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
@ -833,7 +910,7 @@ number(void)
|
||||||
void
|
void
|
||||||
string(void)
|
string(void)
|
||||||
{
|
{
|
||||||
emitter->emit_str(arena, code, parser->previous.start, parser->previous.length);
|
emitter->emit_inline_str(arena, code, parser->previous.start, parser->previous.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -884,6 +961,7 @@ ParseRule rules[] = {
|
||||||
/* TOKEN_RBRACE */ {nil, nil, PREC_NONE},
|
/* TOKEN_RBRACE */ {nil, nil, PREC_NONE},
|
||||||
/* TOKEN_LBRACKET */ {nil, nil, PREC_NONE},
|
/* TOKEN_LBRACKET */ {nil, nil, PREC_NONE},
|
||||||
/* TOKEN_RBRACKET */ {nil, nil, PREC_NONE},
|
/* TOKEN_RBRACKET */ {nil, nil, PREC_NONE},
|
||||||
|
/* TOKEN_DOT */ {nil, dot, PREC_CALL},
|
||||||
/* TOKEN_IDENTIFIER */ {variable, nil, PREC_NONE},
|
/* TOKEN_IDENTIFIER */ {variable, nil, PREC_NONE},
|
||||||
/* TOKEN_LITERAL_INT */ {number, nil, PREC_NONE},
|
/* TOKEN_LITERAL_INT */ {number, nil, PREC_NONE},
|
||||||
/* TOKEN_LITERAL_NAT */ {number, nil, PREC_NONE},
|
/* TOKEN_LITERAL_NAT */ {number, nil, PREC_NONE},
|
||||||
|
|
@ -948,7 +1026,6 @@ ParseRule rules[] = {
|
||||||
/* TOKEN_LT */ {nil, binary, PREC_COMPARISON},
|
/* TOKEN_LT */ {nil, binary, PREC_COMPARISON},
|
||||||
/* TOKEN_GTE */ {nil, binary, PREC_COMPARISON},
|
/* TOKEN_GTE */ {nil, binary, PREC_COMPARISON},
|
||||||
/* TOKEN_LTE */ {nil, binary, PREC_COMPARISON},
|
/* TOKEN_LTE */ {nil, binary, PREC_COMPARISON},
|
||||||
/* TOKEN_DOT */ {nil, nil, PREC_NONE},
|
|
||||||
/* TOKEN_COMMA */ {nil, nil, PREC_NONE},
|
/* TOKEN_COMMA */ {nil, nil, PREC_NONE},
|
||||||
/* TOKEN_COLON */ {nil, nil, PREC_NONE},
|
/* TOKEN_COLON */ {nil, nil, PREC_NONE},
|
||||||
/* TOKEN_CARET */ {nil, nil, PREC_NONE},
|
/* TOKEN_CARET */ {nil, nil, PREC_NONE},
|
||||||
|
|
@ -1015,7 +1092,8 @@ compile(Arena *a, List *c, List* m, Emitter *e, char *source)
|
||||||
|
|
||||||
build_symbol_table(source);
|
build_symbol_table(source);
|
||||||
parser->pass++;
|
parser->pass++;
|
||||||
parser->scope_idx = 0;
|
parser->depth = 0;
|
||||||
|
parser->scope_idx = 1;
|
||||||
emit_program(source);
|
emit_program(source);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ typedef struct parse_rule_s ParseRule;
|
||||||
|
|
||||||
struct scope_s {
|
struct scope_s {
|
||||||
Scope *parent; /* pointer to this scopes parent to "bubble up"*/
|
Scope *parent; /* pointer to this scopes parent to "bubble up"*/
|
||||||
Scope *child; /* pointer to this scopes parent to "bubble up"*/
|
|
||||||
List *symbols; /* list of symbols that live in this scope */
|
List *symbols; /* list of symbols that live in this scope */
|
||||||
u32 locals_offset;
|
u32 locals_offset;
|
||||||
};
|
};
|
||||||
|
|
@ -45,6 +44,7 @@ struct parser_s {
|
||||||
List *scopes;
|
List *scopes;
|
||||||
Token current;
|
Token current;
|
||||||
Token previous;
|
Token previous;
|
||||||
|
Token before;
|
||||||
SymbolType current_type;
|
SymbolType current_type;
|
||||||
u32 scope_idx;
|
u32 scope_idx;
|
||||||
u32 depth;
|
u32 depth;
|
||||||
|
|
|
||||||
26
emit.h
26
emit.h
|
|
@ -14,6 +14,7 @@ typedef void (*VarEmit)(Arena *a, List *out, Symbol *sym, bool local);
|
||||||
typedef void (*MultipleEmit)(Arena *a, List *out, Symbol *sym, List* in);
|
typedef void (*MultipleEmit)(Arena *a, List *out, Symbol *sym, List* in);
|
||||||
typedef void (*I32ArgEmit)(Arena *a, List *out, i32 val);
|
typedef void (*I32ArgEmit)(Arena *a, List *out, i32 val);
|
||||||
typedef void (*U32ArgEmit)(Arena *a, List *out, u32 ptr);
|
typedef void (*U32ArgEmit)(Arena *a, List *out, u32 ptr);
|
||||||
|
typedef void (*RawEmit)(Arena *a, List *out, Symbol *sym, const char *str, u32 length);
|
||||||
|
|
||||||
typedef struct emitter_s Emitter;
|
typedef struct emitter_s Emitter;
|
||||||
struct emitter_s {
|
struct emitter_s {
|
||||||
|
|
@ -25,16 +26,16 @@ struct emitter_s {
|
||||||
SymbolSize get_size;
|
SymbolSize get_size;
|
||||||
VoidArgEmit prolog;
|
VoidArgEmit prolog;
|
||||||
VoidArgEmit epilogue;
|
VoidArgEmit epilogue;
|
||||||
VoidArgEmit emit_add;
|
U32ArgEmit emit_add;
|
||||||
VoidArgEmit emit_sub;
|
U32ArgEmit emit_sub;
|
||||||
VoidArgEmit emit_mul;
|
U32ArgEmit emit_mul;
|
||||||
VoidArgEmit emit_div;
|
U32ArgEmit emit_div;
|
||||||
VoidArgEmit emit_lt;
|
U32ArgEmit emit_lt;
|
||||||
VoidArgEmit emit_le;
|
U32ArgEmit emit_le;
|
||||||
VoidArgEmit emit_gt;
|
U32ArgEmit emit_gt;
|
||||||
VoidArgEmit emit_ge;
|
U32ArgEmit emit_ge;
|
||||||
VoidArgEmit emit_ne;
|
U32ArgEmit emit_ne;
|
||||||
VoidArgEmit emit_eq;
|
U32ArgEmit emit_eq;
|
||||||
VoidArgEmit emit_false;
|
VoidArgEmit emit_false;
|
||||||
VoidArgEmit emit_true;
|
VoidArgEmit emit_true;
|
||||||
VoidArgEmit emit_nil;
|
VoidArgEmit emit_nil;
|
||||||
|
|
@ -43,7 +44,7 @@ struct emitter_s {
|
||||||
StrArgEmit emit_nat;
|
StrArgEmit emit_nat;
|
||||||
StrArgEmit emit_real;
|
StrArgEmit emit_real;
|
||||||
StrArgEmit emit_byte;
|
StrArgEmit emit_byte;
|
||||||
StrArgEmit emit_str;
|
RawEmit emit_str;
|
||||||
VarEmit emit_type;
|
VarEmit emit_type;
|
||||||
MultipleEmit emit_array;
|
MultipleEmit emit_array;
|
||||||
SymbolEmit emit_function;
|
SymbolEmit emit_function;
|
||||||
|
|
@ -102,11 +103,12 @@ struct emitter_s {
|
||||||
VoidArgEmit emit_early_return;
|
VoidArgEmit emit_early_return;
|
||||||
VoidArgEmit emit_halt;
|
VoidArgEmit emit_halt;
|
||||||
SymbolEmit emit_deref_prolog;
|
SymbolEmit emit_deref_prolog;
|
||||||
VoidArgEmit emit_deref;
|
U32ArgEmit emit_deref;
|
||||||
VoidArgEmit emit_ref;
|
VoidArgEmit emit_ref;
|
||||||
U32ArgEmit emit_address;
|
U32ArgEmit emit_address;
|
||||||
U32ArgEmit emit_zero_block;
|
U32ArgEmit emit_zero_block;
|
||||||
StrArgEmit emit_char;
|
StrArgEmit emit_char;
|
||||||
|
StrArgEmit emit_inline_str;
|
||||||
};
|
};
|
||||||
|
|
||||||
Emitter rer_emitter(void);
|
Emitter rer_emitter(void);
|
||||||
|
|
|
||||||
161
emit/rer/emit.c
161
emit/rer/emit.c
|
|
@ -689,86 +689,87 @@ rer_emitter()
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
rer_emit_error,
|
nil,
|
||||||
rer_get_size,
|
nil,
|
||||||
rer_prolog,
|
nil,
|
||||||
rer_epilogue,
|
nil,
|
||||||
rer_emit_add,
|
nil,
|
||||||
rer_emit_sub,
|
nil,
|
||||||
rer_emit_mul,
|
nil,
|
||||||
rer_emit_div,
|
nil,
|
||||||
rer_emit_lt,
|
nil,
|
||||||
rer_emit_le,
|
nil,
|
||||||
rer_emit_gt,
|
nil,
|
||||||
rer_emit_ge,
|
nil,
|
||||||
rer_emit_ne,
|
nil,
|
||||||
rer_emit_eq,
|
nil,
|
||||||
rer_emit_false,
|
nil,
|
||||||
rer_emit_true,
|
nil,
|
||||||
rer_emit_nil,
|
nil,
|
||||||
rer_emit_void,
|
nil,
|
||||||
rer_emit_int,
|
nil,
|
||||||
rer_emit_nat,
|
nil,
|
||||||
rer_emit_real,
|
nil,
|
||||||
rer_emit_byte,
|
nil,
|
||||||
rer_emit_str,
|
nil,
|
||||||
rer_emit_type,
|
nil,
|
||||||
rer_emit_array,
|
nil,
|
||||||
rer_emit_function,
|
nil,
|
||||||
rer_emit_plex,
|
nil,
|
||||||
rer_emit_method,
|
nil,
|
||||||
rer_emit_trait,
|
nil,
|
||||||
rer_emit_const,
|
nil,
|
||||||
rer_emit_print,
|
nil,
|
||||||
rer_emit_neg,
|
nil,
|
||||||
rer_emit_not,
|
nil,
|
||||||
rer_emit_open_paren,
|
nil,
|
||||||
rer_emit_close_paren,
|
nil,
|
||||||
rer_emit_constant,
|
nil,
|
||||||
rer_emit_variable,
|
nil,
|
||||||
rer_emit_set_variable,
|
nil,
|
||||||
rer_emit_write,
|
nil,
|
||||||
rer_emit_read,
|
nil,
|
||||||
rer_emit_open,
|
nil,
|
||||||
rer_emit_close,
|
nil,
|
||||||
rer_emit_stat,
|
nil,
|
||||||
rer_emit_end_statement,
|
nil,
|
||||||
rer_emit_set_value,
|
nil,
|
||||||
rer_emit_plex_def,
|
nil,
|
||||||
rer_emit_cast_int_to_nat,
|
nil,
|
||||||
rer_emit_cast_int_to_real,
|
nil,
|
||||||
rer_emit_cast_int_to_str,
|
nil,
|
||||||
rer_emit_cast_nat_to_int,
|
nil,
|
||||||
rer_emit_cast_nat_to_real,
|
nil,
|
||||||
rer_emit_cast_nat_to_str,
|
nil,
|
||||||
rer_emit_cast_real_to_int,
|
nil,
|
||||||
rer_emit_cast_real_to_nat,
|
nil,
|
||||||
rer_emit_cast_real_to_str,
|
nil,
|
||||||
rer_emit_strbuf_init,
|
nil,
|
||||||
rer_emit_strbuf_append,
|
nil,
|
||||||
rer_emit_strbuf_to_str,
|
nil,
|
||||||
rer_emit_arena_fn_call,
|
nil,
|
||||||
rer_emit_arena_fn_return,
|
nil,
|
||||||
rer_emit_arena_fn_return_plex,
|
nil,
|
||||||
rer_emit_arena_fn_return_array,
|
nil,
|
||||||
rer_emit_arena_fn_return_strbuf,
|
nil,
|
||||||
rer_emit_cast_str_to_int,
|
nil,
|
||||||
rer_emit_cast_str_to_nat,
|
nil,
|
||||||
rer_emit_cast_str_to_real,
|
nil,
|
||||||
rer_emit_sll,
|
nil,
|
||||||
rer_emit_srl,
|
nil,
|
||||||
rer_emit_xor,
|
nil,
|
||||||
rer_emit_mod,
|
nil,
|
||||||
rer_emit_and,
|
nil,
|
||||||
rer_emit_or,
|
nil,
|
||||||
rer_emit_if,
|
nil,
|
||||||
rer_emit_patch_if,
|
nil,
|
||||||
rer_emit_patch_if_done,
|
nil,
|
||||||
rer_emit_while,
|
nil,
|
||||||
rer_emit_while_postfix,
|
nil,
|
||||||
rer_emit_patch_while,
|
nil,
|
||||||
rer_emit_early_return,
|
nil,
|
||||||
rer_emit_halt,
|
nil,
|
||||||
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
|
|
||||||
197
emit/uxn/emit.c
197
emit/uxn/emit.c
|
|
@ -595,63 +595,89 @@ uxn_epilogue(Arena *a, List *out)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
uxn_emit_add(Arena *a, List *out)
|
uxn_emit_add(Arena *a, List *out, u32 size)
|
||||||
{
|
{
|
||||||
StrBuf_append(a, out, "ADD2 ");
|
if (size > 1)
|
||||||
|
StrBuf_append(a, out, "ADD2 ");
|
||||||
|
else
|
||||||
|
StrBuf_append(a, out, "ADD ");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
uxn_emit_sub(Arena *a, List *out)
|
uxn_emit_sub(Arena *a, List *out, u32 size)
|
||||||
{
|
{
|
||||||
StrBuf_append(a, out, "SUB2 ");
|
if (size > 1)
|
||||||
|
StrBuf_append(a, out, "SUB2 ");
|
||||||
|
else
|
||||||
|
StrBuf_append(a, out, "SUB ");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
uxn_emit_mul(Arena *a, List *out)
|
uxn_emit_mul(Arena *a, List *out, u32 size)
|
||||||
{
|
{
|
||||||
StrBuf_append(a, out, "MUL2 ");
|
if (size > 1)
|
||||||
|
StrBuf_append(a, out, "MUL2 ");
|
||||||
|
else
|
||||||
|
StrBuf_append(a, out, "MUL ");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
uxn_emit_div(Arena *a, List *out)
|
uxn_emit_div(Arena *a, List *out, u32 size)
|
||||||
{
|
{
|
||||||
StrBuf_append(a, out, "DIV2 ");
|
if (size > 1)
|
||||||
|
StrBuf_append(a, out, "DIV2 ");
|
||||||
|
else
|
||||||
|
StrBuf_append(a, out, "DIV ");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
uxn_emit_lt(Arena *a, List *out)
|
uxn_emit_lt(Arena *a, List *out, u32 size)
|
||||||
{
|
{
|
||||||
StrBuf_append(a, out, "LTH2 ");
|
if (size > 1)
|
||||||
|
StrBuf_append(a, out, "LTH2 ");
|
||||||
|
else
|
||||||
|
StrBuf_append(a, out, "LTH ");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
uxn_emit_le(Arena *a, List *out)
|
uxn_emit_le(Arena *a, List *out, u32 size)
|
||||||
{
|
{
|
||||||
|
USED(size);
|
||||||
StrBuf_append(a, out, "ROT SWP LTH ?{ LTH #00 EQU JMPr } GTH JMPr ");
|
StrBuf_append(a, out, "ROT SWP LTH ?{ LTH #00 EQU JMPr } GTH JMPr ");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
uxn_emit_gt(Arena *a, List *out)
|
uxn_emit_gt(Arena *a, List *out, u32 size)
|
||||||
{
|
{
|
||||||
StrBuf_append(a, out, "GTH2 ");
|
if (size > 1)
|
||||||
|
StrBuf_append(a, out, "GTH2 ");
|
||||||
|
else
|
||||||
|
StrBuf_append(a, out, "GTH ");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
uxn_emit_ge(Arena *a, List *out)
|
uxn_emit_ge(Arena *a, List *out, u32 size)
|
||||||
{
|
{
|
||||||
|
USED(size);
|
||||||
StrBuf_append(a, out, "ROT SWP GTH ?{ GTH #00 EQU JMPr } LTH JMPr ");
|
StrBuf_append(a, out, "ROT SWP GTH ?{ GTH #00 EQU JMPr } LTH JMPr ");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
uxn_emit_ne(Arena *a, List *out)
|
uxn_emit_ne(Arena *a, List *out, u32 size)
|
||||||
{
|
{
|
||||||
StrBuf_append(a, out, "NEQ2 ");
|
if (size > 1)
|
||||||
|
StrBuf_append(a, out, "NEQ2 ");
|
||||||
|
else
|
||||||
|
StrBuf_append(a, out, "NEQ ");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
uxn_emit_eq(Arena *a, List *out)
|
uxn_emit_eq(Arena *a, List *out, u32 size)
|
||||||
{
|
{
|
||||||
StrBuf_append(a, out, "EQU2 ");
|
if (size > 1)
|
||||||
|
StrBuf_append(a, out, "EQU2 ");
|
||||||
|
else
|
||||||
|
StrBuf_append(a, out, "EQU ");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -786,46 +812,11 @@ uxn_emit_byte(Arena *a, List *out, const char *str, i32 length)
|
||||||
void
|
void
|
||||||
uxn_emit_char(Arena *a, List *out, const char *str, i32 length)
|
uxn_emit_char(Arena *a, List *out, const char *str, i32 length)
|
||||||
{
|
{
|
||||||
sprintf(uxn_temp_strbuf, "#%04x ", (char)str[0]);
|
sprintf(uxn_temp_strbuf, "#%02x ", (char)str[1]);
|
||||||
StrBuf_append(a, out, uxn_temp_strbuf);
|
StrBuf_append(a, out, uxn_temp_strbuf);
|
||||||
USED(length);
|
USED(length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
uxn_emit_str(Arena *a, List *out, const char *str, i32 length)
|
|
||||||
{
|
|
||||||
/* set a pointer to the string literal and then jump over it */
|
|
||||||
StrBuf_append(a, out, ";{ #0002 ADD2 } !{ ");
|
|
||||||
|
|
||||||
i32 i = 1;
|
|
||||||
while(i < length - 1) {
|
|
||||||
char c = str[i++];
|
|
||||||
if(c == '\\' && i < length - 1) {
|
|
||||||
switch(str[i++]) {
|
|
||||||
case 'n':
|
|
||||||
c = '\n';
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
c = '\t';
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
c = '\r';
|
|
||||||
break;
|
|
||||||
case '\\':
|
|
||||||
case '"':
|
|
||||||
case '\'':
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
i--; /* Rewind for unknown escapes */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sprintf(uxn_temp_strbuf, "%02x ", c);
|
|
||||||
StrBuf_append(a, out, uxn_temp_strbuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
StrBuf_append(a, out, "00 } ");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
uxn_emit_constant(Arena *a, List *out, Symbol *sym, bool local)
|
uxn_emit_constant(Arena *a, List *out, Symbol *sym, bool local)
|
||||||
{
|
{
|
||||||
|
|
@ -955,6 +946,77 @@ uxn_emit_array(Arena *a, List *out, Symbol *sym, List *in)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
uxn_emit_inline_str(Arena *a, List *out, const char *str, i32 length)
|
||||||
|
{
|
||||||
|
/* set a pointer to the string literal and then jump over it */
|
||||||
|
StrBuf_append(a, out, ";{ #0002 ADD2 } !{ ");
|
||||||
|
|
||||||
|
i32 i = 1;
|
||||||
|
while(i < length - 1) {
|
||||||
|
char c = str[i++];
|
||||||
|
if(c == '\\' && i < length - 1) {
|
||||||
|
switch(str[i++]) {
|
||||||
|
case 'n':
|
||||||
|
c = '\n';
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
c = '\t';
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
c = '\r';
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
case '"':
|
||||||
|
case '\'':
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
i--; /* Rewind for unknown escapes */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sprintf(uxn_temp_strbuf, "%02x ", c);
|
||||||
|
StrBuf_append(a, out, uxn_temp_strbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
StrBuf_append(a, out, "00 } ");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
uxn_emit_str(Arena *a, List *out, Symbol *sym, const char *str, u32 length)
|
||||||
|
{
|
||||||
|
sprintf(uxn_temp_strbuf, "@%.*s %04x ", sym->name_length, sym->name, length - 2);
|
||||||
|
StrBuf_append(a, out, uxn_temp_strbuf);
|
||||||
|
|
||||||
|
u32 i = 1;
|
||||||
|
while(i < length - 1) {
|
||||||
|
char c = str[i++];
|
||||||
|
if(c == '\\' && i < length - 1) {
|
||||||
|
switch(str[i++]) {
|
||||||
|
case 'n':
|
||||||
|
c = '\n';
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
c = '\t';
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
c = '\r';
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
case '"':
|
||||||
|
case '\'':
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
i--; /* Rewind for unknown escapes */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sprintf(uxn_temp_strbuf, "%02x ", c);
|
||||||
|
StrBuf_append(a, out, uxn_temp_strbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
StrBuf_append(a, out, "00 ");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
uxn_emit_deref_prolog(Arena *a, List *out, Symbol *sym)
|
uxn_emit_deref_prolog(Arena *a, List *out, Symbol *sym)
|
||||||
{
|
{
|
||||||
|
|
@ -963,9 +1025,13 @@ uxn_emit_deref_prolog(Arena *a, List *out, Symbol *sym)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
uxn_emit_deref(Arena *a, List *out)
|
uxn_emit_deref(Arena *a, List *out, u32 size)
|
||||||
{
|
{
|
||||||
StrBuf_append(a, out, "LDA2 ");
|
if (size > 1)
|
||||||
|
StrBuf_append(a, out, "LDA2 ");
|
||||||
|
else
|
||||||
|
StrBuf_append(a, out, "LDA ");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
@ -1474,5 +1540,6 @@ uxn_emitter()
|
||||||
uxn_emit_address,
|
uxn_emit_address,
|
||||||
uxn_emit_zero_block,
|
uxn_emit_zero_block,
|
||||||
uxn_emit_char,
|
uxn_emit_char,
|
||||||
|
uxn_emit_inline_str,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
lexer.h
2
lexer.h
|
|
@ -12,6 +12,7 @@ typedef enum {
|
||||||
TOKEN_RBRACE,
|
TOKEN_RBRACE,
|
||||||
TOKEN_LBRACKET,
|
TOKEN_LBRACKET,
|
||||||
TOKEN_RBRACKET,
|
TOKEN_RBRACKET,
|
||||||
|
TOKEN_DOT,
|
||||||
TOKEN_IDENTIFIER,
|
TOKEN_IDENTIFIER,
|
||||||
TOKEN_LITERAL_INT,
|
TOKEN_LITERAL_INT,
|
||||||
TOKEN_LITERAL_NAT,
|
TOKEN_LITERAL_NAT,
|
||||||
|
|
@ -76,7 +77,6 @@ typedef enum {
|
||||||
TOKEN_LT,
|
TOKEN_LT,
|
||||||
TOKEN_GTE,
|
TOKEN_GTE,
|
||||||
TOKEN_LTE,
|
TOKEN_LTE,
|
||||||
TOKEN_DOT,
|
|
||||||
TOKEN_COMMA,
|
TOKEN_COMMA,
|
||||||
TOKEN_COLON,
|
TOKEN_COLON,
|
||||||
TOKEN_CARET,
|
TOKEN_CARET,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
str msg = " damage inflicted!\n"
|
str msg = " damage inflicted!\n";
|
||||||
nat AT = 14;
|
nat AT = 14;
|
||||||
nat accuracy = 150;
|
nat accuracy = 150;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,10 +23,8 @@ function bf(str code)
|
||||||
{
|
{
|
||||||
nat mp; // memory pointer
|
nat mp; // memory pointer
|
||||||
nat ip = 0; // instruction pointer
|
nat ip = 0; // instruction pointer
|
||||||
// while (ip < code.length) {
|
while (ip < code.length) {
|
||||||
// if (ip > code.length) { return; }
|
if (ip > code.length) { return; }
|
||||||
while (ip < 106) {
|
|
||||||
if (ip < 0 or ip > 106) { return; }
|
|
||||||
if (mp > memory.length) { return; }
|
if (mp > memory.length) { return; }
|
||||||
if (code[ip] == '>') {
|
if (code[ip] == '>') {
|
||||||
mp = mp + 1;
|
mp = mp + 1;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
str msg = " damage inflicted!\n";
|
||||||
|
|
||||||
|
if (msg[1] == 'd') {
|
||||||
|
print("yes\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
print(msg.length as str);
|
||||||
|
print(msg);
|
||||||
|
halt;
|
||||||
Loading…
Reference in New Issue