From bb764a3017397fbe86d9ef560e6f8c436f2b1770 Mon Sep 17 00:00:00 2001 From: zongor Date: Sun, 17 May 2026 23:09:57 -0700 Subject: [PATCH] WIP function calls --- common.h | 2 +- compiler.c | 124 +++++--- compiler.h | 44 +-- docs/WIP-Readme | 2 +- emit.h | 8 +- emit/rer/emit.c | 234 ++++++++------- emit/uxn/emit.c | 556 +++++++++++++++++++---------------- lexer.h | 12 +- list.c | 116 ++++---- list.h | 3 +- test/add.ul | 14 +- test/{str.c => attack.c} | 0 test/{str.tal => attack.tal} | 0 test/attack.ul | 8 + test/fib.ul | 2 +- test/str.ul | 113 ++++++- test/window.ul | 14 +- 17 files changed, 734 insertions(+), 518 deletions(-) rename test/{str.c => attack.c} (100%) rename test/{str.tal => attack.tal} (100%) create mode 100755 test/attack.ul mode change 100755 => 100644 test/str.ul diff --git a/common.h b/common.h index 6b66c3c..10912db 100644 --- a/common.h +++ b/common.h @@ -43,4 +43,4 @@ struct symbol_s { void *node_value(Node *n); -#endif \ No newline at end of file +#endif diff --git a/compiler.c b/compiler.c index 2e2e0d9..2a914b6 100644 --- a/compiler.c +++ b/compiler.c @@ -17,8 +17,10 @@ scope_push() Scope *child = aalloc(arena, sizeof(Scope)); child->symbols = List_init(arena); child->parent = parser.current_scope; + child->locals_offset = 0; parser.current_scope = child; + parser.depth++; } void @@ -26,6 +28,7 @@ scope_pop() { Scope *prev = parser.current_scope->parent; parser.current_scope = prev; + parser.depth--; } Symbol * @@ -37,7 +40,7 @@ scope_get_symbol(Scope *scope, const char *name, u32 name_length) count = scope->symbols->count; for(i = 0; i < count; i++) { Symbol *sym = List_get(scope->symbols, i); - if(sleq(sym->name, name, name_length)) return sym; + if(sym->name_length == name_length && sleq(sym->name, name, name_length)) return sym; } return scope_get_symbol(scope->parent, name, name_length); @@ -47,7 +50,12 @@ Symbol * scope_add_symbol(const char *name, u32 name_length, SymbolType type, u32 size) { Symbol *sym = scope_get_symbol(parser.current_scope, name, name_length); - if(sym != nil) return sym; + if(sym != nil) { + if(parser.pass) + return sym; + else + emitter.error("duplicate found", 14, parser.previous.line); + } sym = aalloc(arena, sizeof(Symbol)); scpy(sym->name, name, name_length); @@ -55,12 +63,16 @@ scope_add_symbol(const char *name, u32 name_length, SymbolType type, u32 size) sym->type = type; sym->secondary_type = SYMBOL_VOID; sym->size = size; - sym->ref = 0; - if(type == SYMBOL_PLEX || type == SYMBOL_METHOD || type == SYMBOL_TRAIT) { + sym->ref = parser.current_scope->locals_offset; + parser.current_scope->locals_offset += size; + if(type == SYMBOL_PLEX || type == SYMBOL_METHOD || type == SYMBOL_TRAIT || + type == SYMBOL_FUNCTION) { sym->args = List_init(arena); - sym->fields = List_init(arena); } + if(type == SYMBOL_PLEX || type == SYMBOL_METHOD || type == SYMBOL_TRAIT) + sym->fields = List_init(arena); + List_push(arena, parser.current_scope->symbols, sym, sizeof(Symbol)); return sym; @@ -80,7 +92,7 @@ is_type() } SymbolType -tokt_to_symt(TokenType t) +token_type_to_sym_type(TokenType t) { switch(t) { case TOKEN_TYPE_BOOL: @@ -153,7 +165,7 @@ match(TokenType type) void expect(TokenType type) { - if(!match(type)) { + if(!consume(type)) { emitter.error(parser.previous.start, parser.previous.length, parser.previous.line); } @@ -185,21 +197,31 @@ define_function() scope_push(); expect(TOKEN_LPAREN); + advance(); /* parse the args */ - while(!match(TOKEN_RPAREN)) size += variable_declaration(fn); + while(!check(TOKEN_LBRACE)) { + size += variable_declaration(fn); + advance(); + advance(); + } - if(!match(TOKEN_LBRACE)) { - fn->secondary_type = tokt_to_symt(parser.previous.type); + if(is_type()) { + /* get return slot */ + fn->secondary_type = token_type_to_sym_type(parser.previous.type); /* now parse the fn body */ expect(TOKEN_LBRACE); } /* get the size of all the locals for the function in the body */ - while(!match(TOKEN_RBRACE)) - if(is_type()) size += variable_declaration(fn); + while(!match(TOKEN_RBRACE)) { + if(is_type() && parser.current.type == TOKEN_IDENTIFIER) + size += variable_declaration(fn); + advance(); + } fn->size = size; + scope_pop(); } void @@ -330,6 +352,11 @@ variable() parser.previous.line); } + if (sym->type == SYMBOL_FUNCTION) { + parser.call_fn = sym; + return; + } + parser.current_type = sym->type; if(match(TOKEN_EQ)) { expression(); @@ -435,23 +462,22 @@ variable_declaration(Symbol *def) i32 size = 0; TokenType tt = parser.previous.type; Token var = parser.current; - SymbolType st = tokt_to_symt(tt); - Symbol *arg; + SymbolType st = token_type_to_sym_type(tt); + Symbol *variable; - if (st != SYMBOL_UNDEFINED) { + if(st != SYMBOL_UNDEFINED) { size = emitter.get_size(st); - arg = 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) { - List_push(arena, def->args, arg, sizeof(Symbol)); + List_push(arena, def->args, variable, sizeof(Symbol)); } else { - emitter.emit_type(st, parser.current.start, parser.current.length, - parser.depth); + emitter.emit_type(variable, parser.depth); parser.current_type = st; } } else { - /* we need to look up the type */ - + /* we need to look up the type */ + emitter.error("Not implemented", 16, parser.previous.line); } advance(); @@ -476,15 +502,11 @@ variable_declaration(Symbol *def) void declaration() { - /** - * maybe a Plex? - * lookup plex defs - * if not then - */ - if(is_type()) + if(is_type()) { variable_declaration(nil); - else + }else{ statement(); + } } void @@ -552,6 +574,33 @@ block() consume(TOKEN_RBRACE); } +void +function() +{ + Symbol *sym = scope_get_symbol(parser.current_scope, parser.previous.start, + parser.previous.length); + emitter.emit_function(sym); + while(!check(TOKEN_LBRACE)) { + advance(); + } + block(); + emitter.emit_arena_fn_return(); +} + +void call() { + if (!check(TOKEN_RPAREN)) { + do { + expression(); + } while (match(TOKEN_COMMA)); + } + consume(TOKEN_RPAREN); + + emitter.emit_arena_fn_call(parser.call_fn); + parser.current_type = parser.call_fn->secondary_type; + advance(); + return; +} + void statement() { @@ -559,6 +608,9 @@ statement() scope_push(); block(); scope_pop(); + } else if(match(TOKEN_KEYWORD_FN)) { + advance(); + function(); } else if(match(TOKEN_KEYWORD_IF)) { if_statement(); } else if(match(TOKEN_KEYWORD_WHILE)) { @@ -618,6 +670,12 @@ unary() ParseRule rules[] = { /* TOKEN_ERROR */ {nil, nil, PREC_NONE}, /* TOKEN_EOF */ {nil, nil, PREC_NONE}, + /* TOKEN_LPAREN */ {grouping, call, PREC_CALL}, + /* TOKEN_RPAREN */ {nil, nil, PREC_NONE}, + /* TOKEN_LBRACE */ {nil, nil, PREC_NONE}, + /* TOKEN_RBRACE */ {nil, nil, PREC_NONE}, + /* TOKEN_LBRACKET */ {nil, nil, PREC_NONE}, + /* TOKEN_RBRACKET */ {nil, nil, PREC_NONE}, /* TOKEN_IDENTIFIER */ {variable, nil, PREC_NONE}, /* TOKEN_LITERAL_INT */ {number, nil, PREC_NONE}, /* TOKEN_LITERAL_NAT */ {number, nil, PREC_NONE}, @@ -689,12 +747,6 @@ ParseRule rules[] = { /* TOKEN_COLON */ {nil, nil, PREC_NONE}, /* TOKEN_CARET */ {nil, nil, PREC_NONE}, /* TOKEN_SEMICOLON */ {nil, nil, PREC_NONE}, - /* TOKEN_LPAREN */ {grouping, nil, PREC_NONE}, - /* TOKEN_RPAREN */ {nil, nil, PREC_NONE}, - /* TOKEN_LBRACE */ {nil, nil, PREC_NONE}, - /* TOKEN_RBRACE */ {nil, nil, PREC_NONE}, - /* TOKEN_LBRACKET */ {nil, nil, PREC_NONE}, - /* TOKEN_RBRACKET */ {nil, nil, PREC_NONE}, /* TOKEN_ARROW_RIGHT */ {nil, nil, PREC_NONE}, /* TOKEN_SLL */ {nil, binary, PREC_NONE}, /* TOKEN_SRL */ {nil, binary, PREC_NONE}, @@ -730,7 +782,6 @@ emit_program(char *source) { init_lexer(source); advance(); - scope_push(); emitter.prolog(); @@ -746,6 +797,7 @@ compile(Arena *a, Emitter e, char *source) emitter = e; build_symbol_table(source); + parser.pass++; emit_program(source); return true; diff --git a/compiler.h b/compiler.h index 17c3b56..7bc5181 100644 --- a/compiler.h +++ b/compiler.h @@ -10,39 +10,43 @@ typedef struct parser_s Parser; typedef struct parse_rule_s ParseRule; struct scope_s { - Scope *parent; /* pointer to this scopes parent to "bubble up"*/ - List *symbols; /* list of symbols that live in this scope */ + Scope *parent; /* pointer to this scopes parent to "bubble up"*/ + List *symbols; /* list of symbols that live in this scope */ + u32 locals_offset; }; typedef enum { - PREC_NONE, - PREC_ASSIGNMENT, /* = */ - PREC_OR, /* or */ - PREC_AND, /* and */ - PREC_EQUALITY, /* == != */ - PREC_COMPARISON, /* < > <= >= */ - PREC_TERM, /* + - */ - PREC_FACTOR, /* * / */ - PREC_UNARY, /* ! - */ - PREC_CAST, /* as */ - PREC_CALL, /* . () */ - PREC_PRIMARY + PREC_NONE, + PREC_ASSIGNMENT, /* = */ + PREC_OR, /* or */ + PREC_AND, /* and */ + PREC_EQUALITY, /* == != */ + PREC_COMPARISON, /* < > <= >= */ + PREC_TERM, /* + - */ + PREC_FACTOR, /* * / */ + PREC_UNARY, /* ! - */ + PREC_CAST, /* as */ + PREC_CALL, /* . () */ + PREC_PRIMARY } Precedence; typedef void (*ParseFn)(); struct parse_rule_s { - ParseFn prefix; - ParseFn infix; - Precedence precedence; + ParseFn prefix; + ParseFn infix; + Precedence precedence; }; struct parser_s { - Scope *current_scope; + Symbol *call_fn; + Scope *current_scope; Token current; Token previous; - SymbolType current_type; - u32 depth; + SymbolType current_type; + u32 depth; + u8 pass; + bool main_found; }; bool compile(Arena *a, Emitter e, char *source); diff --git a/docs/WIP-Readme b/docs/WIP-Readme index 8821dd3..695074e 100644 --- a/docs/WIP-Readme +++ b/docs/WIP-Readme @@ -1,4 +1,4 @@ -A permacomputing & game oriented language. +A permacomputing and game oriented language designed for constrained systems. > Permacomputing is a design practice that encourages the maximization of hardware lifespan, minimization of energy usage and focuses on the use of already available computational resources. It values maintenance and refactoring of systems to keep them efficient, instead of planned obsolescence, permacomputing practices planned longevity. It is about using computation only when it has a strengthening effect on ecosystems. diff --git a/emit.h b/emit.h index cb40dab..8f42889 100644 --- a/emit.h +++ b/emit.h @@ -9,7 +9,6 @@ typedef void (*SymbolEmit)(Symbol *sym); typedef void (*ErrorMsg)(const char *str, i32 length, i32 line); typedef void (*VoidArgEmit)(); typedef void (*StrArgEmit)(const char *str, i32 length); -typedef void (*TypeVariableEmit)(SymbolType t, const char *str, i32 length, bool local); typedef void (*ConstEmit)(const char *str, i32 length, bool local); typedef void (*VarEmit)(Symbol *sym, bool local); typedef void (*I32ArgEmit)(i32 val); @@ -43,9 +42,9 @@ struct emitter_s { StrArgEmit emit_real; StrArgEmit emit_byte; StrArgEmit emit_str; - TypeVariableEmit emit_type; + VarEmit emit_type; VoidArgEmit emit_array; - VoidArgEmit emit_function; + SymbolEmit emit_function; VoidArgEmit emit_plex; VoidArgEmit emit_method; VoidArgEmit emit_trait; @@ -80,7 +79,8 @@ struct emitter_s { VoidArgEmit emit_strbuf_init; VoidArgEmit emit_strbuf_append; VoidArgEmit emit_strbuf_to_str; - VoidArgEmit emit_arena_fn_call; + SymbolEmit emit_arena_fn_call; + VoidArgEmit emit_arena_fn_return; VoidArgEmit emit_arena_fn_return_plex; VoidArgEmit emit_arena_fn_return_array; VoidArgEmit emit_arena_fn_return_strbuf; diff --git a/emit/rer/emit.c b/emit/rer/emit.c index c19e726..3432b7c 100644 --- a/emit/rer/emit.c +++ b/emit/rer/emit.c @@ -1,12 +1,12 @@ - #include "../../emit.h" #include #include + void rer_emit_error(const char *str, i32 length, i32 line) { - printf("Error at line: %d > %.*s\n ", line, length, str); + fprintf(stderr, "\n===\nError at line: %d > %.*s\n===\n", line, length, str); exit(1); } @@ -28,7 +28,6 @@ rer_epilogue() printf("BRK\n\n"); } - void rer_emit_add() { @@ -128,122 +127,104 @@ u32 rer_get_size(SymbolType t) { switch(t) { - case SYMBOL_BOOL: return 1; - case SYMBOL_BYTE: return 1; - case SYMBOL_INT: return 2; - case SYMBOL_NAT: return 2; - case SYMBOL_REAL: return 2; - case SYMBOL_STR: return 2; - case SYMBOL_U8: return 1; - case SYMBOL_I8: return 1; - case SYMBOL_I16: return 2; - case SYMBOL_U16: return 2; - case SYMBOL_I32: return 4; - case SYMBOL_U32: return 4; - case SYMBOL_F32: return 4; - default: break; + case SYMBOL_BOOL: + return 1; + case SYMBOL_BYTE: + return 1; + case SYMBOL_INT: + return 2; + case SYMBOL_NAT: + return 2; + case SYMBOL_REAL: + return 2; + case SYMBOL_STR: + return 2; + case SYMBOL_U8: + return 1; + case SYMBOL_I8: + return 1; + case SYMBOL_I16: + return 2; + case SYMBOL_U16: + return 2; + case SYMBOL_I32: + return 4; + case SYMBOL_U32: + return 4; + case SYMBOL_F32: + return 4; + default: + break; } return 0; } void -rer_emit_primitive_type(SymbolType t, const char *str, i32 length, bool local) +rer_emit_primitive_type(Symbol *sym, bool local) { - switch(t) { - case SYMBOL_BOOL: { - if(local) - printf("!{ &%.*s $2 } ", length, str); + if(local) + if(sym->ref) + printf("STH2kr #%04x ADD2 STA2\n", sym->ref); else - printf("!{ @%.*s $2 } ", length, str); - break; - } - case SYMBOL_BYTE: { - if(local) - printf("!{ &%.*s $1 } ", length, str); - else - printf("!{ @%.*s $1 } ", length, str); - break; - } - case SYMBOL_INT: { - if(local) - printf("!{ &%.*s $2 } ", length, str); - else - printf("!{ @%.*s $2 } ", length, str); - break; - } - case SYMBOL_NAT: { - if(local) - printf("!{ &%.*s $2 } ", length, str); - else - printf("!{ @%.*s $2 } ", length, str); - break; - } - case SYMBOL_REAL: { - if(local) - printf("!{ &%.*s $2 } ", length, str); - else - printf("!{ @%.*s $2 } ", length, str); - break; - } - case SYMBOL_STR: { - if(local) - printf("!{ &%.*s $2 } ", length, str); - else - printf("!{ @%.*s $2 } ", length, str); - break; - } - case SYMBOL_U8: { - if(local) - printf("!{ &%.*s $1 } ", length, str); - else - printf("!{ @%.*s $1 } ", length, str); - break; - } - case SYMBOL_I8: { - if(local) - printf("!{ &%.*s $1 } ", length, str); - else - printf("!{ @%.*s $1 } ", length, str); - break; - } - case SYMBOL_I16: { - if(local) - printf("!{ &%.*s $2 } ", length, str); - else - printf("!{ @%.*s $2 } ", length, str); - break; - } - case SYMBOL_U16: { - if(local) - printf("!{ &%.*s $2 } ", length, str); - else - printf("!{ @%.*s $2 } ", length, str); - break; - } - case SYMBOL_I32: { - if(local) - printf("!{ &%.*s $4 } ", length, str); - else - printf("!{ @%.*s $4 } ", length, str); - break; - } - case SYMBOL_U32: { - if(local) - printf("!{ &%.*s $4 } ", length, str); - else - printf("!{ @%.*s $4 } ", length, str); - break; - } - case SYMBOL_F32: { - if(local) - printf("!{ &%.*s $4 } ", length, str); - else - printf("!{ @%.*s $4 } ", length, str); - break; - } - default: break; - } + printf("STH2kr STA2\n"); + else + switch(sym->type) { + case SYMBOL_BOOL: { + printf("!{ @%.*s $2 } ", sym->name_length, sym->name); + break; + } + case SYMBOL_BYTE: { + printf("!{ @%.*s $1 } ", sym->name_length, sym->name); + break; + } + case SYMBOL_INT: { + printf("!{ @%.*s $2 } ", sym->name_length, sym->name); + break; + } + case SYMBOL_NAT: { + printf("!{ @%.*s $2 } ", sym->name_length, sym->name); + break; + } + case SYMBOL_REAL: { + printf("!{ @%.*s $2 } ", sym->name_length, sym->name); + break; + } + case SYMBOL_STR: { + printf("!{ @%.*s $2 } ", sym->name_length, sym->name); + break; + } + case SYMBOL_U8: { + printf("!{ @%.*s $1 } ", sym->name_length, sym->name); + break; + } + case SYMBOL_I8: { + printf("!{ @%.*s $1 } ", sym->name_length, sym->name); + break; + } + case SYMBOL_I16: { + printf("!{ @%.*s $2 } ", sym->name_length, sym->name); + break; + } + case SYMBOL_U16: { + printf("!{ @%.*s $2 } ", sym->name_length, sym->name); + break; + } + case SYMBOL_I32: { + printf("!{ @%.*s $4 } ", sym->name_length, sym->name); + break; + } + case SYMBOL_U32: { + printf("!{ @%.*s $4 } ", sym->name_length, sym->name); + break; + } + case SYMBOL_F32: { + printf("!{ @%.*s $4 } ", sym->name_length, sym->name); + break; + } + default: + break; + } } void rer_emit_int(const char *str, i32 length) @@ -303,8 +284,21 @@ rer_emit_array() } void -rer_emit_function() +rer_emit_function(Symbol *sym) { + USED(sym); +} + +void +rer_emit_arena_fn_return() +{ + printf("&return\n\t\tPOP2r JMP2r\n\n"); +} + +void +rer_emit_arena_fn_call(Symbol *sym) +{ + USED(sym); } void @@ -353,7 +347,10 @@ void rer_emit_variable(Symbol *sym, bool local) { if(local) - printf(",/%.*s LDR2 ", sym->name_length, sym->name); + if(sym->ref) + printf("STH2kr #%04x ADD2 LDA2 ", sym->ref); + else + printf("STH2kr LDA2 "); else printf(";%.*s LDA2 ", sym->name_length, sym->name); } @@ -362,7 +359,10 @@ void rer_emit_set_variable(Symbol *sym, bool local) { if(local) - printf(",/%.*s STR2 ", sym->name_length, sym->name); + if(sym->ref) + printf("STH2kr #%04x ADD2 STA2 ", sym->ref); + else + printf("STH2kr STA2 "); else printf(";%.*s STA2 ", sym->name_length, sym->name); } @@ -477,11 +477,6 @@ rer_emit_strbuf_to_str() { } -void -rer_emit_arena_fn_call() -{ -} - void rer_emit_arena_fn_return_plex() { @@ -656,6 +651,7 @@ rer_emitter() 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, diff --git a/emit/uxn/emit.c b/emit/uxn/emit.c index cdcb8df..d3207cb 100644 --- a/emit/uxn/emit.c +++ b/emit/uxn/emit.c @@ -7,148 +7,171 @@ #define UXN_OP_K (1 << 7) enum uxn_opcode { - /* Stack I */ /* Logic */ /* Memory I */ /* Arithmetic*/ - BRK = 0x00, EQU = 0x08, LDZ = 0x10, ADD = 0x18, - INC = 0x01, NEQ = 0x09, STZ = 0x11, SUB = 0x19, - POP = 0x02, GTH = 0x0A, LDR = 0x12, MUL = 0x1A, - NIP = 0x03, LTH = 0x0B, STR = 0x13, DIV = 0x1B, - /* Stack II */ /* Stash */ /* Memory II */ /* Bitwise */ - SWP = 0x04, JMP = 0x0C, LDA = 0x14, AND = 0x1C, - ROT = 0x05, JCN = 0x0D, STA = 0x15, ORA = 0x1D, - DUP = 0x06, JSR = 0x0E, DEI = 0x16, EOR = 0x1E, - OVR = 0x07, STH = 0x0F, DEO = 0x17, SFT = 0x1F, - - LIT = 0x80, JCI = 0x20, JMI = 0x40, JSI = 0x60, + BRK = 0x00, + EQU = 0x08, + LDZ = 0x10, + ADD = 0x18, + INC = 0x01, + NEQ = 0x09, + STZ = 0x11, + SUB = 0x19, + POP = 0x02, + GTH = 0x0A, + LDR = 0x12, + MUL = 0x1A, + NIP = 0x03, + LTH = 0x0B, + STR = 0x13, + DIV = 0x1B, + SWP = 0x04, + JMP = 0x0C, + LDA = 0x14, + AND = 0x1C, + ROT = 0x05, + JCN = 0x0D, + STA = 0x15, + ORA = 0x1D, + DUP = 0x06, + JSR = 0x0E, + DEI = 0x16, + EOR = 0x1E, + OVR = 0x07, + STH = 0x0F, + DEO = 0x17, + SFT = 0x1F, + LIT = 0x80, + JCI = 0x20, + JMI = 0x40, + JSI = 0x60, }; unsigned char __lib_undar[] = { - 0x40, 0x73, 0x65, 0x78, 0x74, 0x0a, 0x20, 0x20, 0x23, 0x38, 0x30, 0x20, - 0x41, 0x4e, 0x44, 0x6b, 0x20, 0x45, 0x51, 0x55, 0x20, 0x23, 0x66, 0x66, - 0x20, 0x4d, 0x55, 0x4c, 0x20, 0x53, 0x57, 0x50, 0x20, 0x4a, 0x4d, 0x50, - 0x32, 0x72, 0x0a, 0x0a, 0x40, 0x61, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, - 0x20, 0x28, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2a, 0x20, 0x2d, 0x2d, 0x20, - 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2a, 0x20, 0x29, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x4f, 0x56, 0x52, 0x32, 0x72, 0x20, 0x4c, 0x49, 0x54, 0x32, - 0x72, 0x20, 0x30, 0x30, 0x30, 0x34, 0x20, 0x53, 0x55, 0x42, 0x32, 0x72, - 0x20, 0x53, 0x54, 0x48, 0x32, 0x6b, 0x72, 0x20, 0x49, 0x4e, 0x43, 0x32, - 0x20, 0x49, 0x4e, 0x43, 0x32, 0x20, 0x53, 0x54, 0x41, 0x32, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x3b, 0x6d, 0x65, 0x6d, 0x5f, 0x6c, 0x65, 0x6e, 0x67, - 0x74, 0x68, 0x5f, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x20, 0x53, 0x54, 0x48, - 0x32, 0x6b, 0x72, 0x20, 0x53, 0x54, 0x41, 0x32, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x3b, 0x6d, 0x65, 0x6d, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, - 0x5f, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x6b, 0x20, 0x53, 0x54, 0x48, 0x32, - 0x6b, 0x72, 0x20, 0x49, 0x4e, 0x43, 0x32, 0x20, 0x49, 0x4e, 0x43, 0x32, - 0x20, 0x4c, 0x44, 0x41, 0x32, 0x20, 0x41, 0x44, 0x44, 0x32, 0x20, 0x53, - 0x57, 0x50, 0x32, 0x20, 0x53, 0x54, 0x41, 0x32, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x3b, 0x6d, 0x65, 0x6d, 0x5f, 0x20, 0x53, 0x54, 0x48, 0x32, 0x6b, - 0x72, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x20, 0x41, 0x44, 0x44, 0x32, 0x20, - 0x21, 0x26, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x23, 0x30, 0x30, 0x30, 0x30, 0x0a, 0x0a, 0x20, 0x20, 0x26, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x50, 0x4f, - 0x50, 0x32, 0x72, 0x20, 0x4a, 0x4d, 0x50, 0x32, 0x72, 0x0a, 0x0a, 0x40, - 0x61, 0x6d, 0x63, 0x70, 0x79, 0x5f, 0x20, 0x28, 0x20, 0x6c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x2a, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x2a, 0x20, 0x2d, - 0x2d, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2a, 0x20, 0x29, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x4f, 0x56, 0x52, 0x32, 0x72, 0x20, 0x4c, 0x49, - 0x54, 0x32, 0x72, 0x20, 0x30, 0x30, 0x30, 0x38, 0x20, 0x53, 0x55, 0x42, - 0x32, 0x72, 0x20, 0x53, 0x54, 0x48, 0x32, 0x6b, 0x72, 0x20, 0x23, 0x30, - 0x30, 0x30, 0x36, 0x20, 0x41, 0x44, 0x44, 0x32, 0x20, 0x53, 0x54, 0x41, - 0x32, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x53, 0x54, 0x48, 0x32, 0x6b, 0x72, - 0x20, 0x23, 0x30, 0x30, 0x30, 0x34, 0x20, 0x41, 0x44, 0x44, 0x32, 0x20, - 0x53, 0x54, 0x41, 0x32, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x53, 0x54, 0x48, - 0x32, 0x6b, 0x72, 0x20, 0x23, 0x30, 0x30, 0x30, 0x34, 0x20, 0x41, 0x44, - 0x44, 0x32, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x20, 0x61, 0x61, 0x6c, 0x6c, - 0x6f, 0x63, 0x5f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x53, 0x54, 0x48, 0x32, - 0x6b, 0x72, 0x20, 0x49, 0x4e, 0x43, 0x32, 0x20, 0x49, 0x4e, 0x43, 0x32, - 0x20, 0x53, 0x54, 0x41, 0x32, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x23, 0x30, - 0x30, 0x30, 0x30, 0x20, 0x53, 0x54, 0x48, 0x32, 0x6b, 0x72, 0x20, 0x53, - 0x54, 0x41, 0x32, 0x0a, 0x0a, 0x20, 0x20, 0x26, 0x62, 0x65, 0x67, 0x69, - 0x6e, 0x2e, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x53, 0x54, 0x48, 0x32, - 0x6b, 0x72, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x20, 0x53, 0x54, 0x48, 0x32, - 0x6b, 0x72, 0x20, 0x23, 0x30, 0x30, 0x30, 0x34, 0x20, 0x41, 0x44, 0x44, - 0x32, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x20, 0x4c, 0x54, 0x48, 0x32, 0x20, - 0x23, 0x30, 0x30, 0x20, 0x45, 0x51, 0x55, 0x20, 0x3f, 0x26, 0x62, 0x72, - 0x65, 0x61, 0x6b, 0x2e, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x53, 0x54, - 0x48, 0x32, 0x6b, 0x72, 0x20, 0x23, 0x30, 0x30, 0x30, 0x36, 0x20, 0x41, - 0x44, 0x44, 0x32, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x20, 0x53, 0x54, 0x48, - 0x32, 0x6b, 0x72, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x20, 0x41, 0x44, 0x44, - 0x32, 0x20, 0x4c, 0x44, 0x41, 0x20, 0x73, 0x65, 0x78, 0x74, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x53, 0x54, 0x48, 0x32, 0x6b, 0x72, 0x20, 0x49, 0x4e, - 0x43, 0x32, 0x20, 0x49, 0x4e, 0x43, 0x32, 0x20, 0x4c, 0x44, 0x41, 0x32, - 0x20, 0x53, 0x54, 0x48, 0x32, 0x6b, 0x72, 0x20, 0x4c, 0x44, 0x41, 0x32, - 0x20, 0x41, 0x44, 0x44, 0x32, 0x20, 0x53, 0x54, 0x41, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x50, 0x4f, 0x50, 0x0a, 0x0a, 0x20, 0x20, 0x26, 0x63, 0x6f, - 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x2e, 0x31, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x53, 0x54, 0x48, 0x32, 0x6b, 0x72, 0x20, 0x4c, 0x44, 0x41, 0x32, - 0x6b, 0x20, 0x49, 0x4e, 0x43, 0x32, 0x6b, 0x20, 0x52, 0x4f, 0x54, 0x32, - 0x20, 0x53, 0x54, 0x41, 0x32, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x50, 0x4f, - 0x50, 0x32, 0x20, 0x21, 0x26, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x2e, 0x31, - 0x0a, 0x0a, 0x20, 0x20, 0x26, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x2e, 0x31, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x53, 0x54, 0x48, 0x32, 0x6b, 0x72, 0x20, - 0x49, 0x4e, 0x43, 0x32, 0x20, 0x49, 0x4e, 0x43, 0x32, 0x20, 0x4c, 0x44, - 0x41, 0x32, 0x20, 0x21, 0x26, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x23, 0x30, 0x30, 0x30, 0x30, 0x0a, 0x0a, 0x20, - 0x20, 0x26, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x50, 0x4f, 0x50, 0x32, 0x72, 0x20, 0x4a, 0x4d, 0x50, 0x32, 0x72, - 0x0a, 0x0a, 0x40, 0x6e, 0x61, 0x74, 0x5f, 0x74, 0x6f, 0x5f, 0x73, 0x74, - 0x72, 0x5f, 0x20, 0x28, 0x20, 0x6e, 0x2a, 0x20, 0x2d, 0x2d, 0x20, 0x72, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2a, 0x20, 0x29, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x4f, 0x56, 0x52, 0x32, 0x72, 0x20, 0x4c, 0x49, 0x54, 0x32, 0x72, - 0x20, 0x30, 0x30, 0x30, 0x61, 0x20, 0x53, 0x55, 0x42, 0x32, 0x72, 0x20, - 0x53, 0x54, 0x48, 0x32, 0x6b, 0x72, 0x20, 0x23, 0x30, 0x30, 0x30, 0x38, - 0x20, 0x41, 0x44, 0x44, 0x32, 0x20, 0x53, 0x54, 0x41, 0x32, 0x0a, 0x20, - 0x20, 0x20, 0x20, 0x23, 0x30, 0x30, 0x30, 0x35, 0x20, 0x53, 0x54, 0x48, - 0x32, 0x6b, 0x72, 0x20, 0x53, 0x54, 0x41, 0x32, 0x0a, 0x0a, 0x20, 0x20, - 0x26, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x2e, 0x31, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x53, 0x54, 0x48, 0x32, 0x6b, 0x72, 0x20, 0x23, 0x30, 0x30, 0x30, - 0x38, 0x20, 0x41, 0x44, 0x44, 0x32, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x20, - 0x23, 0x30, 0x30, 0x30, 0x61, 0x20, 0x4f, 0x56, 0x52, 0x32, 0x20, 0x4f, - 0x56, 0x52, 0x32, 0x20, 0x44, 0x49, 0x56, 0x32, 0x20, 0x4d, 0x55, 0x4c, - 0x32, 0x20, 0x53, 0x55, 0x42, 0x32, 0x20, 0x23, 0x30, 0x30, 0x33, 0x30, - 0x20, 0x41, 0x44, 0x44, 0x32, 0x20, 0x53, 0x54, 0x48, 0x32, 0x6b, 0x72, - 0x20, 0x49, 0x4e, 0x43, 0x32, 0x20, 0x49, 0x4e, 0x43, 0x32, 0x20, 0x53, - 0x54, 0x48, 0x32, 0x6b, 0x72, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x6b, 0x20, - 0x23, 0x30, 0x30, 0x30, 0x31, 0x20, 0x53, 0x55, 0x42, 0x32, 0x20, 0x53, - 0x57, 0x50, 0x32, 0x20, 0x53, 0x54, 0x41, 0x32, 0x6b, 0x0a, 0x20, 0x20, - 0x20, 0x20, 0x50, 0x4f, 0x50, 0x32, 0x20, 0x41, 0x44, 0x44, 0x32, 0x20, - 0x53, 0x54, 0x41, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x50, 0x4f, 0x50, 0x20, - 0x53, 0x54, 0x48, 0x32, 0x6b, 0x72, 0x20, 0x23, 0x30, 0x30, 0x30, 0x38, - 0x20, 0x41, 0x44, 0x44, 0x32, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x6b, 0x20, - 0x23, 0x30, 0x30, 0x30, 0x61, 0x20, 0x44, 0x49, 0x56, 0x32, 0x20, 0x53, - 0x57, 0x50, 0x32, 0x20, 0x53, 0x54, 0x41, 0x32, 0x0a, 0x0a, 0x20, 0x20, - 0x26, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x2e, 0x31, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x23, 0x30, 0x30, 0x30, 0x30, 0x20, 0x53, 0x54, - 0x48, 0x32, 0x6b, 0x72, 0x20, 0x23, 0x30, 0x30, 0x30, 0x38, 0x20, 0x41, - 0x44, 0x44, 0x32, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x20, 0x4c, 0x54, 0x48, - 0x32, 0x20, 0x3f, 0x26, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x2e, 0x31, 0x0a, - 0x0a, 0x20, 0x20, 0x26, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x2e, 0x31, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x23, 0x30, 0x30, 0x30, 0x35, 0x20, 0x53, 0x54, - 0x48, 0x32, 0x6b, 0x72, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x20, 0x53, 0x55, - 0x42, 0x32, 0x20, 0x53, 0x54, 0x48, 0x32, 0x6b, 0x72, 0x20, 0x49, 0x4e, - 0x43, 0x32, 0x20, 0x49, 0x4e, 0x43, 0x32, 0x20, 0x53, 0x54, 0x48, 0x32, - 0x6b, 0x72, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x20, 0x41, 0x44, 0x44, 0x32, - 0x20, 0x61, 0x6d, 0x63, 0x70, 0x79, 0x5f, 0x0a, 0x20, 0x20, 0x20, 0x20, - 0x21, 0x26, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x23, 0x30, 0x30, 0x30, 0x30, 0x0a, 0x0a, 0x20, 0x20, 0x26, 0x72, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x50, 0x4f, - 0x50, 0x32, 0x72, 0x20, 0x4a, 0x4d, 0x50, 0x32, 0x72, 0x0a, 0x0a, 0x40, - 0x73, 0x74, 0x72, 0x2f, 0x3c, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x3e, 0x20, - 0x28, 0x20, 0x73, 0x74, 0x72, 0x2a, 0x20, 0x2d, 0x2d, 0x20, 0x29, 0x0a, - 0x20, 0x20, 0x20, 0x20, 0x4c, 0x44, 0x41, 0x6b, 0x20, 0x44, 0x55, 0x50, - 0x20, 0x3f, 0x7b, 0x20, 0x50, 0x4f, 0x50, 0x20, 0x50, 0x4f, 0x50, 0x32, - 0x20, 0x4a, 0x4d, 0x50, 0x32, 0x72, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x23, 0x31, 0x38, 0x20, 0x44, 0x45, 0x4f, 0x0a, 0x20, 0x20, 0x20, - 0x20, 0x49, 0x4e, 0x43, 0x32, 0x20, 0x21, 0x2f, 0x3c, 0x70, 0x72, 0x69, - 0x6e, 0x74, 0x3e, 0x0a, 0x0a, 0x40, 0x6d, 0x65, 0x6d, 0x5f, 0x6c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x20, 0x23, 0x30, 0x30, 0x30, 0x30, 0x0a, - 0x40, 0x6d, 0x65, 0x6d, 0x5f -}; + 0x40, 0x73, 0x65, 0x78, 0x74, 0x0a, 0x20, 0x20, 0x23, 0x38, 0x30, 0x20, + 0x41, 0x4e, 0x44, 0x6b, 0x20, 0x45, 0x51, 0x55, 0x20, 0x23, 0x66, 0x66, + 0x20, 0x4d, 0x55, 0x4c, 0x20, 0x53, 0x57, 0x50, 0x20, 0x4a, 0x4d, 0x50, + 0x32, 0x72, 0x0a, 0x0a, 0x40, 0x61, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, + 0x20, 0x28, 0x20, 0x73, 0x69, 0x7a, 0x65, 0x2a, 0x20, 0x2d, 0x2d, 0x20, + 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2a, 0x20, 0x29, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x4f, 0x56, 0x52, 0x32, 0x72, 0x20, 0x4c, 0x49, 0x54, 0x32, + 0x72, 0x20, 0x30, 0x30, 0x30, 0x34, 0x20, 0x53, 0x55, 0x42, 0x32, 0x72, + 0x20, 0x53, 0x54, 0x48, 0x32, 0x6b, 0x72, 0x20, 0x49, 0x4e, 0x43, 0x32, + 0x20, 0x49, 0x4e, 0x43, 0x32, 0x20, 0x53, 0x54, 0x41, 0x32, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x3b, 0x6d, 0x65, 0x6d, 0x5f, 0x6c, 0x65, 0x6e, 0x67, + 0x74, 0x68, 0x5f, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x20, 0x53, 0x54, 0x48, + 0x32, 0x6b, 0x72, 0x20, 0x53, 0x54, 0x41, 0x32, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x3b, 0x6d, 0x65, 0x6d, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, + 0x5f, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x6b, 0x20, 0x53, 0x54, 0x48, 0x32, + 0x6b, 0x72, 0x20, 0x49, 0x4e, 0x43, 0x32, 0x20, 0x49, 0x4e, 0x43, 0x32, + 0x20, 0x4c, 0x44, 0x41, 0x32, 0x20, 0x41, 0x44, 0x44, 0x32, 0x20, 0x53, + 0x57, 0x50, 0x32, 0x20, 0x53, 0x54, 0x41, 0x32, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x3b, 0x6d, 0x65, 0x6d, 0x5f, 0x20, 0x53, 0x54, 0x48, 0x32, 0x6b, + 0x72, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x20, 0x41, 0x44, 0x44, 0x32, 0x20, + 0x21, 0x26, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x23, 0x30, 0x30, 0x30, 0x30, 0x0a, 0x0a, 0x20, 0x20, 0x26, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x50, 0x4f, + 0x50, 0x32, 0x72, 0x20, 0x4a, 0x4d, 0x50, 0x32, 0x72, 0x0a, 0x0a, 0x40, + 0x61, 0x6d, 0x63, 0x70, 0x79, 0x5f, 0x20, 0x28, 0x20, 0x6c, 0x65, 0x6e, + 0x67, 0x74, 0x68, 0x2a, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x2a, 0x20, 0x2d, + 0x2d, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2a, 0x20, 0x29, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x4f, 0x56, 0x52, 0x32, 0x72, 0x20, 0x4c, 0x49, + 0x54, 0x32, 0x72, 0x20, 0x30, 0x30, 0x30, 0x38, 0x20, 0x53, 0x55, 0x42, + 0x32, 0x72, 0x20, 0x53, 0x54, 0x48, 0x32, 0x6b, 0x72, 0x20, 0x23, 0x30, + 0x30, 0x30, 0x36, 0x20, 0x41, 0x44, 0x44, 0x32, 0x20, 0x53, 0x54, 0x41, + 0x32, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x53, 0x54, 0x48, 0x32, 0x6b, 0x72, + 0x20, 0x23, 0x30, 0x30, 0x30, 0x34, 0x20, 0x41, 0x44, 0x44, 0x32, 0x20, + 0x53, 0x54, 0x41, 0x32, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x53, 0x54, 0x48, + 0x32, 0x6b, 0x72, 0x20, 0x23, 0x30, 0x30, 0x30, 0x34, 0x20, 0x41, 0x44, + 0x44, 0x32, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x20, 0x61, 0x61, 0x6c, 0x6c, + 0x6f, 0x63, 0x5f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x53, 0x54, 0x48, 0x32, + 0x6b, 0x72, 0x20, 0x49, 0x4e, 0x43, 0x32, 0x20, 0x49, 0x4e, 0x43, 0x32, + 0x20, 0x53, 0x54, 0x41, 0x32, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x23, 0x30, + 0x30, 0x30, 0x30, 0x20, 0x53, 0x54, 0x48, 0x32, 0x6b, 0x72, 0x20, 0x53, + 0x54, 0x41, 0x32, 0x0a, 0x0a, 0x20, 0x20, 0x26, 0x62, 0x65, 0x67, 0x69, + 0x6e, 0x2e, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x53, 0x54, 0x48, 0x32, + 0x6b, 0x72, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x20, 0x53, 0x54, 0x48, 0x32, + 0x6b, 0x72, 0x20, 0x23, 0x30, 0x30, 0x30, 0x34, 0x20, 0x41, 0x44, 0x44, + 0x32, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x20, 0x4c, 0x54, 0x48, 0x32, 0x20, + 0x23, 0x30, 0x30, 0x20, 0x45, 0x51, 0x55, 0x20, 0x3f, 0x26, 0x62, 0x72, + 0x65, 0x61, 0x6b, 0x2e, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x53, 0x54, + 0x48, 0x32, 0x6b, 0x72, 0x20, 0x23, 0x30, 0x30, 0x30, 0x36, 0x20, 0x41, + 0x44, 0x44, 0x32, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x20, 0x53, 0x54, 0x48, + 0x32, 0x6b, 0x72, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x20, 0x41, 0x44, 0x44, + 0x32, 0x20, 0x4c, 0x44, 0x41, 0x20, 0x73, 0x65, 0x78, 0x74, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x53, 0x54, 0x48, 0x32, 0x6b, 0x72, 0x20, 0x49, 0x4e, + 0x43, 0x32, 0x20, 0x49, 0x4e, 0x43, 0x32, 0x20, 0x4c, 0x44, 0x41, 0x32, + 0x20, 0x53, 0x54, 0x48, 0x32, 0x6b, 0x72, 0x20, 0x4c, 0x44, 0x41, 0x32, + 0x20, 0x41, 0x44, 0x44, 0x32, 0x20, 0x53, 0x54, 0x41, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x50, 0x4f, 0x50, 0x0a, 0x0a, 0x20, 0x20, 0x26, 0x63, 0x6f, + 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x2e, 0x31, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x53, 0x54, 0x48, 0x32, 0x6b, 0x72, 0x20, 0x4c, 0x44, 0x41, 0x32, + 0x6b, 0x20, 0x49, 0x4e, 0x43, 0x32, 0x6b, 0x20, 0x52, 0x4f, 0x54, 0x32, + 0x20, 0x53, 0x54, 0x41, 0x32, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x50, 0x4f, + 0x50, 0x32, 0x20, 0x21, 0x26, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x2e, 0x31, + 0x0a, 0x0a, 0x20, 0x20, 0x26, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x2e, 0x31, + 0x0a, 0x20, 0x20, 0x20, 0x20, 0x53, 0x54, 0x48, 0x32, 0x6b, 0x72, 0x20, + 0x49, 0x4e, 0x43, 0x32, 0x20, 0x49, 0x4e, 0x43, 0x32, 0x20, 0x4c, 0x44, + 0x41, 0x32, 0x20, 0x21, 0x26, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x23, 0x30, 0x30, 0x30, 0x30, 0x0a, 0x0a, 0x20, + 0x20, 0x26, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x50, 0x4f, 0x50, 0x32, 0x72, 0x20, 0x4a, 0x4d, 0x50, 0x32, 0x72, + 0x0a, 0x0a, 0x40, 0x6e, 0x61, 0x74, 0x5f, 0x74, 0x6f, 0x5f, 0x73, 0x74, + 0x72, 0x5f, 0x20, 0x28, 0x20, 0x6e, 0x2a, 0x20, 0x2d, 0x2d, 0x20, 0x72, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2a, 0x20, 0x29, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x4f, 0x56, 0x52, 0x32, 0x72, 0x20, 0x4c, 0x49, 0x54, 0x32, 0x72, + 0x20, 0x30, 0x30, 0x30, 0x61, 0x20, 0x53, 0x55, 0x42, 0x32, 0x72, 0x20, + 0x53, 0x54, 0x48, 0x32, 0x6b, 0x72, 0x20, 0x23, 0x30, 0x30, 0x30, 0x38, + 0x20, 0x41, 0x44, 0x44, 0x32, 0x20, 0x53, 0x54, 0x41, 0x32, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x23, 0x30, 0x30, 0x30, 0x35, 0x20, 0x53, 0x54, 0x48, + 0x32, 0x6b, 0x72, 0x20, 0x53, 0x54, 0x41, 0x32, 0x0a, 0x0a, 0x20, 0x20, + 0x26, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x2e, 0x31, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x53, 0x54, 0x48, 0x32, 0x6b, 0x72, 0x20, 0x23, 0x30, 0x30, 0x30, + 0x38, 0x20, 0x41, 0x44, 0x44, 0x32, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x20, + 0x23, 0x30, 0x30, 0x30, 0x61, 0x20, 0x4f, 0x56, 0x52, 0x32, 0x20, 0x4f, + 0x56, 0x52, 0x32, 0x20, 0x44, 0x49, 0x56, 0x32, 0x20, 0x4d, 0x55, 0x4c, + 0x32, 0x20, 0x53, 0x55, 0x42, 0x32, 0x20, 0x23, 0x30, 0x30, 0x33, 0x30, + 0x20, 0x41, 0x44, 0x44, 0x32, 0x20, 0x53, 0x54, 0x48, 0x32, 0x6b, 0x72, + 0x20, 0x49, 0x4e, 0x43, 0x32, 0x20, 0x49, 0x4e, 0x43, 0x32, 0x20, 0x53, + 0x54, 0x48, 0x32, 0x6b, 0x72, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x6b, 0x20, + 0x23, 0x30, 0x30, 0x30, 0x31, 0x20, 0x53, 0x55, 0x42, 0x32, 0x20, 0x53, + 0x57, 0x50, 0x32, 0x20, 0x53, 0x54, 0x41, 0x32, 0x6b, 0x0a, 0x20, 0x20, + 0x20, 0x20, 0x50, 0x4f, 0x50, 0x32, 0x20, 0x41, 0x44, 0x44, 0x32, 0x20, + 0x53, 0x54, 0x41, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x50, 0x4f, 0x50, 0x20, + 0x53, 0x54, 0x48, 0x32, 0x6b, 0x72, 0x20, 0x23, 0x30, 0x30, 0x30, 0x38, + 0x20, 0x41, 0x44, 0x44, 0x32, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x6b, 0x20, + 0x23, 0x30, 0x30, 0x30, 0x61, 0x20, 0x44, 0x49, 0x56, 0x32, 0x20, 0x53, + 0x57, 0x50, 0x32, 0x20, 0x53, 0x54, 0x41, 0x32, 0x0a, 0x0a, 0x20, 0x20, + 0x26, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x2e, 0x31, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x23, 0x30, 0x30, 0x30, 0x30, 0x20, 0x53, 0x54, + 0x48, 0x32, 0x6b, 0x72, 0x20, 0x23, 0x30, 0x30, 0x30, 0x38, 0x20, 0x41, + 0x44, 0x44, 0x32, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x20, 0x4c, 0x54, 0x48, + 0x32, 0x20, 0x3f, 0x26, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x2e, 0x31, 0x0a, + 0x0a, 0x20, 0x20, 0x26, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x2e, 0x31, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x23, 0x30, 0x30, 0x30, 0x35, 0x20, 0x53, 0x54, + 0x48, 0x32, 0x6b, 0x72, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x20, 0x53, 0x55, + 0x42, 0x32, 0x20, 0x53, 0x54, 0x48, 0x32, 0x6b, 0x72, 0x20, 0x49, 0x4e, + 0x43, 0x32, 0x20, 0x49, 0x4e, 0x43, 0x32, 0x20, 0x53, 0x54, 0x48, 0x32, + 0x6b, 0x72, 0x20, 0x4c, 0x44, 0x41, 0x32, 0x20, 0x41, 0x44, 0x44, 0x32, + 0x20, 0x61, 0x6d, 0x63, 0x70, 0x79, 0x5f, 0x0a, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x26, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x23, 0x30, 0x30, 0x30, 0x30, 0x0a, 0x0a, 0x20, 0x20, 0x26, 0x72, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x50, 0x4f, + 0x50, 0x32, 0x72, 0x20, 0x4a, 0x4d, 0x50, 0x32, 0x72, 0x0a, 0x0a, 0x40, + 0x73, 0x74, 0x72, 0x2f, 0x3c, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x3e, 0x20, + 0x28, 0x20, 0x73, 0x74, 0x72, 0x2a, 0x20, 0x2d, 0x2d, 0x20, 0x29, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x4c, 0x44, 0x41, 0x6b, 0x20, 0x44, 0x55, 0x50, + 0x20, 0x3f, 0x7b, 0x20, 0x50, 0x4f, 0x50, 0x20, 0x50, 0x4f, 0x50, 0x32, + 0x20, 0x4a, 0x4d, 0x50, 0x32, 0x72, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x23, 0x31, 0x38, 0x20, 0x44, 0x45, 0x4f, 0x0a, 0x20, 0x20, 0x20, + 0x20, 0x49, 0x4e, 0x43, 0x32, 0x20, 0x21, 0x2f, 0x3c, 0x70, 0x72, 0x69, + 0x6e, 0x74, 0x3e, 0x0a, 0x0a, 0x40, 0x6d, 0x65, 0x6d, 0x5f, 0x6c, 0x65, + 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x20, 0x23, 0x30, 0x30, 0x30, 0x30, 0x0a, + 0x40, 0x6d, 0x65, 0x6d, 0x5f}; unsigned int __lib_undar_len = 1433; void uxn_emit_error(const char *str, i32 length, i32 line) { - printf("Error at line: %d > %.*s\n ", line, length, str); + fprintf(stderr, "\n===\nError at line: %d '%.*s'\n===\n", line, length, str); exit(1); } @@ -161,13 +184,12 @@ uxn_mem(u32 a) void uxn_prolog() { - printf("|100\n"); + printf("|100\n\tLIT2r 0000 main POP2r BRK\n\n"); } void uxn_epilogue() { - printf("BRK\n\n"); for(u32 i = 0; i < __lib_undar_len; i++) putchar(__lib_undar[i]); } @@ -270,122 +292,104 @@ u32 uxn_get_size(SymbolType t) { switch(t) { - case SYMBOL_BOOL: return 1; - case SYMBOL_BYTE: return 1; - case SYMBOL_INT: return 2; - case SYMBOL_NAT: return 2; - case SYMBOL_REAL: return 2; - case SYMBOL_STR: return 2; - case SYMBOL_U8: return 1; - case SYMBOL_I8: return 1; - case SYMBOL_I16: return 2; - case SYMBOL_U16: return 2; - case SYMBOL_I32: return 4; - case SYMBOL_U32: return 4; - case SYMBOL_F32: return 4; - default: break; + case SYMBOL_BOOL: + return 1; + case SYMBOL_BYTE: + return 1; + case SYMBOL_INT: + return 2; + case SYMBOL_NAT: + return 2; + case SYMBOL_REAL: + return 2; + case SYMBOL_STR: + return 2; + case SYMBOL_U8: + return 1; + case SYMBOL_I8: + return 1; + case SYMBOL_I16: + return 2; + case SYMBOL_U16: + return 2; + case SYMBOL_I32: + return 4; + case SYMBOL_U32: + return 4; + case SYMBOL_F32: + return 4; + default: + break; } return 0; } void -uxn_emit_primitive_type(SymbolType t, const char *str, i32 length, bool local) +uxn_emit_type(Symbol *sym, bool local) { - switch(t) { - case SYMBOL_BOOL: { - if(local) - printf("!{ &%.*s $2 } ", length, str); + if(local) + if(sym->ref) + printf("\tSTH2kr #%04x ADD2 LDA2\n", sym->ref); else - printf("!{ @%.*s $2 } ", length, str); - break; - } - case SYMBOL_BYTE: { - if(local) - printf("!{ &%.*s $1 } ", length, str); - else - printf("!{ @%.*s $1 } ", length, str); - break; - } - case SYMBOL_INT: { - if(local) - printf("!{ &%.*s $2 } ", length, str); - else - printf("!{ @%.*s $2 } ", length, str); - break; - } - case SYMBOL_NAT: { - if(local) - printf("!{ &%.*s $2 } ", length, str); - else - printf("!{ @%.*s $2 } ", length, str); - break; - } - case SYMBOL_REAL: { - if(local) - printf("!{ &%.*s $2 } ", length, str); - else - printf("!{ @%.*s $2 } ", length, str); - break; - } - case SYMBOL_STR: { - if(local) - printf("!{ &%.*s $2 } ", length, str); - else - printf("!{ @%.*s $2 } ", length, str); - break; - } - case SYMBOL_U8: { - if(local) - printf("!{ &%.*s $1 } ", length, str); - else - printf("!{ @%.*s $1 } ", length, str); - break; - } - case SYMBOL_I8: { - if(local) - printf("!{ &%.*s $1 } ", length, str); - else - printf("!{ @%.*s $1 } ", length, str); - break; - } - case SYMBOL_I16: { - if(local) - printf("!{ &%.*s $2 } ", length, str); - else - printf("!{ @%.*s $2 } ", length, str); - break; - } - case SYMBOL_U16: { - if(local) - printf("!{ &%.*s $2 } ", length, str); - else - printf("!{ @%.*s $2 } ", length, str); - break; - } - case SYMBOL_I32: { - if(local) - printf("!{ &%.*s $4 } ", length, str); - else - printf("!{ @%.*s $4 } ", length, str); - break; - } - case SYMBOL_U32: { - if(local) - printf("!{ &%.*s $4 } ", length, str); - else - printf("!{ @%.*s $4 } ", length, str); - break; - } - case SYMBOL_F32: { - if(local) - printf("!{ &%.*s $4 } ", length, str); - else - printf("!{ @%.*s $4 } ", length, str); - break; - } - default: break; - } + printf("\tSTH2kr LDA2\n"); + else + switch(sym->type) { + case SYMBOL_BOOL: { + printf("!{ @%.*s $2 } ", sym->name_length, sym->name); + break; + } + case SYMBOL_BYTE: { + printf("!{ @%.*s $1 } ", sym->name_length, sym->name); + break; + } + case SYMBOL_INT: { + printf("!{ @%.*s $2 } ", sym->name_length, sym->name); + break; + } + case SYMBOL_NAT: { + printf("!{ @%.*s $2 } ", sym->name_length, sym->name); + break; + } + case SYMBOL_REAL: { + printf("!{ @%.*s $2 } ", sym->name_length, sym->name); + break; + } + case SYMBOL_STR: { + printf("!{ @%.*s $2 } ", sym->name_length, sym->name); + break; + } + case SYMBOL_U8: { + printf("!{ @%.*s $1 } ", sym->name_length, sym->name); + break; + } + case SYMBOL_I8: { + printf("!{ @%.*s $1 } ", sym->name_length, sym->name); + break; + } + case SYMBOL_I16: { + printf("!{ @%.*s $2 } ", sym->name_length, sym->name); + break; + } + case SYMBOL_U16: { + printf("!{ @%.*s $2 } ", sym->name_length, sym->name); + break; + } + case SYMBOL_I32: { + printf("!{ @%.*s $4 } ", sym->name_length, sym->name); + break; + } + case SYMBOL_U32: { + printf("!{ @%.*s $4 } ", sym->name_length, sym->name); + break; + } + case SYMBOL_F32: { + printf("!{ @%.*s $4 } ", sym->name_length, sym->name); + break; + } + default: + break; + } } void uxn_emit_int(const char *str, i32 length) @@ -444,9 +448,51 @@ uxn_emit_array() { } -void -uxn_emit_function() +bool +fn_loop_emit_args(void *data) { + Symbol *sym = ((Symbol *)data); + + if(sym->ref) + printf("\tSTH2kr #%04x ADD2 STA2\n", sym->ref); + else + printf("\tSTH2kr STA2\n"); + return true; +} + +bool +fn_loop_emit_args_comment(void *data) +{ + Symbol *sym = ((Symbol *)data); + printf("%.*s ", sym->name_length, sym->name); + return true; +} + +void +uxn_emit_function(Symbol *sym) +{ + printf("@%.*s_ ( ", sym->name_length, sym->name); + List_map(sym->args, fn_loop_emit_args_comment); + printf(" -- "); + if(sym->secondary_type != SYMBOL_UNDEFINED && + sym->secondary_type != SYMBOL_VOID) + printf(" res "); + printf(")\n"); + printf("\tOVR2r LIT2r #%04x SUB2r\n", sym->size); + List_map(sym->args, fn_loop_emit_args); + printf("\n"); +} + +void +uxn_emit_arena_fn_return() +{ + printf("\t&return\n\t\tPOP2r JMP2r\n\n"); +} + +void +uxn_emit_arena_fn_call(Symbol *sym) +{ + printf("%.*s_ ", sym->name_length, sym->name); } void @@ -495,7 +541,10 @@ void uxn_emit_variable(Symbol *sym, bool local) { if(local) - printf(",/%.*s LDR2 ", sym->name_length, sym->name); + if(sym->ref) + printf("\tSTH2kr #%04x ADD2 LDA2 ", sym->ref); + else + printf("\tSTH2kr LDA2 "); else printf(";%.*s LDA2 ", sym->name_length, sym->name); } @@ -504,7 +553,10 @@ void uxn_emit_set_variable(Symbol *sym, bool local) { if(local) - printf(",/%.*s STR2 ", sym->name_length, sym->name); + if(sym->ref) + printf("\tSTH2kr #%04x ADD2 STA2 ", sym->ref); + else + printf("\tSTH2kr STA2 "); else printf(";%.*s STA2 ", sym->name_length, sym->name); } @@ -619,11 +671,6 @@ uxn_emit_strbuf_to_str() { } -void -uxn_emit_arena_fn_call() -{ -} - void uxn_emit_arena_fn_return_plex() { @@ -760,7 +807,7 @@ uxn_emitter() uxn_emit_real, uxn_emit_byte, uxn_emit_str, - uxn_emit_primitive_type, + uxn_emit_type, uxn_emit_array, uxn_emit_function, uxn_emit_plex, @@ -798,6 +845,7 @@ uxn_emitter() uxn_emit_strbuf_append, uxn_emit_strbuf_to_str, uxn_emit_arena_fn_call, + uxn_emit_arena_fn_return, uxn_emit_arena_fn_return_plex, uxn_emit_arena_fn_return_array, uxn_emit_arena_fn_return_strbuf, diff --git a/lexer.h b/lexer.h index d853010..d0f7769 100644 --- a/lexer.h +++ b/lexer.h @@ -6,6 +6,12 @@ typedef enum { TOKEN_ERROR, TOKEN_EOF, + TOKEN_LPAREN, + TOKEN_RPAREN, + TOKEN_LBRACE, + TOKEN_RBRACE, + TOKEN_LBRACKET, + TOKEN_RBRACKET, TOKEN_IDENTIFIER, TOKEN_LITERAL_INT, TOKEN_LITERAL_NAT, @@ -77,12 +83,6 @@ typedef enum { TOKEN_COLON, TOKEN_CARET, TOKEN_SEMICOLON, - TOKEN_LPAREN, - TOKEN_RPAREN, - TOKEN_LBRACE, - TOKEN_RBRACE, - TOKEN_LBRACKET, - TOKEN_RBRACKET, TOKEN_ARROW_RIGHT, TOKEN_SLL, TOKEN_SRL, diff --git a/list.c b/list.c index 65b8afc..b6688df 100644 --- a/list.c +++ b/list.c @@ -3,14 +3,14 @@ List * List_init(Arena *arena) { - List *l = (List*)aalloc(arena, sizeof(List)); - if (!l) return nil; + List *l = (List *)aalloc(arena, sizeof(List)); + if(!l) return nil; - l->head = nil; - l->tail = nil; - l->count = 0; + l->head = nil; + l->tail = nil; + l->count = 0; - return l; + return l; } void * @@ -22,83 +22,83 @@ node_value(Node *n) void * List_push(Arena *arena, List *list, void *data, u32 data_size) { - void *dest; - void *ptr = aalloc(arena, sizeof(Node) + data_size); - Node *node = (Node *)ptr; + void *dest; + void *ptr = aalloc(arena, sizeof(Node) + data_size); + Node *node = (Node *)ptr; - if (!node) return nil; + if(!node) return nil; node->size = data_size; - node->next = nil; + node->next = nil; - if (!list->head) { - list->head = list->tail = node; - } else { - list->tail->next = node; - list->tail = node; - } - - list->count++; + if(!list->head) { + list->head = list->tail = node; + } else { + list->tail->next = node; + list->tail = node; + } - dest = node_value(node); - if (data && data_size > 0) { - mcpy(dest, data, data_size); - } + list->count++; - return dest; + dest = node_value(node); + if(data && data_size > 0) mcpy(dest, data, data_size); + + return dest; } void List_map(List *list, list_iter_fn func) { - Node *curr; - if (!list || !func) return; - - curr = list->head; - while (curr) { - if (!func(node_value(curr))) break; - curr = curr->next; - } + Node *curr; + if(!list || !func) return; + + curr = list->head; + while(curr) { + if(!func(node_value(curr))) break; + curr = curr->next; + } } void * List_get(List *list, u32 index) { - u32 i; - Node *curr; - if (!list || index >= list->count) return nil; - - curr = list->head; - for (i = 0; i < index; i++) { - curr = curr->next; - } - - return node_value(curr); + u32 i; + Node *curr; + if(!list || index >= list->count) return nil; + + curr = list->head; + for(i = 0; i < index; i++) curr = curr->next; + + return node_value(curr); } void List_set(List *list, u32 index, void *data, u32 size) { - void *target = List_get(list, index); - if (!target) return; - mcpy(target, data, size); + void *target = List_get(list, index); + if(!target) return; + mcpy(target, data, size); } void * List_find(List *list, compare_fn compare, void *target) { - Node *curr; - void *data; + Node *curr; + void *data; - if (!list || !compare) return nil; + if(!list || !compare) return nil; - curr = list->head; - while (curr) { - data = node_value(curr); - if (compare(data, target)) { - return data; - } - curr = curr->next; - } - return nil; -} \ No newline at end of file + curr = list->head; + while(curr) { + data = node_value(curr); + if(compare(data, target)) return data; + curr = curr->next; + } + return nil; +} + +void * +List_last(List *list) +{ + return node_value(list->tail); +} diff --git a/list.h b/list.h index ad8b88c..4dbd69c 100644 --- a/list.h +++ b/list.h @@ -26,5 +26,6 @@ void List_map(List *list, list_iter_fn func); void *List_find(List *list, compare_fn compare, void *target); void *List_get(List *list, u32 index); void List_set(List *list, u32 index, void *data, u32 size); +void *List_last(List *list); -#endif \ No newline at end of file +#endif diff --git a/test/add.ul b/test/add.ul index 5298c74..b2353d8 100755 --- a/test/add.ul +++ b/test/add.ul @@ -1,10 +1,12 @@ -/** - * Add two numbers together - */ -function add(int a, int b) int { - return a + b; -} function main() { print(add(1, 1) as str); + return; +} + +/** + * Add two numbers together + */ +function add(nat a, nat b) nat { + return a + b; } diff --git a/test/str.c b/test/attack.c similarity index 100% rename from test/str.c rename to test/attack.c diff --git a/test/str.tal b/test/attack.tal similarity index 100% rename from test/str.tal rename to test/attack.tal diff --git a/test/attack.ul b/test/attack.ul new file mode 100755 index 0000000..5b193e1 --- /dev/null +++ b/test/attack.ul @@ -0,0 +1,8 @@ +str msg = " damage inflicted!\n" +nat AT = 14; +nat accuracy = 150; + +nat dmg = ((AT * accuracy) / 20) - 3; + +print(dmg as str); +print(msg); diff --git a/test/fib.ul b/test/fib.ul index d05e733..edc5240 100755 --- a/test/fib.ul +++ b/test/fib.ul @@ -6,4 +6,4 @@ function fib(nat n) nat { return fib(n - 2) + fib(n - 1); } -print(fib(23) as str); \ No newline at end of file +print(fib(23) as str); diff --git a/test/str.ul b/test/str.ul old mode 100755 new mode 100644 index 5b193e1..d522309 --- a/test/str.ul +++ b/test/str.ul @@ -1,8 +1,109 @@ -str msg = " damage inflicted!\n" -nat AT = 14; -nat accuracy = 150; +/** + * Constants + */ +const str nl = "\n"; +const str terminal_namespace = "/dev/term/0"; -nat dmg = ((AT * accuracy) / 20) - 3; +plex Terminal { + nat handle; +} -print(dmg as str); -print(msg); +/** + * Print with a newline + */ +function pln(str string) { + Terminal term = open(terminal_namespace, 0); + write(term, string, string.length); + write(term, nl, nl.length); + // implied return because it is a void function. +} + +/** + * Concatinates 2 strings + */ +function concat(str src1, str src2) str { + str result = malloc(src1.length + src2.length); + // note result[0].ref is much different than result.ref[0] ! + // result[0].ref means the pointer at char 0 (pointer to first char) + memcpy(result[0].ref, src1.ref); + memcpy(result[src1.length].ref, src2.ref); + return result; +} + +/** + * finds index of string, -1 if not found + */ +function str_index_of(str haystack, byte needle) int { + int i = -1; + for (byte c in haystack) { + if (c == needle) { + break; + } + } + return i; +} + +/** + * checks if 2 strings are equal + */ +function str_eq(str src1, str src2) bool { + if (src1.length != src2.length) return false; + do (int i=0; src1.length; i++) { + if (src1[i] != src2[i]) return false; + } + return true; +} + +/** + * Slice string + */ +function str_slice(str src, int start, int stop) str { + int len = stop - start; + str result = malloc(len); + do (int i=start; i