From 23bb9f73e76e958826fb6660b8ba38d769571f3e Mon Sep 17 00:00:00 2001 From: zongor Date: Wed, 1 Jul 2026 23:38:27 -0700 Subject: [PATCH] wip string and array indexing, need to do setting index array yet --- arch/linux/main.c | 18 ++--- arch/web/main.c | 91 +++++++++++---------- compiler.c | 130 ++++++++++++++++++++++++------ compiler.h | 2 +- emit.h | 26 +++--- emit/rer/emit.c | 161 ++++++++++++++++++------------------- emit/uxn/emit.c | 197 +++++++++++++++++++++++++++++++--------------- lexer.h | 2 +- test/attack.ul | 2 +- test/bf.ul | 6 +- test/string.ul | 9 +++ 11 files changed, 404 insertions(+), 240 deletions(-) create mode 100755 test/string.ul diff --git a/arch/linux/main.c b/arch/linux/main.c index 9e2ba1c..467fdfa 100644 --- a/arch/linux/main.c +++ b/arch/linux/main.c @@ -3,7 +3,7 @@ #include #include -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); diff --git a/arch/web/main.c b/arch/web/main.c index 1c131da..3d091dc 100644 --- a/arch/web/main.c +++ b/arch/web/main.c @@ -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; } \ No newline at end of file diff --git a/compiler.c b/compiler.c index 331903d..c994889 100644 --- a/compiler.c +++ b/compiler.c @@ -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; diff --git a/compiler.h b/compiler.h index 2ea441e..98d3d6a 100644 --- a/compiler.h +++ b/compiler.h @@ -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; diff --git a/emit.h b/emit.h index cb70648..a067b3e 100644 --- a/emit.h +++ b/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 (*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); diff --git a/emit/rer/emit.c b/emit/rer/emit.c index 211f32c..3806c82 100644 --- a/emit/rer/emit.c +++ b/emit/rer/emit.c @@ -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, diff --git a/emit/uxn/emit.c b/emit/uxn/emit.c index 959ff8e..f383963 100644 --- a/emit/uxn/emit.c +++ b/emit/uxn/emit.c @@ -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, }; } diff --git a/lexer.h b/lexer.h index 0ab5384..030e031 100644 --- a/lexer.h +++ b/lexer.h @@ -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, diff --git a/test/attack.ul b/test/attack.ul index 0c18320..40667f6 100755 --- a/test/attack.ul +++ b/test/attack.ul @@ -1,4 +1,4 @@ -str msg = " damage inflicted!\n" +str msg = " damage inflicted!\n"; nat AT = 14; nat accuracy = 150; diff --git a/test/bf.ul b/test/bf.ul index 73861d8..789e21e 100644 --- a/test/bf.ul +++ b/test/bf.ul @@ -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; diff --git a/test/string.ul b/test/string.ul new file mode 100755 index 0000000..6536f77 --- /dev/null +++ b/test/string.ul @@ -0,0 +1,9 @@ +str msg = " damage inflicted!\n"; + +if (msg[1] == 'd') { + print("yes\n"); +} + +print(msg.length as str); +print(msg); +halt;