wip string and array indexing, need to do setting index array yet

This commit is contained in:
zongor 2026-07-01 23:38:27 -07:00
parent b8899d8bc9
commit 23bb9f73e7
11 changed files with 404 additions and 240 deletions

View File

@ -3,7 +3,7 @@
#include <stdlib.h>
#include <unistd.h>
static char *
char *
readFile(const char *path)
{
FILE *file = fopen(path, "rb");
@ -75,18 +75,18 @@ main(int argc, char **argv)
compile(&a, code, memory, &e, source);
Node *curr = code->head;
while (curr) {
char* tmp_str = node_value(curr);
while(curr) {
char *tmp_str = node_value(curr);
printf("%.*s", curr->size, tmp_str);
curr = curr->next;
}
curr = curr->next;
}
curr = memory->head;
while (curr) {
char* tmp_str = node_value(curr);
while(curr) {
char *tmp_str = node_value(curr);
printf("%.*s", curr->size, tmp_str);
curr = curr->next;
}
curr = curr->next;
}
afree(&a);
free(source);

View File

@ -6,58 +6,67 @@
#define MEM_SIZE (1 << 16)
static size_t List_size(List *list) {
size_t total = 0;
Node *curr = list->head;
while (curr) {
total += curr->size;
curr = curr->next;
}
return total;
size_t
List_size(List *list)
{
size_t total = 0;
Node *curr = list->head;
while(curr) {
total += curr->size;
curr = curr->next;
}
return total;
}
static void list2buffer(List *list, char *buffer, size_t *offset) {
Node *curr = list->head;
while (curr) {
char *tmp_str = node_value(curr);
memcpy(buffer + *offset, tmp_str, curr->size);
*offset += curr->size;
curr = curr->next;
}
void
list2buffer(List *list, char *buffer, size_t *offset)
{
Node *curr = list->head;
while(curr) {
char *tmp_str = node_value(curr);
memcpy(buffer + *offset, tmp_str, curr->size);
*offset += curr->size;
curr = curr->next;
}
}
EMSCRIPTEN_KEEPALIVE
char *undar_compile(int emitter_type, char *source) {
u8 tape[MEM_SIZE];
Arena a = {tape, 0, MEM_SIZE};
char *
undar_compile(int emitter_type, char *source)
{
u8 tape[MEM_SIZE];
Arena a = {tape, 0, MEM_SIZE};
Emitter e;
if (emitter_type == 0) {
e = rer_emitter();
} else if (emitter_type == 1) {
e = uxn_emitter();
} else {
return NULL;
}
Emitter e;
switch(emitter_type) {
case 0:
e = rer_emitter();
break;
case 1:
e = uxn_emitter();
break;
default:
return NULL;
}
List *code = List_init(&a);
List *memory = List_init(&a);
List *code = 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 mem_size = List_size(memory);
size_t total_size = code_size + mem_size + 1;
size_t code_size = List_size(code);
size_t mem_size = List_size(memory);
size_t total_size = code_size + mem_size + 1;
char *result = (char *)malloc(total_size);
if (result == NULL) return NULL;
char *result = (char *)malloc(total_size);
if(result == NULL) return NULL;
size_t offset = 0;
list2buffer(code, result, &offset);
list2buffer(memory, result, &offset);
result[offset] = '\0';
size_t offset = 0;
list2buffer(code, result, &offset);
list2buffer(memory, result, &offset);
result[offset] = '\0';
afree(&a);
afree(&a);
return result;
return result;
}

View File

@ -158,6 +158,7 @@ token_type_to_sym_type(TokenType t)
bool
advance(void)
{
parser->before = parser->previous;
parser->previous = parser->current;
for(;;) {
@ -241,11 +242,9 @@ define_function(void)
advance();
/* parse the args */
while(!check(TOKEN_LBRACE)) {
while(!match(TOKEN_RPAREN)) {
size += variable_declaration(fn);
advance();
if(check(TOKEN_LBRACE)) break;
advance();
if(match(TOKEN_RPAREN)) break;
}
if(is_type()) {
@ -332,6 +331,14 @@ define_array(void)
array->fields = strides;
}
void
define_string(void)
{
scope_add_symbol(parser->current.start,
parser->current.length,
SYMBOL_STR, 0);
}
void
build_symbol_table(char *source)
{
@ -351,6 +358,8 @@ build_symbol_table(char *source)
define_plex();
} else if(match(TOKEN_KEYWORD_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 &&
parser->current.type <= TOKEN_TYPE_PTR) {
advance();
@ -379,6 +388,28 @@ variable_declaration(Symbol *def)
SymbolType st = token_type_to_sym_type(tt);
Symbol *variable;
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) {
while(!check(TOKEN_RBRACKET)) {
@ -390,7 +421,7 @@ variable_declaration(Symbol *def)
parser->current.start,
parser->current.length);
if (!variable) {
emitter->error("cannot find array symbol", 24, parser->current.line);
emitter->error("cannot find array symbol", 25, parser->current.line);
return 0;
}
advance();
@ -416,8 +447,9 @@ variable_declaration(Symbol *def)
emitter->emit_array(arena, memory, variable, nil);
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) {
@ -468,34 +500,34 @@ binary(void)
switch(operatorType) {
case TOKEN_BANG_EQ:
emitter->emit_ne(arena, code);
emitter->emit_ne(arena, code, emitter->get_size(parser->current_type));
break;
case TOKEN_EQ_EQ:
emitter->emit_eq(arena, code);
emitter->emit_eq(arena, code, emitter->get_size(parser->current_type));
break;
case TOKEN_GT:
emitter->emit_gt(arena, code);
emitter->emit_gt(arena, code, emitter->get_size(parser->current_type));
break;
case TOKEN_GTE:
emitter->emit_ge(arena, code);
emitter->emit_ge(arena, code, emitter->get_size(parser->current_type));
break;
case TOKEN_LT:
emitter->emit_lt(arena, code);
emitter->emit_lt(arena, code, emitter->get_size(parser->current_type));
break;
case TOKEN_LTE:
emitter->emit_le(arena, code);
emitter->emit_le(arena, code, emitter->get_size(parser->current_type));
break;
case TOKEN_PLUS:
emitter->emit_add(arena, code);
emitter->emit_add(arena, code, emitter->get_size(parser->current_type));
break;
case TOKEN_MINUS:
emitter->emit_sub(arena, code);
emitter->emit_sub(arena, code, emitter->get_size(parser->current_type));
break;
case TOKEN_STAR:
emitter->emit_mul(arena, code);
emitter->emit_mul(arena, code, emitter->get_size(parser->current_type));
break;
case TOKEN_SLASH:
emitter->emit_div(arena, code);
emitter->emit_div(arena, code, emitter->get_size(parser->current_type));
break;
case TOKEN_OPERATOR_AND:
emitter->emit_and(arena, code);
@ -544,12 +576,24 @@ expression(void)
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
variable(void)
{
Symbol *sym = scope_get_symbol(parser->current_scope, parser->previous.start,
parser->previous.length);
if(sym == nil) {
return;
emitter->error(parser->previous.start, parser->previous.length,
parser->previous.line);
}
@ -559,26 +603,59 @@ variable(void)
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) {
u32 size = emitter->get_size(sym->secondary_type);
emitter->emit_deref_prolog(arena, code, sym);
if (match(TOKEN_LBRACKET)) {
expression();
emitter->emit_address(arena, code, emitter->get_size(sym->secondary_type));
emitter->emit_mul(arena, code);
emitter->emit_add(arena, code);
emitter->emit_address(arena, code, size);
emitter->emit_mul(arena, code, size);
emitter->emit_add(arena, code, size);
/* add offset of "length"*/
emitter->emit_nat(arena, code, "2", 1);
emitter->emit_add(arena, code);
emitter->emit_deref(arena, code);
emitter->emit_add(arena, code, size);
emitter->emit_deref(arena, code, size);
parser->current_type = sym->secondary_type;
while (!match(TOKEN_RBRACKET)) {
}
} else if (match(TOKEN_DOT)) {
if (sleq("length", parser->current.start, parser->current.length)) {
emitter->emit_deref(arena, code);
emitter->emit_deref(arena, code, size);
} 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();
}
return;
@ -833,7 +910,7 @@ number(void)
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
@ -884,6 +961,7 @@ ParseRule rules[] = {
/* TOKEN_RBRACE */ {nil, nil, PREC_NONE},
/* TOKEN_LBRACKET */ {nil, nil, PREC_NONE},
/* TOKEN_RBRACKET */ {nil, nil, PREC_NONE},
/* TOKEN_DOT */ {nil, dot, PREC_CALL},
/* TOKEN_IDENTIFIER */ {variable, nil, PREC_NONE},
/* TOKEN_LITERAL_INT */ {number, nil, PREC_NONE},
/* TOKEN_LITERAL_NAT */ {number, nil, PREC_NONE},
@ -948,7 +1026,6 @@ ParseRule rules[] = {
/* TOKEN_LT */ {nil, binary, PREC_COMPARISON},
/* TOKEN_GTE */ {nil, binary, PREC_COMPARISON},
/* TOKEN_LTE */ {nil, binary, PREC_COMPARISON},
/* TOKEN_DOT */ {nil, nil, PREC_NONE},
/* TOKEN_COMMA */ {nil, nil, PREC_NONE},
/* TOKEN_COLON */ {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);
parser->pass++;
parser->scope_idx = 0;
parser->depth = 0;
parser->scope_idx = 1;
emit_program(source);
return true;

View File

@ -11,7 +11,6 @@ typedef struct parse_rule_s ParseRule;
struct scope_s {
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 */
u32 locals_offset;
};
@ -45,6 +44,7 @@ struct parser_s {
List *scopes;
Token current;
Token previous;
Token before;
SymbolType current_type;
u32 scope_idx;
u32 depth;

26
emit.h
View File

@ -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 (*I32ArgEmit)(Arena *a, List *out, i32 val);
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;
struct emitter_s {
@ -25,16 +26,16 @@ struct emitter_s {
SymbolSize get_size;
VoidArgEmit prolog;
VoidArgEmit epilogue;
VoidArgEmit emit_add;
VoidArgEmit emit_sub;
VoidArgEmit emit_mul;
VoidArgEmit emit_div;
VoidArgEmit emit_lt;
VoidArgEmit emit_le;
VoidArgEmit emit_gt;
VoidArgEmit emit_ge;
VoidArgEmit emit_ne;
VoidArgEmit emit_eq;
U32ArgEmit emit_add;
U32ArgEmit emit_sub;
U32ArgEmit emit_mul;
U32ArgEmit emit_div;
U32ArgEmit emit_lt;
U32ArgEmit emit_le;
U32ArgEmit emit_gt;
U32ArgEmit emit_ge;
U32ArgEmit emit_ne;
U32ArgEmit emit_eq;
VoidArgEmit emit_false;
VoidArgEmit emit_true;
VoidArgEmit emit_nil;
@ -43,7 +44,7 @@ struct emitter_s {
StrArgEmit emit_nat;
StrArgEmit emit_real;
StrArgEmit emit_byte;
StrArgEmit emit_str;
RawEmit emit_str;
VarEmit emit_type;
MultipleEmit emit_array;
SymbolEmit emit_function;
@ -102,11 +103,12 @@ struct emitter_s {
VoidArgEmit emit_early_return;
VoidArgEmit emit_halt;
SymbolEmit emit_deref_prolog;
VoidArgEmit emit_deref;
U32ArgEmit emit_deref;
VoidArgEmit emit_ref;
U32ArgEmit emit_address;
U32ArgEmit emit_zero_block;
StrArgEmit emit_char;
StrArgEmit emit_inline_str;
};
Emitter rer_emitter(void);

View File

@ -689,86 +689,87 @@ rer_emitter()
0,
0,
0,
rer_emit_error,
rer_get_size,
rer_prolog,
rer_epilogue,
rer_emit_add,
rer_emit_sub,
rer_emit_mul,
rer_emit_div,
rer_emit_lt,
rer_emit_le,
rer_emit_gt,
rer_emit_ge,
rer_emit_ne,
rer_emit_eq,
rer_emit_false,
rer_emit_true,
rer_emit_nil,
rer_emit_void,
rer_emit_int,
rer_emit_nat,
rer_emit_real,
rer_emit_byte,
rer_emit_str,
rer_emit_type,
rer_emit_array,
rer_emit_function,
rer_emit_plex,
rer_emit_method,
rer_emit_trait,
rer_emit_const,
rer_emit_print,
rer_emit_neg,
rer_emit_not,
rer_emit_open_paren,
rer_emit_close_paren,
rer_emit_constant,
rer_emit_variable,
rer_emit_set_variable,
rer_emit_write,
rer_emit_read,
rer_emit_open,
rer_emit_close,
rer_emit_stat,
rer_emit_end_statement,
rer_emit_set_value,
rer_emit_plex_def,
rer_emit_cast_int_to_nat,
rer_emit_cast_int_to_real,
rer_emit_cast_int_to_str,
rer_emit_cast_nat_to_int,
rer_emit_cast_nat_to_real,
rer_emit_cast_nat_to_str,
rer_emit_cast_real_to_int,
rer_emit_cast_real_to_nat,
rer_emit_cast_real_to_str,
rer_emit_strbuf_init,
rer_emit_strbuf_append,
rer_emit_strbuf_to_str,
rer_emit_arena_fn_call,
rer_emit_arena_fn_return,
rer_emit_arena_fn_return_plex,
rer_emit_arena_fn_return_array,
rer_emit_arena_fn_return_strbuf,
rer_emit_cast_str_to_int,
rer_emit_cast_str_to_nat,
rer_emit_cast_str_to_real,
rer_emit_sll,
rer_emit_srl,
rer_emit_xor,
rer_emit_mod,
rer_emit_and,
rer_emit_or,
rer_emit_if,
rer_emit_patch_if,
rer_emit_patch_if_done,
rer_emit_while,
rer_emit_while_postfix,
rer_emit_patch_while,
rer_emit_early_return,
rer_emit_halt,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,
nil,

View File

@ -595,63 +595,89 @@ uxn_epilogue(Arena *a, List *out)
}
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
uxn_emit_sub(Arena *a, List *out)
{
StrBuf_append(a, out, "SUB2 ");
uxn_emit_sub(Arena *a, List *out, u32 size)
{
if (size > 1)
StrBuf_append(a, out, "SUB2 ");
else
StrBuf_append(a, out, "SUB ");
}
void
uxn_emit_mul(Arena *a, List *out)
{
StrBuf_append(a, out, "MUL2 ");
uxn_emit_mul(Arena *a, List *out, u32 size)
{
if (size > 1)
StrBuf_append(a, out, "MUL2 ");
else
StrBuf_append(a, out, "MUL ");
}
void
uxn_emit_div(Arena *a, List *out)
{
StrBuf_append(a, out, "DIV2 ");
uxn_emit_div(Arena *a, List *out, u32 size)
{
if (size > 1)
StrBuf_append(a, out, "DIV2 ");
else
StrBuf_append(a, out, "DIV ");
}
void
uxn_emit_lt(Arena *a, List *out)
{
StrBuf_append(a, out, "LTH2 ");
uxn_emit_lt(Arena *a, List *out, u32 size)
{
if (size > 1)
StrBuf_append(a, out, "LTH2 ");
else
StrBuf_append(a, out, "LTH ");
}
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 ");
}
void
uxn_emit_gt(Arena *a, List *out)
{
StrBuf_append(a, out, "GTH2 ");
uxn_emit_gt(Arena *a, List *out, u32 size)
{
if (size > 1)
StrBuf_append(a, out, "GTH2 ");
else
StrBuf_append(a, out, "GTH ");
}
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 ");
}
void
uxn_emit_ne(Arena *a, List *out)
{
StrBuf_append(a, out, "NEQ2 ");
uxn_emit_ne(Arena *a, List *out, u32 size)
{
if (size > 1)
StrBuf_append(a, out, "NEQ2 ");
else
StrBuf_append(a, out, "NEQ ");
}
void
uxn_emit_eq(Arena *a, List *out)
{
StrBuf_append(a, out, "EQU2 ");
uxn_emit_eq(Arena *a, List *out, u32 size)
{
if (size > 1)
StrBuf_append(a, out, "EQU2 ");
else
StrBuf_append(a, out, "EQU ");
}
void
@ -786,46 +812,11 @@ uxn_emit_byte(Arena *a, List *out, const char *str, i32 length)
void
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);
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
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
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
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
@ -1474,5 +1540,6 @@ uxn_emitter()
uxn_emit_address,
uxn_emit_zero_block,
uxn_emit_char,
uxn_emit_inline_str,
};
}

View File

@ -12,6 +12,7 @@ typedef enum {
TOKEN_RBRACE,
TOKEN_LBRACKET,
TOKEN_RBRACKET,
TOKEN_DOT,
TOKEN_IDENTIFIER,
TOKEN_LITERAL_INT,
TOKEN_LITERAL_NAT,
@ -76,7 +77,6 @@ typedef enum {
TOKEN_LT,
TOKEN_GTE,
TOKEN_LTE,
TOKEN_DOT,
TOKEN_COMMA,
TOKEN_COLON,
TOKEN_CARET,

View File

@ -1,4 +1,4 @@
str msg = " damage inflicted!\n"
str msg = " damage inflicted!\n";
nat AT = 14;
nat accuracy = 150;

View File

@ -23,10 +23,8 @@ function bf(str code)
{
nat mp; // memory pointer
nat ip = 0; // instruction pointer
// while (ip < code.length) {
// if (ip > code.length) { return; }
while (ip < 106) {
if (ip < 0 or ip > 106) { return; }
while (ip < code.length) {
if (ip > code.length) { return; }
if (mp > memory.length) { return; }
if (code[ip] == '>') {
mp = mp + 1;

9
test/string.ul Executable file
View File

@ -0,0 +1,9 @@
str msg = " damage inflicted!\n";
if (msg[1] == 'd') {
print("yes\n");
}
print(msg.length as str);
print(msg);
halt;