From fbfb24d1e52fadcd207c7adb0538dde744d9b38d Mon Sep 17 00:00:00 2001 From: zongor Date: Thu, 23 Apr 2026 00:01:11 -0700 Subject: [PATCH] fix casting, add strings, add libundar for uxntal, add chibicc-uxn generator files, --- README.org | 13 +- compiler.c | 241 +++++++++++++++-------------- docs/VM.org | 22 +++ emit/rer/emit.c | 49 +++--- emit/uxn/emit.c | 150 ++++++++++++++++-- emit/uxn/lib/chibicc-uxn/uxn.h | 11 ++ emit/uxn/lib/chibicc-uxn/varvara.h | 133 ++++++++++++++++ emit/uxn/lib/undar.c | 84 ++++++++++ emit/uxn/lib/undar.tal | 148 ++++++++++++++++++ test/bang.tal | 8 + test/global.tal | 2 + test/hello.tal | 8 + test/local.tal | 2 - test/str.c | 11 ++ test/str.tal | 73 +++++++++ test/str.ul | 6 +- 16 files changed, 803 insertions(+), 158 deletions(-) create mode 100644 emit/uxn/lib/chibicc-uxn/uxn.h create mode 100644 emit/uxn/lib/chibicc-uxn/varvara.h create mode 100644 emit/uxn/lib/undar.c create mode 100644 emit/uxn/lib/undar.tal create mode 100644 test/bang.tal create mode 100644 test/global.tal create mode 100644 test/hello.tal delete mode 100644 test/local.tal create mode 100755 test/str.c create mode 100644 test/str.tal diff --git a/README.org b/README.org index 25ad74b..52e2d10 100644 --- a/README.org +++ b/README.org @@ -27,16 +27,26 @@ cd undar-lang && ./build * Memory Management All memory used by the program exists in one big bump allocator. + When a function gets called, it creates a new arena in memory starting at the end of the previous frame. (or at the beginning of memory if no function has been called) + Variables allocated in the frame's arena are owned by default by the frame they are allocated in. + When variables get modified within the current frame they will get updated in that frame in their current location in the arena. + All complex types (Plex, arrays, strings) use fat pointers where they have a header of the length of that block and a "next" ptr that refers to the next allocated block for that value + If the size of the variable changes (like adding a value to the end of a array), a link is added to the internal list that points to a new block is allocated at the end of the arena of the size of that value, so they are variable sized blocks + When a variable is passed to a child function primitive types are pass by value, complex types (Arrays, Plexes, Strings) are pass by reference. + Variables passed as arguments to the child follow the same rules except when the size of a complex type changes, then a new value is added as a link from the parent to the child and the new value is allocated at the end of the childs arena (but the owner is still the parent). + When a function "returns" the frame is deallocated and all values allocated by it is freed; thus freeing memory deterministically. + Only a single variable may be returned from a function. When a variable is returned if it is primitive it is just passed back to the parent. If it is complex the value is coalesced into a single contiguous values and the link in the parent is updated to point at the "new" end of the arena. If the parents block is at the end the entire block is coalesced into a single contiguous block. -this allows for the low resource usage of a C but the convenience of a garbage collected language like C# or Go but without the GC pauses. + +This allows for the low resource usage of a C but the convenience of a garbage collected language like C# or Go but without the GC pauses. **Built in Types** @@ -71,4 +81,5 @@ this allows for the low resource usage of a C but the convenience of a garbage c - [[https://lua.org][Lua]] - Friendly syntax, portable, and minimal VM. - [[https://www.craftinginterpreters.com/the-lox-language.html][Lox]] - Lexer & Parser logic. - [[https://wiki.xxiivv.com/site/uxn.html][Uxn]] - Major inspiration. +- [[https://github.com/lynn/chibicc][chibicc-uxn]] - Generated uxntal code for the undar-uxn libc. - Retro Systems - N64, PS1, Mac Classic, Windows 95 - UI esthetics diff --git a/compiler.c b/compiler.c index d79d650..c7fc494 100644 --- a/compiler.c +++ b/compiler.c @@ -95,7 +95,7 @@ advance() return false; } } -static bool +bool check(TokenType type) { return parser.current.type == type; @@ -112,7 +112,7 @@ consume(TokenType type) return false; } -static bool +bool match(TokenType type) { if(!check(type)) return false; @@ -120,13 +120,13 @@ match(TokenType type) return true; } -static void expression(); -static void statement(); -static void declaration(); -static ParseRule *get_rule(TokenType type); -static void parse_precedence(Precedence precedence); +void expression(); +void statement(); +void declaration(); +ParseRule *get_rule(TokenType type); +void parse_precedence(Precedence precedence); -static void +void binary() { TokenType operatorType = parser.previous.type; @@ -176,19 +176,19 @@ binary() break; case TOKEN_OPERATOR_MOD: emitter.emit_mod(); - break; + break; case TOKEN_SLL: emitter.emit_sll(); break; case TOKEN_SRL: emitter.emit_srl(); - break; + break; default: return; } } -static void +void literal() { switch(parser.previous.type) { @@ -206,13 +206,13 @@ literal() } } -static void +void expression() { parse_precedence(PREC_ASSIGNMENT); } -static void +void variable() { Symbol *sym = scope_get_symbol(parser.current_scope, parser.previous.start, @@ -226,103 +226,97 @@ variable() emitter.emit_variable(sym, parser.depth); } -static void +void cast_type() { - TokenType cast_type = parser.current.type; SymbolType st = parser.current_type; + TokenType cast_type = parser.current.type; advance(); - switch(cast_type) { - case TOKEN_TYPE_INT:{ - switch(st) { - case SYMBOL_NAT:{ - emitter.emit_cast_int_to_nat(); - break; - } - case SYMBOL_REAL:{ - emitter.emit_cast_int_to_real(); - break; - } - case SYMBOL_STR:{ - emitter.emit_cast_int_to_str(); - break; - } - default: - emitter.error("Not castable to this type", 26, parser.previous.line); + switch(st) { + case SYMBOL_INT: { + switch(cast_type) { + case TOKEN_TYPE_NAT: { + emitter.emit_cast_int_to_nat(); + break; + } + case TOKEN_TYPE_REAL: { + emitter.emit_cast_int_to_real(); + break; + } + case TOKEN_TYPE_STR: { + emitter.emit_cast_int_to_str(); + break; + } + default: + emitter.error("Not castable to this type", 26, parser.previous.line); } break; } - case TOKEN_TYPE_NAT:{ - switch(st) { - case SYMBOL_INT:{ - emitter.emit_cast_nat_to_int(); - break; - } - case SYMBOL_REAL:{ - emitter.emit_cast_nat_to_real(); - break; - } - case SYMBOL_STR:{ - emitter.emit_cast_nat_to_str(); - break; - } - default: - emitter.error("Not castable to this type", 26, parser.previous.line); + case SYMBOL_NAT: { + switch(cast_type) { + case TOKEN_TYPE_INT: { + emitter.emit_cast_nat_to_int(); + break; } - break; + case TOKEN_TYPE_REAL: { + emitter.emit_cast_nat_to_real(); + break; + } + case TOKEN_TYPE_STR: { + emitter.emit_cast_nat_to_str(); + break; + } + default: + emitter.error("Not castable to this type", 26, parser.previous.line); + } + break; } - case TOKEN_TYPE_REAL:{ - switch(st) { - case SYMBOL_NAT:{ - emitter.emit_cast_real_to_nat(); - break; - } - case SYMBOL_INT:{ - emitter.emit_cast_real_to_int(); - break; - } - case SYMBOL_STR:{ - emitter.emit_cast_real_to_str(); - break; - } - default: - emitter.error("Not castable to this type", 26, parser.previous.line); + case SYMBOL_REAL: { + switch(cast_type) { + case TOKEN_TYPE_NAT: { + emitter.emit_cast_real_to_nat(); + break; } - break; + case TOKEN_TYPE_INT: { + emitter.emit_cast_real_to_int(); + break; + } + case TOKEN_TYPE_STR: { + emitter.emit_cast_real_to_str(); + break; + } + default: + emitter.error("Not castable to this type", 26, parser.previous.line); + } + break; } - case TOKEN_TYPE_STR:{ - switch(st) { - case SYMBOL_NAT:{ - emitter.emit_cast_str_to_nat(); - break; - } - case SYMBOL_REAL:{ - emitter.emit_cast_str_to_real(); - break; - } - case SYMBOL_INT:{ - emitter.emit_cast_str_to_int(); - break; - } - default: - emitter.error("Not castable to this type", 26, parser.previous.line); + case SYMBOL_STR: { + switch(cast_type) { + case TOKEN_TYPE_NAT: { + emitter.emit_cast_str_to_nat(); + break; } - break; + case TOKEN_TYPE_REAL: { + emitter.emit_cast_str_to_real(); + break; + } + case TOKEN_TYPE_INT: { + emitter.emit_cast_str_to_int(); + break; + } + default: + emitter.error("Not castable to this type", 26, parser.previous.line); + } + break; } default: emitter.error("Not castable to this type", 26, parser.previous.line); } - - emitter.emit_open_paren(); - - expression(); - - emitter.emit_close_paren(); } -static void +void variable_declaration() { @@ -332,70 +326,80 @@ variable_declaration() switch(tt) { case TOKEN_TYPE_INT: { - size = emitter.emit_int_type(parser.current.start, parser.current.length, parser.depth); + size = emitter.emit_int_type(parser.current.start, parser.current.length, + parser.depth); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_INT, - size); + size); parser.current_type = SYMBOL_INT; break; } case TOKEN_TYPE_NAT: { - size = emitter.emit_nat_type(parser.current.start, parser.current.length, parser.depth); + size = emitter.emit_nat_type(parser.current.start, parser.current.length, + parser.depth); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_NAT, size); parser.current_type = SYMBOL_NAT; break; } case TOKEN_TYPE_REAL: { - size = emitter.emit_real_type(parser.current.start, parser.current.length, parser.depth); + size = emitter.emit_real_type(parser.current.start, parser.current.length, + parser.depth); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_REAL, size); parser.current_type = SYMBOL_REAL; break; } case TOKEN_TYPE_STR: { - size = emitter.emit_str_type(parser.current.start, parser.current.length, parser.depth); + size = emitter.emit_str_type(parser.current.start, parser.current.length, + parser.depth); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_STR, size); parser.current_type = SYMBOL_STR; break; } case TOKEN_TYPE_BOOL: { - size = emitter.emit_bool_type(parser.current.start, parser.current.length, parser.depth); + size = emitter.emit_bool_type(parser.current.start, parser.current.length, + parser.depth); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_BOOL, size); parser.current_type = SYMBOL_BOOL; break; } case TOKEN_TYPE_BYTE: { - size = emitter.emit_byte_type(parser.current.start, parser.current.length, parser.depth); + size = emitter.emit_byte_type(parser.current.start, parser.current.length, + parser.depth); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_U8, size); parser.current_type = SYMBOL_BYTE; break; } case TOKEN_TYPE_U8: { - size = emitter.emit_u8_type(parser.current.start, parser.current.length, parser.depth); + size = emitter.emit_u8_type(parser.current.start, parser.current.length, + parser.depth); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_U8, size); parser.current_type = SYMBOL_U8; break; } case TOKEN_TYPE_I8: { - size = emitter.emit_i8_type(parser.current.start, parser.current.length, parser.depth); + size = emitter.emit_i8_type(parser.current.start, parser.current.length, + parser.depth); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_I8, size); parser.current_type = SYMBOL_I8; break; } case TOKEN_TYPE_U16: { - size = emitter.emit_u16_type(parser.current.start, parser.current.length, parser.depth); + size = emitter.emit_u16_type(parser.current.start, parser.current.length, + parser.depth); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_U16, size); parser.current_type = SYMBOL_U16; break; } case TOKEN_TYPE_I16: { - size = emitter.emit_i16_type(parser.current.start, parser.current.length, parser.depth); + size = emitter.emit_i16_type(parser.current.start, parser.current.length, + parser.depth); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_I16, size); parser.current_type = SYMBOL_I16; @@ -420,7 +424,7 @@ variable_declaration() parser.current_type = SYMBOL_UNDEFINED; } -static void +void declaration() { /** @@ -428,14 +432,13 @@ declaration() * lookup plex defs * if not then */ - if(is_type()) variable_declaration(); else statement(); } -static void +void print_statement() { expression(); @@ -444,7 +447,7 @@ print_statement() emitter.emit_print(); } -static void +void putchar_statement() { expression(); @@ -453,7 +456,7 @@ putchar_statement() emitter.emit_putchar(); } -static void +void getchar_statement() { expression(); @@ -462,7 +465,7 @@ getchar_statement() emitter.emit_putchar(); } -static void +void if_statement() { consume(TOKEN_LPAREN); @@ -473,7 +476,7 @@ if_statement() emitter.emit_patch_jump(); } -static void +void block() { while(!check(TOKEN_RBRACE) && !check(TOKEN_EOF)) declaration(); @@ -481,7 +484,7 @@ block() consume(TOKEN_RBRACE); } -static void +void statement() { if(match(TOKEN_LBRACE)) { @@ -489,9 +492,9 @@ statement() block(); scope_pop(); } else if(match(TOKEN_KEYWORD_IF)) { - if_statement(); + if_statement(); } else if(match(TOKEN_KEYWORD_PRINT)) { - print_statement(); + print_statement(); } else if(match(TOKEN_KEYWORD_PUTCHAR)) { putchar_statement(); } else if(match(TOKEN_KEYWORD_GETCHAR)) { @@ -501,7 +504,7 @@ statement() } } -static void +void grouping() { emitter.emit_open_paren(); @@ -512,19 +515,19 @@ grouping() consume(TOKEN_RPAREN); } -static void +void number() { emitter.emit_int(parser.previous.start, parser.previous.length); } -static void +void string() { emitter.emit_str(parser.previous.start, parser.previous.length); } -static void +void unary() { TokenType operatorType = parser.previous.type; @@ -590,7 +593,7 @@ ParseRule rules[] = { /* TOKEN_OPERATOR_AND */ {nil, binary, PREC_NONE}, /* TOKEN_OPERATOR_OR */ {nil, binary, PREC_NONE}, /* TOKEN_OPERATOR_XOR */ {nil, binary, PREC_NONE}, - /* TOKEN_OPERATOR_MOD */ {nil, binary, PREC_NONE}, + /* TOKEN_OPERATOR_MOD */ {nil, binary, PREC_NONE}, /* TOKEN_BANG */ {unary, nil, PREC_NONE}, /* TOKEN_BANG_EQ */ {nil, binary, PREC_EQUALITY}, /* TOKEN_EQ */ {nil, nil, PREC_NONE}, @@ -625,9 +628,9 @@ ParseRule rules[] = { /* TOKEN_ARROW_RIGHT */ {nil, nil, PREC_NONE}, /* TOKEN_SLL */ {nil, binary, PREC_NONE}, /* TOKEN_SRL */ {nil, binary, PREC_NONE}, - /*TOKEN_KEYWORD_PRINT*/{nil, binary, PREC_NONE} }; + /*TOKEN_KEYWORD_PRINT*/ {nil, binary, PREC_NONE}}; -static void +void parse_precedence(Precedence precedence) { ParseFn prefixRule; @@ -646,7 +649,7 @@ parse_precedence(Precedence precedence) } } -static ParseRule * +ParseRule * get_rule(TokenType type) { return &rules[type]; diff --git a/docs/VM.org b/docs/VM.org index c37ab26..d8ddef2 100644 --- a/docs/VM.org +++ b/docs/VM.org @@ -14,3 +14,25 @@ so its a ptr to the next link followed by the size followed by an array of raw d When modified it just adds the new values to the end of the list. The list then can be "collapsed" back into a simple array. +** Core x86 ISA -> RISC-like +*** Math +RISC : ADD SUB AND OR XOR SHL SHR +x86 : ADD SUB AND OR XOR SHL SHR +- flags don't matter unless there is a conditional branch immediately after without a CMP/TEST in-between +*** MEM +RISC : LOAD [Base + Offset] +x86 : MOV Reg, [Base + Offset] +RISC : STORE [Base + Offset] +x86 : MOV [Base + Offset], Reg +*** Branch +RISC : Branch Eq +x86 : CMP JE + + +** Stack based system in machine code + x86 ARM32 RISC-V +TOS (Top of Stack) = EAX W0 R0 +TOS - 1 = ECX W1 T1 +TOS - 2 = EDX W2 T2 +Memory Stack = Hardware Ptr (ESP, SP, SP) + diff --git a/emit/rer/emit.c b/emit/rer/emit.c index 90aa63f..7d50e01 100644 --- a/emit/rer/emit.c +++ b/emit/rer/emit.c @@ -2,25 +2,6 @@ #include #include -#define RER_OP_2 (1 << 5) -#define RER_OP_R (1 << 6) -#define RER_OP_K (1 << 7) - -enum rer_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, -}; - void rer_emit_error(const char *str, i32 length, i32 line) { @@ -43,7 +24,7 @@ rer_prolog() void rer_epilogue() { - printf("\n\n@str/ ( str* -- )\n\ + printf("BRK\n\n@str/ ( str* -- )\n\ LDAk DUP ?{ POP POP2 JMP2r }\n\ #18 DEO\n\ INC2 !/\n"); @@ -136,7 +117,7 @@ rer_emit_neg() void rer_emit_not() { - printf("#FFFF EOR2 "); + printf("#ffff EOR2 "); } void @@ -148,11 +129,11 @@ i32 rer_emit_bool_type(const char *str, i32 length, bool local) { if(local) - printf("!{ &%.*s $1 } ", length, str); + printf("!{ &%.*s $2 } ", length, str); else - printf("!{ @%.*s $1 } ", length, str); + printf("!{ @%.*s $2 } ", length, str); - return 1; + return 2; } i32 @@ -577,6 +558,26 @@ rer_emit_patch_jump() printf("} "); } +i32 +rer_emit_const_type(SymbolType type, const char *var, i32 var_length, const char *val, i32 val_legnth, bool local) { + + if(local) + printf("&%.*s ", var_length, var); + else + printf("@%.*s ", var_length, var); + + if (type == SYMBOL_STR) { + for (i32 i = 1; i < val_legnth - 1 ; i++) { + printf("#%02x ", val[i]); + } + } else { + i32 i = (i32)strtol(val, nil, 10); + printf("#%04x ", i); + } + + return 2; +} + Emitter rer_emitter() { diff --git a/emit/uxn/emit.c b/emit/uxn/emit.c index 2ef3a93..13b5459 100644 --- a/emit/uxn/emit.c +++ b/emit/uxn/emit.c @@ -21,6 +21,131 @@ enum uxn_opcode { 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 +}; +unsigned int __lib_undar_len = 1433; + + void uxn_emit_error(const char *str, i32 length, i32 line) { @@ -43,10 +168,10 @@ uxn_prolog() void uxn_epilogue() { - printf("BRK\n\n@str/ ( str* -- )\n\ - LDAk DUP ?{ POP POP2 JMP2r }\n\ - #18 DEO\n\ - INC2 !/\n"); + printf("\n\n"); + for (u32 i = 0; i < __lib_undar_len; i++) { + putchar(__lib_undar[i]); + } } void @@ -313,9 +438,7 @@ uxn_emit_str(const char *str, i32 length) /* set a pointer to the string literal and then jump over it */ printf(";{ #0002 ADD2 } !{ "); - for (i32 i = 1; i < length - 1 ; i++) { - printf("#%02x ", str[i]); - } + for(i32 i = 1; i < length - 1; i++) printf("#%02x ", str[i]); printf("#00 } "); } @@ -418,6 +541,7 @@ uxn_emit_stat() void uxn_emit_end_statement() { + printf("\n"); } void @@ -433,46 +557,55 @@ uxn_emit_plex_def() void uxn_emit_cast_int_to_nat() { + printf("int_to_nat_ "); } void uxn_emit_cast_int_to_real() { + printf("int_to_real_ "); } void uxn_emit_cast_int_to_str() { + printf("int_to_str_ "); } void uxn_emit_cast_nat_to_int() { + printf("nat_to_int_ "); } void uxn_emit_cast_nat_to_real() { + printf("nat_to_real_ "); } void uxn_emit_cast_nat_to_str() { + printf("nat_to_str_ "); } void uxn_emit_cast_real_to_int() { + printf("real_to_int_ "); } void uxn_emit_cast_real_to_nat() { + printf("real_to_nat_ "); } void uxn_emit_cast_real_to_str() { + printf("real_to_str_ "); } void @@ -564,7 +697,6 @@ uxn_emit_print() printf("str/ "); } - void uxn_emit_jump() { @@ -665,6 +797,6 @@ uxn_emitter() uxn_emit_and, uxn_emit_or, uxn_emit_jump, - uxn_emit_patch_jump, + uxn_emit_patch_jump, }; } diff --git a/emit/uxn/lib/chibicc-uxn/uxn.h b/emit/uxn/lib/chibicc-uxn/uxn.h new file mode 100644 index 0000000..c01aa56 --- /dev/null +++ b/emit/uxn/lib/chibicc-uxn/uxn.h @@ -0,0 +1,11 @@ +// Raw interface to uxn's "devices" +void deo(char data, char device); +void deo2(int data, char device); +char dei(char device); +int dei2(char device); + +int __builtin_va_arg(); +typedef void *va_list; +#define va_start(ap, va) +#define va_end(ap) +#define va_arg(ap, ty) __builtin_va_arg() diff --git a/emit/uxn/lib/chibicc-uxn/varvara.h b/emit/uxn/lib/chibicc-uxn/varvara.h new file mode 100644 index 0000000..2152b4e --- /dev/null +++ b/emit/uxn/lib/chibicc-uxn/varvara.h @@ -0,0 +1,133 @@ +#include "uxn.h" + +void exit(char status); + +typedef struct { + char operation; // 1 = copy + int length; + int src_page; + void* src_addr; + int dst_page; + void* dst_addr; +} Expansion; + +// https://wiki.xxiivv.com/site/varvara.html +#define expansion(ptr) deo2(ptr, 0x02) +#define friend(func) deo2(func, 0x04) +#define set_palette(r, g, b) (deo2(r, 0x08), deo2(g, 0x0a), deo2(b, 0x0c)) +#define debug() deo(0x01, 0x0e) + +#define console_read() dei(0x12) +#define console_type() dei(0x17) +#define console_write(c) deo(c, 0x18) // stdout +#define console_error(c) deo(c, 0x19) // stderr +#define getchar console_read +#define putchar console_write + +#define set_screen_size(width, height) (deo2(width, 0x22), deo2(height, 0x24)) +#define screen_width() dei2(0x22) +#define screen_height() dei2(0x24) +#define set_screen_auto(a) deo(a, 0x26) +#define set_screen_x(x) deo2(x, 0x28) +#define set_screen_y(y) deo2(y, 0x2a) +#define set_screen_xy(x,y) (set_screen_x(x), set_screen_y(y)) +#define screen_x() dei2(0x28) +#define screen_y() dei2(0x2a) +#define set_screen_addr(a) deo2(a, 0x2c) +#define draw_pixel(a) deo(a, 0x2e) +#define draw_sprite(a) deo(a, 0x2f) + +#define audio_position(ch, a) dei2(0x32 + 0x10*ch) +#define audio_output(ch) dei(a, 0x34 + 0x10*ch) +#define set_audio_adsr(ch, adsr) deo2(adsr, 0x38 + 0x10*ch) +#define set_audio_length(ch, length) deo2(length, 0x3a + 0x10*ch) +#define set_audio_addr(ch, addr) deo2(addr, 0x3c + 0x10*ch) +#define set_audio_volume(ch, volume) deo(volume, 0x3e + 0x10*ch) +#define play_audio(ch, pitch) deo(pitch, 0x3f + 0x10*ch) + +#define controller_button() dei(0x82) +#define controller_key() dei(0x83) + +#define mouse_x() dei2(0x92) +#define mouse_y() dei2(0x94) +#define mouse_state() dei(0x96) +#define mouse_scrollx() dei2(0x9a) +#define mouse_scrolly() dei2(0x9c) + +/// Read up to n bytes from file "name" into addr, then return bytes read. +#define file_read(name, n, addr) (deo2(name, 0xa8), deo2(n, 0xaa), deo2(addr, 0xac), dei2(0xa2)) +#define _file_write(name, n, addr, append) (deo(append, 0xa7), deo2(name, 0xa8), deo2(n, 0xaa), deo2(addr, 0xae), dei2(0xa2)) +/// Write n bytes from addr into file "name", then return bytes written. +#define file_write(name, n, addr) _file_write(name, n, addr, 0) +#define file_append(name, n, addr) _file_write(name, n, addr, 1) +#define file_delete(name) (deo2(name, 0xa8), deo(1, 0xa6)) + +#define datetime_year() dei2(0xc0) +#define datetime_month() dei(0xc2) +#define datetime_day() dei(0xc3) +#define datetime_hour() dei(0xc4) +#define datetime_minute() dei(0xc5) +#define datetime_second() dei(0xc6) +#define datetime_dotw() dei(0xc7) +#define datetime_doty() dei2(0xc8) +#define datetime_isdst() dei(0xca) + +// Pixel values (| with color number) +// (Layer + operation + corner) +#define BgDot 0x00 +#define BgFillBR 0x80 +#define BgFillBL 0x90 +#define BgFillTR 0xa0 +#define BgFillTL 0xb0 +#define FgDot 0x40 +#define FgFillBR 0xc0 +#define FgFillBL 0xd0 +#define FgFillTR 0xe0 +#define FgFillTL 0xf0 + +// Sprite values (| with blend number) +// (Layer + bit depth + flip axes) +#define Bg1 0x00 +#define Bg1X 0x10 +#define Bg1Y 0x20 +#define Bg1XY 0x30 +#define Fg1 0x40 +#define Fg1X 0x50 +#define Fg1Y 0x60 +#define Fg1XY 0x70 +#define Bg2 0x80 +#define Bg2X 0x90 +#define Bg2Y 0xa0 +#define Bg2XY 0xb0 +#define Fg2 0xc0 +#define Fg2X 0xd0 +#define Fg2Y 0xe0 +#define Fg2XY 0xf0 + +// Auto values +#define Auto1 0x00 +#define Auto1x 0x01 +#define Auto1y 0x02 +#define Auto1a 0x04 +#define Auto1ax 0x05 +#define Auto1ay 0x06 +#define Auto2 0x10 +#define Auto2x 0x11 +#define Auto2y 0x12 +#define Auto2a 0x14 +#define Auto2ax 0x15 +#define Auto2ay 0x16 + +// Button values +#define ButtonCtrl 0x01 +#define ButtonA 0x01 +#define ButtonAlt 0x02 +#define ButtonB 0x02 +#define ButtonShift 0x04 +#define ButtonSelect 0x04 +#define ButtonStart 0x08 +#define ButtonHome 0x08 +#define ButtonUp 0x10 +#define ButtonDown 0x20 +#define ButtonLeft 0x40 +#define ButtonRight 0x80 diff --git a/emit/uxn/lib/undar.c b/emit/uxn/lib/undar.c new file mode 100644 index 0000000..9d682c5 --- /dev/null +++ b/emit/uxn/lib/undar.c @@ -0,0 +1,84 @@ +#include "chibicc-uxn/varvara.h" + +char mem[100]; +unsigned mem_length; + +char * +aalloc(unsigned size) +{ + unsigned pos = mem_length; + mem_length += size; + return (char *)&mem[pos]; +} + +char * +areturn(unsigned checkpoint, char *src, unsigned size) +{ + char *dest = (char *)&mem[checkpoint]; + if(src == dest) return src; + + for (unsigned i = 0; i < size; i++) { + dest[i] = src[i]; + } + + mem_length = checkpoint + size; + /* zero out the end of the memory copy (for strings mostly) */ + mem[mem_length] = 0; + return dest; +} + +void +afree() +{ + mem_length = 0; +} + +char * +amcpy(char *from, unsigned length) +{ + char *ptr = aalloc(length); + for (unsigned i = 0; i < length; i++) { + ptr[i] = from[i]; + } + return ptr; +} + +char* nat_to_str(unsigned n) { + char buffer[5]; + unsigned i = 5; + + do { + buffer[--i] = '0' + n % 10; + n /= 10; + } while(n > 0); + + return amcpy(buffer + i, 5 - i); +} + +char* int_to_str(int n) { + char buffer[6]; + unsigned i = 6; + _Bool neg = n < 0; + + if (neg) n = -n; + + do { + buffer[--i] = '0' + n % 10; + n /= 10; + } while(n > 0); + if(neg) buffer[--i] = '-'; + + return amcpy(buffer + i, 6 - i); +} + +unsigned +int_to_nat(int n) +{ + return (unsigned)n; +} + +int +nat_to_int(unsigned n) +{ + return (int)n; +} diff --git a/emit/uxn/lib/undar.tal b/emit/uxn/lib/undar.tal new file mode 100644 index 0000000..07d6db5 --- /dev/null +++ b/emit/uxn/lib/undar.tal @@ -0,0 +1,148 @@ +@sext + #80 ANDk EQU #ff MUL SWP JMP2r +@sdiv + OVR #80 AND ?&b_neg &b_pos OVR2 POP #80 AND ?&a_neg_b_pos DIV2 JMP2r &a_neg_b_pos SWP2 #0000 SWP2 SUB2 SWP2 DIV2 #0000 SWP2 SUB2 JMP2r + &b_neg #0000 SWP2 SUB2 OVR2 POP #80 AND ?&a_neg_b_neg DIV2 #0000 SWP2 SUB2 JMP2r + &a_neg_b_neg #0000 ROT2 SUB2 SWP2 DIV2 JMP2r + +@aalloc_ ( size* -- result* ) + OVR2r LIT2r 0004 SUB2r STH2kr INC2 INC2 STA2 + ;mem_length_ LDA2 STH2kr STA2 + ;mem_length_ LDA2k STH2kr INC2 INC2 LDA2 ADD2 SWP2 STA2 + ;mem_ STH2kr LDA2 ADD2 !&return + #0000 + + &return + POP2r JMP2r + +@areturn_ ( size* src* checkpoint* -- result* ) + OVR2r LIT2r 000a SUB2r STH2kr #0008 ADD2 STA2 + STH2kr #0006 ADD2 STA2 + STH2kr #0004 ADD2 STA2 + ;mem_ STH2kr #0008 ADD2 LDA2 ADD2 STH2kr INC2 INC2 STA2 + STH2kr #0006 ADD2 LDA2 STH2kr INC2 INC2 LDA2 NEQ2 ?&end.1 + STH2kr #0006 ADD2 LDA2 !&return + + &end.1 + #0000 STH2kr STA2 + + &begin.2 + STH2kr LDA2 STH2kr #0004 ADD2 LDA2 LTH2 #00 EQU ?&break.2 + STH2kr #0006 ADD2 LDA2 STH2kr LDA2 ADD2 LDA sext + STH2kr INC2 INC2 LDA2 STH2kr LDA2 ADD2 STA + POP + + &continue.2 + STH2kr LDA2k INC2k ROT2 STA2 + POP2 !&begin.2 + + &break.2 + STH2kr #0008 ADD2 LDA2 STH2kr #0004 ADD2 LDA2 ADD2 ;mem_length_ STA2 + #0000 ;mem_ ;mem_length_ LDA2 ADD2 STA + POP STH2kr INC2 INC2 LDA2 !&return + #0000 + + &return + POP2r JMP2r + +@afree_ ( -- result* ) + OVR2r #0000 ;mem_length_ STA2 + #0000 + + &return + POP2r JMP2r + +@amcpy_ ( length* from* -- result* ) + OVR2r LIT2r 0008 SUB2r STH2kr #0006 ADD2 STA2 + STH2kr #0004 ADD2 STA2 + STH2kr #0004 ADD2 LDA2 aalloc_ + STH2kr INC2 INC2 STA2 + #0000 STH2kr STA2 + + &begin.1 + STH2kr LDA2 STH2kr #0004 ADD2 LDA2 LTH2 #00 EQU ?&break.1 + STH2kr #0006 ADD2 LDA2 STH2kr LDA2 ADD2 LDA sext + STH2kr INC2 INC2 LDA2 STH2kr LDA2 ADD2 STA + POP + + &continue.1 + STH2kr LDA2k INC2k ROT2 STA2 + POP2 !&begin.1 + + &break.1 + STH2kr INC2 INC2 LDA2 !&return + #0000 + + &return + POP2r JMP2r + +@nat_to_str_ ( n* -- result* ) + OVR2r LIT2r 000a SUB2r STH2kr #0008 ADD2 STA2 + #0005 STH2kr STA2 + + &begin.1 + STH2kr #0008 ADD2 LDA2 #000a OVR2 OVR2 DIV2 MUL2 SUB2 #0030 ADD2 STH2kr INC2 INC2 STH2kr LDA2k #0001 SUB2 SWP2 STA2k + POP2 ADD2 STA + POP STH2kr #0008 ADD2 LDA2k #000a DIV2 SWP2 STA2 + + &continue.1 + #0000 STH2kr #0008 ADD2 LDA2 LTH2 ?&begin.1 + + &break.1 + #0005 STH2kr LDA2 SUB2 STH2kr INC2 INC2 STH2kr LDA2 ADD2 amcpy_ + !&return + #0000 + + &return + POP2r JMP2r + +@int_to_str_ ( n* -- result* ) + OVR2r LIT2r 000c SUB2r STH2kr #000a ADD2 STA2 + #0006 STH2kr INC2 INC2 STA2 + STH2kr #000a ADD2 LDA2 #8000 EOR2 #8000 LTH2 #00 SWP #0000 NEQ2 #00 SWP STH2kr STA + POP LDAkr STHr sext + #0000 EQU2 ?&end.1 + #0000 STH2kr #000a ADD2 LDA2 SUB2 STH2kr #000a ADD2 STA2 + + &end.1 + + &begin.2 + STH2kr #000a ADD2 LDA2 #000a OVR2 OVR2 sdiv/b_pos + MUL2 SUB2 #0030 ADD2 STH2kr #0004 ADD2 STH2kr INC2 INC2 LDA2k #0001 SUB2 SWP2 STA2k + POP2 ADD2 STA + POP STH2kr #000a ADD2 LDA2k #000a sdiv/b_pos + SWP2 STA2 + + &continue.2 + #8000 STH2kr #000a ADD2 LDA2 #8000 EOR2 LTH2 ?&begin.2 + + &break.2 + LDAkr STHr sext + #0000 EQU2 ?&end.3 + #002d STH2kr #0004 ADD2 STH2kr INC2 INC2 LDA2k #0001 SUB2 SWP2 STA2k + POP2 ADD2 STA + POP + + &end.3 + #0006 STH2kr INC2 INC2 LDA2 SUB2 STH2kr #0004 ADD2 STH2kr INC2 INC2 LDA2 ADD2 amcpy_ + !&return + #0000 + + &return + POP2r JMP2r + +@int_to_nat_ ( n* -- result* ) + OVR2r LIT2r 0002 SUB2r STH2kr STA2 + STH2kr LDA2 !&return + #0000 + + &return + POP2r JMP2r + +@nat_to_int_ ( n* -- result* ) + OVR2r LIT2r 0002 SUB2r STH2kr STA2 + STH2kr LDA2 !&return + #0000 + + &return + POP2r JMP2r diff --git a/test/bang.tal b/test/bang.tal new file mode 100644 index 0000000..8e1fcd8 --- /dev/null +++ b/test/bang.tal @@ -0,0 +1,8 @@ +|100 +!{ @flag $1 } #0000 ;flag STA2 ;flag LDA2 #ffff EOR2 ?{ ;{ #0002 ADD2 } !{ #66 #6c #61 #67 #20 #69 #73 #20 #66 #61 #6c #73 #65 #00 } str/ } BRK + +@str/ ( str* -- ) + LDAk DUP ?{ POP POP2 JMP2r } + #18 DEO + INC2 !/ + diff --git a/test/global.tal b/test/global.tal new file mode 100644 index 0000000..047f461 --- /dev/null +++ b/test/global.tal @@ -0,0 +1,2 @@ +|100 +!{ @i $2 } #007a ;i STA2 !{ @j $2 } #0020 ;j STA2 ;i LDA2 ;j LDA2 SUB2 #18 DEO diff --git a/test/hello.tal b/test/hello.tal new file mode 100644 index 0000000..a75bf6a --- /dev/null +++ b/test/hello.tal @@ -0,0 +1,8 @@ +|100 +!{ @msg $2 } ;{ #0002 ADD2 } !{ #6e #75 #71 #6e #65 #48 #20 #27 #75 #27 #3f #00 } ;msg STA2 ;msg LDA2 str/ + +@str/ ( str* -- ) + LDAk DUP ?{ POP POP2 JMP2r } + #18 DEO + INC2 !/ + diff --git a/test/local.tal b/test/local.tal deleted file mode 100644 index e6b5bf7..0000000 --- a/test/local.tal +++ /dev/null @@ -1,2 +0,0 @@ -|100 @main ( -> ) -!{ &i $2 } #007a ,/i STR2 !{ &j $2 } #0020 ,/j STR2 ,/i LDR2 ,/j LDR2 SUB2 #18 DEO diff --git a/test/str.c b/test/str.c new file mode 100755 index 0000000..3f3ad38 --- /dev/null +++ b/test/str.c @@ -0,0 +1,11 @@ +#include +char* msg = " damage inflicted!\n"; + +int main() { + unsigned AT = 14; + unsigned accuracy = 150; + + unsigned dmg = ((AT * accuracy) / 20) - 3; + + printf("%d%s", dmg, msg); +} \ No newline at end of file diff --git a/test/str.tal b/test/str.tal new file mode 100644 index 0000000..68dd86e --- /dev/null +++ b/test/str.tal @@ -0,0 +1,73 @@ +|100 +!{ @msg $2 } ;{ #0002 ADD2 } !{ #20 #64 #61 #6d #61 #67 #65 #20 #69 #6e #66 #6c #69 #63 #74 #65 #64 #21 #5c #6e #00 } ;msg STA2 +!{ @AT $2 } #000e ;AT STA2 +!{ @accuracy $2 } #0096 ;accuracy STA2 +!{ @dmg $2 } ;AT LDA2 ;accuracy LDA2 MUL2 #0014 DIV2 #0003 SUB2 ;dmg STA2 +;dmg LDA2 nat_to_str_ +str/ ;msg LDA2 +str/ + +@sext + #80 ANDk EQU #ff MUL SWP JMP2r + +@aalloc_ ( size* -- result* ) + OVR2r LIT2r 0004 SUB2r STH2kr INC2 INC2 STA2 + ;mem_length_ LDA2 STH2kr STA2 + ;mem_length_ LDA2k STH2kr INC2 INC2 LDA2 ADD2 SWP2 STA2 + ;mem_ STH2kr LDA2 ADD2 !&return + #0000 + + &return + POP2r JMP2r + +@amcpy_ ( length* from* -- result* ) + OVR2r LIT2r 0008 SUB2r STH2kr #0006 ADD2 STA2 + STH2kr #0004 ADD2 STA2 + STH2kr #0004 ADD2 LDA2 aalloc_ + STH2kr INC2 INC2 STA2 + #0000 STH2kr STA2 + + &begin.1 + STH2kr LDA2 STH2kr #0004 ADD2 LDA2 LTH2 #00 EQU ?&break.1 + STH2kr #0006 ADD2 LDA2 STH2kr LDA2 ADD2 LDA sext + STH2kr INC2 INC2 LDA2 STH2kr LDA2 ADD2 STA + POP + + &continue.1 + STH2kr LDA2k INC2k ROT2 STA2 + POP2 !&begin.1 + + &break.1 + STH2kr INC2 INC2 LDA2 !&return + #0000 + + &return + POP2r JMP2r + +@nat_to_str_ ( n* -- result* ) + OVR2r LIT2r 000a SUB2r STH2kr #0008 ADD2 STA2 + #0005 STH2kr STA2 + + &begin.1 + STH2kr #0008 ADD2 LDA2 #000a OVR2 OVR2 DIV2 MUL2 SUB2 #0030 ADD2 STH2kr INC2 INC2 STH2kr LDA2k #0001 SUB2 SWP2 STA2k + POP2 ADD2 STA + POP STH2kr #0008 ADD2 LDA2k #000a DIV2 SWP2 STA2 + + &continue.1 + #0000 STH2kr #0008 ADD2 LDA2 LTH2 ?&begin.1 + + &break.1 + #0005 STH2kr LDA2 SUB2 STH2kr INC2 INC2 STH2kr LDA2 ADD2 amcpy_ + !&return + #0000 + + &return + POP2r JMP2r + +@str/ ( str* -- ) + LDAk DUP ?{ POP POP2 JMP2r } + #18 DEO + INC2 !/ + +@mem_length_ #0000 +@mem_ \ No newline at end of file diff --git a/test/str.ul b/test/str.ul index efa4a2a..3384cd3 100755 --- a/test/str.ul +++ b/test/str.ul @@ -1,8 +1,8 @@ str msg = " damage inflicted!\n" -int AT = 14; -int accuracy = 150; +nat AT = 14; +nat accuracy = 150; -int dmg = ((AT * accuracy) / 20) - 3; +nat dmg = ((AT * accuracy) / 20) - 3; print(dmg as str); print(msg); \ No newline at end of file