From 38585bf1057c1bbbe55145e401fdffde30d7d3e3 Mon Sep 17 00:00:00 2001 From: zongor Date: Mon, 20 Apr 2026 23:24:38 -0700 Subject: [PATCH] Add arena return to libc, add strbuf, add reality engine rom emitter, remove C emitter --- README.org | 51 ++- arch/linux/main.c | 21 +- build | 5 +- common.h | 4 +- compiler.c | 134 ++++++- compiler.h | 2 + docs/VM.org | 16 + docs/plex_orented_c_example.c | 93 +++++ emit.h | 37 +- emit/c99/emit.c | 384 ------------------- emit/c99/libundar.c | 605 ----------------------------- emit/rer/emit.c | 509 +++++++++++++++++++++++++ emit/uxn/emit.c | 145 ++++++- lexer.c | 20 +- libc.c | 212 +++++++++++ libc.h | 40 ++ list.c | 26 +- list.h | 15 +- strbuf.c | 65 ++++ strbuf.h | 17 + test/global.ul | 4 +- test/plex.c | 696 ---------------------------------- 22 files changed, 1304 insertions(+), 1797 deletions(-) create mode 100644 docs/VM.org create mode 100644 docs/plex_orented_c_example.c delete mode 100644 emit/c99/emit.c delete mode 100644 emit/c99/libundar.c create mode 100644 emit/rer/emit.c create mode 100644 strbuf.c create mode 100644 strbuf.h delete mode 100644 test/plex.c diff --git a/README.org b/README.org index a9dd3c4..25ad74b 100644 --- a/README.org +++ b/README.org @@ -26,52 +26,49 @@ cd undar-lang && ./build * Memory Management -memory is stack based only. +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. -For a limited dynamic style you can create unbounded arrays which go on a pre-allocated memory pool. - -dynamic allocations push pointers within a call frame. when a frame exits, the pointer is reset and the child copys its return value to the end of the parent, thus freeing memory deterministically. - -values passed to functions must be explicitly returned to propagate. if a value is modified in a child function it will change the parents value, unless the size of the structure changes then it will copy the parents value and append it to its own frame with the modification. this allows for the low resource usage of a C but the convenience of a Java/Go without the garbage collection. - -**Core Types** +**Built in Types** | Type | Description | |------+------------------------------------| -| =byte= | Character/8 bit unsigned int | -| =u8= | 8 bit unsigned int | -| =i8= | 8 bit signed int | -| =u16= | 16 bit unsigned int | -| =i16= | 16 bit signed int | +| =byte= | Character (architecture specific) | +| =u8= | exactly 8-bit unsigned int | +| =i8= | exactly 8-bit signed int | +| =u16= | exactly 16-bit unsigned int | +| =i16= | exactly 16-bit signed int | | =u32= | exactly 32-bit unsigned integer | | =i32= | exactly 32-bit signed integer | -| =int= | signed number | -| =nat= | unsigned number | +| =int= | 1 word signed number | +| =nat= | 1 word unsigned number | | =real= | Q16.16 fixed-point real number | | =str= | fat pointer [length + data] string | | =bool= | true/false | -primitive types like int, nat, real, etc. will always be safe to change in child frames. - -complex types like =str,= =plex= or arrays will be references to their location in the memory pool - * Roadmap [[./ROADMAP.org][Compiler, Plex, Immidate mode GUI, Constructive solid geometry, Tunnels, Actor model]] * License -MIT-0 +[[./LICENSE][MIT]] * Inspirations - [[https://plan9.io/][Plan 9]] / 9P - Unified I/O, Tunnels. -- [[https://en.wikipedia.org/wiki/Lisp_(programming_language)][Lisp]] - Live coding, REPL, introspection. - [[https://fortran-lang.org/][Fortran]] - Array semantics. -- [[https://en.wikipedia.org/wiki/C_(programming_language)][C]] / [[https://ziglang.org/][Zig]] - Portability, control, minimalism. -- [[https://lua.org][Lua]] - Friendly syntax, portable, and minimal. -- [[https://www.craftinginterpreters.com/the-lox-language.html][Lox]] - The start of my programming language creation journey. -- [[https://wiki.xxiivv.com/site/uxn.html][Uxn]] - Major inspiration, espeically around the core VM. -- [[http://duskos.org/][Dusk OS]] - A much better system for doing permacomputing. -- [[https://doc.cat-v.org/inferno/4th_edition/dis_VM_specification][Dis VM]] - CISC VM structure +- [[https://en.wikipedia.org/wiki/C_(programming_language)][C]] / [[https://ziglang.org/][Zig]] - Type system, portability, control. +- [[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. - Retro Systems - N64, PS1, Mac Classic, Windows 95 - UI esthetics diff --git a/arch/linux/main.c b/arch/linux/main.c index f803db3..aa7ab62 100644 --- a/arch/linux/main.c +++ b/arch/linux/main.c @@ -2,16 +2,6 @@ #include #include -#define EMBED_FILE(name) \ - void emit_##name(const char *filename) \ - { \ - FILE *f = fopen(filename, "wb"); \ - if(f) { \ - fwrite(name, 1, name##_len, f); \ - fclose(f); \ - } \ - } - static char * readFile(const char *path) { @@ -45,11 +35,11 @@ readFile(const char *path) void print_help() { - printf("Usage: undar [options] file...\nOptions:\n\t-emit={c99|uxn}\tEmitter " - "output, currently C source and Uxn binary.\n\n"); + printf("Usage: undar [options] file...\nOptions:\n\t-emit={rer|uxn}\tEmitter " + "output, currently Uxn tal code and Reality Engine rom.\n\n"); } -#define MEM_SIZE 68000 +#define MEM_SIZE 64000 int main(int argc, char **argv) @@ -65,14 +55,15 @@ main(int argc, char **argv) } Emitter e; - if(seq(argv[1], "-emit=c99")) { - e = c_emitter(); + if(seq(argv[1], "-emit=rer")) { + e = rer_emitter(); } else if(seq(argv[1], "-emit=uxn")) { e = uxn_emitter(); } else { printf("unknown emitter type\n"); return EXIT_FAILURE; } + u8 tape[MEM_SIZE]; Arena a = {tape, 0, MEM_SIZE}; diff --git a/build b/build index 3d1e49e..5c6a11d 100755 --- a/build +++ b/build @@ -73,16 +73,17 @@ esac VM_BUILD_FLAGS="$BUILD_FLAGS -std=c89 -ffreestanding -nostdlib -fno-builtin" ${CC} -c libc.c -o $BUILD_DIR/libc.o $VM_BUILD_FLAGS ${CC} -c list.c -o $BUILD_DIR/list.o $VM_BUILD_FLAGS +${CC} -c strbuf.c -o $BUILD_DIR/strbuf.o $VM_BUILD_FLAGS ${CC} -c lexer.c -o $BUILD_DIR/lexer.o $VM_BUILD_FLAGS ${CC} -c compiler.c -o $BUILD_DIR/compiler.o $VM_BUILD_FLAGS # Set up the final build command case $ARCH in "linux") - BUILD_CMD="$CC -o $BUILD_DIR/undar $SRC_DIR/main.c emit/c/emit.c emit/uxn/emit.c $LINK_FLAGS $BUILD_DIR/libc.o $BUILD_DIR/list.o $BUILD_DIR/lexer.o $BUILD_DIR/compiler.o $BUILD_FLAGS $LINK_FLAGS" + BUILD_CMD="$CC -o $BUILD_DIR/undar $SRC_DIR/main.c emit/rer/emit.c emit/uxn/emit.c $LINK_FLAGS $BUILD_DIR/libc.o $BUILD_DIR/list.o $BUILD_DIR/lexer.o $BUILD_DIR/compiler.o $BUILD_DIR/strbuf.o $BUILD_FLAGS $LINK_FLAGS" ;; "web") - BUILD_CMD="$CC $SRC_DIR/main.c emit/c/emit.c emit/uxn/emit.c $BUILD_DIR/libc.o $BUILD_DIR/list.o $BUILD_DIR/lexer.o $BUILD_DIR/compiler.o -o $BUILD_DIR/undar.html $BUILD_FLAGS $LINK_FLAGS" + BUILD_CMD="$CC $SRC_DIR/main.c emit/rer/emit.c emit/uxn/emit.c $BUILD_DIR/libc.o $BUILD_DIR/list.o $BUILD_DIR/lexer.o $BUILD_DIR/compiler.o -o $BUILD_DIR/undar.html $BUILD_FLAGS $LINK_FLAGS" ;; esac diff --git a/common.h b/common.h index e48daa9..6b66c3c 100644 --- a/common.h +++ b/common.h @@ -1,10 +1,10 @@ #ifndef UNDAR_COMMON_H #define UNDAR_COMMON_H -#include "libc.h" #include "list.h" typedef enum symbol_type_e { + SYMBOL_UNDEFINED, SYMBOL_VOID, SYMBOL_BOOL, SYMBOL_BYTE, @@ -41,4 +41,6 @@ struct symbol_s { List *fields; /* either plex variable fields, or method signatures */ }; +void *node_value(Node *n); + #endif \ No newline at end of file diff --git a/compiler.c b/compiler.c index 1a1eb2d..d8a110a 100644 --- a/compiler.c +++ b/compiler.c @@ -1,4 +1,5 @@ #include "compiler.h" +#include "common.h" #include "emit.h" Emitter emitter; @@ -13,7 +14,7 @@ void scope_push() { Scope *child = aalloc(arena, sizeof(Scope)); - child->symbols = new_list(arena); + child->symbols = List_init(arena); child->parent = parser.current_scope; parser.current_scope = child; @@ -34,7 +35,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); + Symbol *sym = List_get(scope->symbols, i); if(sleq(sym->name, name, name_length)) return sym; } @@ -55,11 +56,11 @@ scope_add_symbol(const char *name, u32 name_length, SymbolType type, u32 size) sym->size = size; sym->ref = 0; if(type == SYMBOL_PLEX || type == SYMBOL_METHOD || type == SYMBOL_TRAIT) { - sym->args = new_list(arena); - sym->fields = new_list(arena); + sym->args = List_init(arena); + sym->fields = List_init(arena); } - list_push(arena, parser.current_scope->symbols, sym, sizeof(Symbol)); + List_push(arena, parser.current_scope->symbols, sym, sizeof(Symbol)); return sym; } @@ -130,8 +131,7 @@ binary() TokenType operatorType = parser.previous.type; ParseRule *rule = get_rule(operatorType); - if(emitter.notation == POSTFIX) - parse_precedence((Precedence)(rule->precedence + 1)); + parse_precedence((Precedence)(rule->precedence + 1)); switch(operatorType) { case TOKEN_BANG_EQ: @@ -167,9 +167,6 @@ binary() default: return; } - - if(emitter.notation == INFIX) - parse_precedence((Precedence)(rule->precedence + 1)); } static void @@ -206,12 +203,104 @@ variable() parser.previous.line); } + parser.current_type = sym->type; emitter.emit_variable(sym); } static void cast_type() { + TokenType cast_type = parser.current.type; + SymbolType st = 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); + } + + 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); + } + 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); + } + 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); + } + break; + } + default: + emitter.error("Not castable to this type", 26, parser.previous.line); + } + + emitter.emit_open_paren(); + + expression(); + + emitter.emit_close_paren(); } static void @@ -226,61 +315,71 @@ variable_declaration() case TOKEN_TYPE_INT: { size = emitter.emit_int_type(parser.current.start, parser.current.length); 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); 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); 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); 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); 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); 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); 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); 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); 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); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_I16, size); + parser.current_type = SYMBOL_I16; break; } default: { @@ -292,11 +391,14 @@ variable_declaration() advance(); if(match(TOKEN_EQ)) { + emitter.emit_set_value(); expression(); emitter.emit_constant(var.start, var.length); } consume(TOKEN_SEMICOLON); + emitter.emit_end_statement(); + parser.current_type = SYMBOL_UNDEFINED; } static void @@ -317,10 +419,10 @@ declaration() static void print_statement() { - if(emitter.notation == INFIX) emitter.emit_print(); expression(); consume(TOKEN_SEMICOLON); - if(emitter.notation == POSTFIX) emitter.emit_print(); + emitter.emit_end_statement(); + emitter.emit_print(); } static void @@ -372,7 +474,7 @@ static void unary() { TokenType operatorType = parser.previous.type; - if(emitter.notation == POSTFIX) parse_precedence(PREC_UNARY); + parse_precedence(PREC_UNARY); switch(operatorType) { case TOKEN_MINUS: @@ -384,8 +486,6 @@ unary() default: return; } - - if(emitter.notation == INFIX) parse_precedence(PREC_UNARY); } ParseRule rules[] = { @@ -413,7 +513,7 @@ ParseRule rules[] = { /* TOKEN_KEYWORD_CONST */ {nil, nil, PREC_NONE}, /* TOKEN_KEYWORD_IF */ {nil, nil, PREC_NONE}, /* TOKEN_KEYWORD_IS */ {nil, nil, PREC_NONE}, - /* TOKEN_KEYWORD_AS */ {nil, cast_type, PREC_NONE}, + /* TOKEN_KEYWORD_AS */ {nil, cast_type, PREC_CAST}, /* TOKEN_KEYWORD_ELSE */ {nil, nil, PREC_NONE}, /* TOKEN_KEYWORD_WHILE */ {nil, nil, PREC_NONE}, /* TOKEN_KEYWORD_FOR */ {nil, nil, PREC_NONE}, diff --git a/compiler.h b/compiler.h index 6012fad..0735a59 100644 --- a/compiler.h +++ b/compiler.h @@ -24,6 +24,7 @@ typedef enum { PREC_TERM, /* + - */ PREC_FACTOR, /* * / */ PREC_UNARY, /* ! - */ + PREC_CAST, /* as */ PREC_CALL, /* . () */ PREC_PRIMARY } Precedence; @@ -40,6 +41,7 @@ struct parser_s { Scope *current_scope; Token current; Token previous; + SymbolType current_type; }; bool compile(Arena *a, Emitter e, char *source); diff --git a/docs/VM.org b/docs/VM.org new file mode 100644 index 0000000..c37ab26 --- /dev/null +++ b/docs/VM.org @@ -0,0 +1,16 @@ +Ok this actually sounds similar to my soluition. I have a variation on the smalltalk model, + + +** Reality Engine VM + +I imagine that this is running on a turing machine with 2 stacks (one operation, one stack); harvard arch. + +when a function gets called the function allocates N many "locals" onto the tape, +primitves are just the raw values, +complex values in locals are stored as ptrs to the positions in memory following the locals array. + +Instead of just arrays, each array is wrapped in a linked list, +so its a ptr to the next link followed by the size followed by an array of raw data. +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. + diff --git a/docs/plex_orented_c_example.c b/docs/plex_orented_c_example.c new file mode 100644 index 0000000..75bad4e --- /dev/null +++ b/docs/plex_orented_c_example.c @@ -0,0 +1,93 @@ +#define __UNDAR_ARENA_SIZE__ 64000 + +#include "../libc.h" +#include "../strbuf.h" +#include + +typedef struct Point Point; +struct Point { + u32 x; + u32 y; +}; + +Point * +Point_init(Arena *a, u32 x, u32 y) +{ + Point *this = (Point *)aalloc(a, sizeof(Point)); + this->x = x; + this->y = y; + return this; +} + +char* +Point_toS(Arena *a, Point *this) +{ + u32 __UNDAR_FN_CHECKPOINT_REF__ = a->count; + + StrBuf *buf = StrBuf_init(a); + StrBuf_append(a, buf, "[x:"); + StrBuf_append(a, buf,nat_to_string(a, this->x)); + StrBuf_append(a, buf, ", y:"); + StrBuf_append(a, buf,nat_to_string(a, this->y)); + StrBuf_append(a, buf, "]"); + + ARENA_RETURN_STRBUF(a, __UNDAR_FN_CHECKPOINT_REF__, buf); +} + +typedef struct Rect Rect; +struct Rect { + Point top_left; + Point bottom_right; + u32 width; + u32 height; +}; + +Rect * +Rect_init(Arena *a, Point *tl, Point *br, u32 width, u32 height) +{ + Rect *this = (Rect *)aalloc(a, sizeof(Rect)); + mcpy(&this->top_left, tl, sizeof(Point)); + mcpy(&this->bottom_right, br, sizeof(Point)); + this->width = width; + this->height = height; + return this; +} + +char* +Rect_toS(Arena *a, Rect *this) +{ + u32 __UNDAR_FN_CHECKPOINT_REF__ = a->count; + + StrBuf *buf = StrBuf_init(a); + StrBuf_append(a, buf, "[top_left: "); + StrBuf_append(a, buf,Point_toS(a,&this->top_left)); + StrBuf_append(a, buf,", bottom_right: "); + StrBuf_append(a, buf,Point_toS(a,&this->bottom_right)); + StrBuf_append(a, buf, ", width:"); + StrBuf_append(a, buf,nat_to_string(a,this->width)); + StrBuf_append(a, buf, ", height:"); + StrBuf_append(a, buf,nat_to_string(a,this->height)); + StrBuf_append(a, buf, "]"); + + ARENA_RETURN_STRBUF(a, __UNDAR_FN_CHECKPOINT_REF__, buf); +} + +Rect * +create_geometry(Arena *a) +{ + u32 __UNDAR_FN_CHECKPOINT_REF__ = a->count; + + Point *tl = Point_init(a, 10, 20); + Point *br = Point_init(a, 100, 200); + Rect *final_rect = Rect_init(a, tl, br, 90, 180); + + ARENA_RETURN(a, __UNDAR_FN_CHECKPOINT_REF__, final_rect, Rect); +} + +int main() { + u8 tape[__UNDAR_ARENA_SIZE__]; + Arena arena = {tape, 0, __UNDAR_ARENA_SIZE__}; + Rect *r = create_geometry(&arena); + printf("%s\n", Rect_toS(&arena, r)); + return 0; +} diff --git a/emit.h b/emit.h index 4155eaf..a033924 100644 --- a/emit.h +++ b/emit.h @@ -4,17 +4,6 @@ #include "common.h" #include "libc.h" -typedef enum notation_type_e { - PREFIX, - INFIX, - POSTFIX -} NotationType; - -typedef enum output_type_e { - BINARY, - TEXT -} OutputType; - typedef void (*SymbolEmit)(Symbol *sym); typedef void (*ErrorMsg)(const char *str, i32 length, i32 line); typedef void (*VoidArgEmit)(); @@ -23,8 +12,6 @@ typedef i32 (*TypeVariableEmit)(const char *str, i32 length); typedef struct emitter_s Emitter; struct emitter_s { - NotationType notation; - OutputType output; ErrorMsg error; VoidArgEmit prolog; VoidArgEmit epilogue; @@ -78,9 +65,31 @@ struct emitter_s { VoidArgEmit emit_open; VoidArgEmit emit_close; VoidArgEmit emit_stat; + VoidArgEmit emit_end_statement; + VoidArgEmit emit_set_value; + VoidArgEmit emit_plex_def; + VoidArgEmit emit_cast_int_to_nat; + VoidArgEmit emit_cast_int_to_real; + VoidArgEmit emit_cast_int_to_str; + VoidArgEmit emit_cast_nat_to_int; + VoidArgEmit emit_cast_nat_to_real; + VoidArgEmit emit_cast_nat_to_str; + VoidArgEmit emit_cast_real_to_int; + VoidArgEmit emit_cast_real_to_nat; + VoidArgEmit emit_cast_real_to_str; + VoidArgEmit emit_strbuf_init; + VoidArgEmit emit_strbuf_append; + VoidArgEmit emit_strbuf_to_str; + VoidArgEmit emit_arena_fn_call; + VoidArgEmit emit_arena_fn_return_plex; + VoidArgEmit emit_arena_fn_return_array; + VoidArgEmit emit_arena_fn_return_strbuf; + VoidArgEmit emit_cast_str_to_int; + VoidArgEmit emit_cast_str_to_nat; + VoidArgEmit emit_cast_str_to_real; }; -Emitter c_emitter(); +Emitter rer_emitter(); Emitter uxn_emitter(); #endif diff --git a/emit/c99/emit.c b/emit/c99/emit.c deleted file mode 100644 index 77ed4a6..0000000 --- a/emit/c99/emit.c +++ /dev/null @@ -1,384 +0,0 @@ -#include "../../emit.h" -#include -#include - -void -c99_emit_error(const char *str, i32 length, i32 line) -{ - printf("Error at line: %d (%.*s)\n ", line, length, str); - exit(1); -} - -void -c99_prolog() -{ -} - -void -c99_epilogue() -{ -} - -void -c99_emit_add() -{ - printf("+ "); -} - -void -c99_emit_sub() -{ - printf("- "); -} - -void -c99_emit_mul() -{ - printf("* "); -} - -void -c99_emit_div() -{ - printf("/ "); -} - -void -c99_emit_lt() -{ - printf("< "); -} - -void -c99_emit_le() -{ - printf("<= "); -} - -void -c99_emit_gt() -{ - printf("> "); -} - -void -c99_emit_ge() -{ - printf(">= "); -} - -void -c99_emit_ne() -{ - printf("!= "); -} - -void -c99_emit_eq() -{ - printf("== "); -} - -void -c99_emit_false() -{ - printf("false "); -} - -void -c99_emit_true() -{ - printf("true "); -} - -void -c99_emit_nil() -{ - printf("nil "); -} - -void -c99_emit_neg() -{ - printf("-"); -} - -void -c99_emit_not() -{ - printf("!"); -} - -void -c99_emit_void() -{ -} - -i32 -c99_emit_bool_type(const char *str, i32 length) -{ - printf("%.*s ", length, str); - return 1; -} - -i32 -c99_emit_byte_type(const char *str, i32 length) -{ - printf("%.*s ", length, str); - return 1; -} - -i32 -c99_emit_int_type(const char *str, i32 length) -{ - printf("%.*s ", length, str); - return 2; -} - -i32 -c99_emit_nat_type(const char *str, i32 length) -{ - printf("%.*s ", length, str); - return 2; -} - -i32 -c99_emit_real_type(const char *str, i32 length) -{ - printf("%.*s ", length, str); - return 2; -} - -i32 -c99_emit_str_type(const char *str, i32 length) -{ - printf("%.*s ", length, str); - return 2; -} - -i32 -c99_emit_u8_type(const char *str, i32 length) -{ - printf("%.*s ", length, str); - return 1; -} - -i32 -c99_emit_i8_type(const char *str, i32 length) -{ - printf("%.*s ", length, str); - return 1; -} - -i32 -c99_emit_i16_type(const char *str, i32 length) -{ - printf("%.*s ", length, str); - return 2; -} - -i32 -c99_emit_u16_type(const char *str, i32 length) -{ - printf("%.*s ", length, str); - return 2; -} - -i32 -c99_emit_i32_type(const char *str, i32 length) -{ - printf("%.*s ", length, str); - return 4; -} - -i32 -c99_emit_u32_type(const char *str, i32 length) -{ - printf("%.*s ", length, str); - return 4; -} - -i32 -c99_emit_f32_type(const char *str, i32 length) -{ - printf("%.*s ", length, str); - return 4; -} - -void -c99_emit_int(const char *str, i32 length) -{ - printf("%.*s ", length, str); -} - -void -c99_emit_nat(const char *str, i32 length) -{ - printf("%.*s ", length, str); -} - -void -c99_emit_real(const char *str, i32 length) -{ - printf("%.*s ", length, str); -} - -void -c99_emit_byte(const char *str, i32 length) -{ - printf("%.*s ", length, str); -} - -void -c99_emit_str(const char *str, i32 length) -{ - printf("%.*s ", length, str); -} - -void -c99_emit_array() -{ -} - -void -c99_emit_function() -{ -} - -void -c99_emit_plex() -{ -} - -void -c99_emit_method() -{ -} - -void -c99_emit_trait() -{ -} - -void -c99_emit_const() -{ -} - -void -c99_emit_print() -{ - printf("printf"); -} - -void -c99_emit_open_paren() -{ - printf("("); -} - -void -c99_emit_close_paren() -{ - printf(")"); -} - -void -c99_emit_constant(const char *str, i32 length) -{ - USED(str); - USED(length); -} - -void -c99_emit_variable(Symbol *sym) -{ - USED(sym); -} - -void -c99_emit_write() -{ -} - -void -c99_emit_read() -{ -} - -void -c99_emit_open() -{ -} - -void -c99_emit_close() -{ -} - -void -c99_emit_stat() -{ -} - -Emitter -c99_emitter() -{ - return (Emitter){ - INFIX, - TEXT, - c99_emit_error, - c99_prolog, - c99_epilogue, - c99_emit_add, - c99_emit_sub, - c99_emit_mul, - c99_emit_div, - c99_emit_lt, - c99_emit_le, - c99_emit_gt, - c99_emit_ge, - c99_emit_ne, - c99_emit_eq, - c99_emit_false, - c99_emit_true, - c99_emit_nil, - c99_emit_void, - c99_emit_int, - c99_emit_nat, - c99_emit_real, - c99_emit_byte, - c99_emit_str, - c99_emit_bool_type, - c99_emit_byte_type, - c99_emit_int_type, - c99_emit_nat_type, - c99_emit_real_type, - c99_emit_str_type, - c99_emit_u8_type, - c99_emit_i8_type, - c99_emit_i16_type, - c99_emit_u16_type, - c99_emit_i32_type, - c99_emit_u32_type, - c99_emit_f32_type, - c99_emit_array, - c99_emit_function, - c99_emit_plex, - c99_emit_method, - c99_emit_trait, - c99_emit_const, - c99_emit_print, - c99_emit_neg, - c99_emit_not, - c99_emit_open_paren, - c99_emit_close_paren, - c99_emit_constant, - c99_emit_variable, - c99_emit_write, - c99_emit_read, - c99_emit_open, - c99_emit_close, - c99_emit_stat, - }; -} diff --git a/emit/c99/libundar.c b/emit/c99/libundar.c deleted file mode 100644 index a495686..0000000 --- a/emit/c99/libundar.c +++ /dev/null @@ -1,605 +0,0 @@ -#if defined(__has_include) -#if __has_include() -#define HAVE_STDINT 1 -#endif -#if __has_include() -#define HAVE_STDBOOL 1 -#endif -#if __has_include() -#define HAVE_STDDEF 1 -#endif -#endif - -#ifdef HAVE_STDINT -#include -typedef uint8_t u8; -typedef int8_t i8; -typedef uint16_t u16; -typedef int16_t i16; -typedef uint32_t u32; -typedef int32_t i32; -typedef int32_t r32; -typedef float f32; -#else -typedef unsigned char u8; -typedef signed char i8; -typedef unsigned short u16; -typedef signed short i16; -typedef unsigned int u32; -typedef signed int i32; -typedef signed int r32; -typedef float f32; -#endif - -#ifdef HAVE_STDBOOL -#include -#else -#define true 1 -#define false 0 -typedef u8 bool; -#endif - -#ifdef HAVE_STDDEF -#include -#define nil NULL -#else -#define nil ((void *)0) -#endif - -#define I8_MIN -128 -#define I8_MAX 127 -#define U8_MAX 255 - -#define I16_MIN -32768 -#define I16_MAX 32767 -#define U16_MAX 65535 - -#define I32_MIN -2147483648 -#define I32_MAX 2147483647 -#define U32_MAX 4294967295 - -#define FIXED_CONST 65536.0f - -#define AS_INT(v) ((i32)(v)) -#define AS_NAT(v) ((u32)(v)) -#define AS_REAL(v) ((r32)(v)) -#define FLOAT_TO_REAL(v) (((r32)(v)) * FIXED_CONST) -#define REAL_TO_FLOAT(v) (((f32)(v)) / FIXED_CONST) - -#define USED(x) ((void)(x)) - -#define MAX_LEN_REAL32 12 -#define MAX_LEN_INT32 11 -const char radix_set[11] = "0123456789"; - -typedef struct arena_s Arena; -struct arena_s { - u8 *tape; - u32 count; - u32 capacity; -}; - -typedef bool (*compare_fn)(void *data, void *target); -typedef bool (*list_iter_fn)(void *data); - -static inline void -mcpy(void *to, void *from, u32 length) -{ - u8 *src, *dest; - if(to == nil || from == nil) return; - - src = (u8 *)from; - dest = (u8 *)to; - - while(length-- > 0) *(dest++) = *(src++); - return; -} - -static inline i32 -scpy(char *to, const char *from, u32 length) -{ - u32 i; - if(to == nil || from == nil) return -1; - if(length == 0) return 0; - for(i = 0; i < length && from[i] != '\0'; i++) to[i] = from[i]; - to[i] = '\0'; - return 0; -} - -static inline bool -seq(const char *s1, const char *s2) -{ - if(s1 == nil && s2 == nil) return true; - if(s1 == nil || s2 == nil) return false; - - while(*s1 && *s2) { - if(*s1 != *s2) return false; - s1++; - s2++; - } - - return (*s1 == '\0' && *s2 == '\0'); -} - -static inline bool -sleq(const char *s1, const char *s2, u32 length) -{ - u32 i; - if(s1 == nil && s2 == nil) return true; - if(s1 == nil || s2 == nil) return false; - - i = 0; - while(i < length && *s1 && *s2) { - if(*s1 != *s2) return false; - s1++; - s2++; - i++; - } - if(i == length) return true; - return (*s1 == '\0' && *s2 == '\0'); -} - -static inline u32 -slen(const char *str) -{ - u32 i; - if(str == nil) return 0; - for(i = 0; str[i] != '\0'; i++); - return i; -} - -static inline u32 -snlen(const char *str, u32 max_len) -{ - u32 i; - if(str == nil) return 0; - for(i = 0; i < max_len && str[i] != '\0'; i++); - return i; -} - -u8 tape[__UNDAR_ARENA_SIZE__]; -Arena arena = {tape, 0, __UNDAR_ARENA_SIZE__}; - -static inline void * -aalloc(u32 size) -{ - u32 pos; - if(arena.count + size > arena.capacity) return nil; - - pos = arena.count; - arena.count += size; - return (void *)&arena.tape[pos]; -} - -static inline void * -aend() -{ - i32 pos = arena.count; - return (void *)&arena.tape[pos]; -} - -static inline void * -areturn(u32 checkpoint, const void *src, u32 size) -{ - void *dest; - if(src == nil) return nil; - - u32 current = arena.count; - - dest = (void *)&arena.tape[checkpoint]; - if(src == dest) return dest; - - mcpy(dest, (void *)src, size); - arena.count = checkpoint + size; - - // zero out the end of the memory copy (for strings mostly) - arena.tape[arena.count] = 0; - - return dest; -} - -#define ARENA_RETURN(ckpt, src_ptr, type) \ - return (type *)areturn((ckpt), (src_ptr), sizeof(type)) - -#define ARENA_RETURN_ARRAY(ckpt, src_ptr, type, count) \ - return (type *)areturn((ckpt), (src_ptr), sizeof(type) * (count)) - -#define ARENA_RETURN_STR(ckpt, src_ptr) \ - return (char *)areturn((ckpt), (src_ptr), slen(src_ptr)) - -#define ARENA_RETURN_STRBUF(ckpt, sbuf) \ - char *to_return = StrBuf_toS(sbuf); \ - return (char *)areturn((ckpt), (to_return), slen(to_return)) - -static inline r32 -int_to_real(i32 i) -{ - return i << 16; -} -static inline i32 -real_to_int(r32 f) -{ - return f >> 16; -} -static inline r32 -float_to_real(f32 f) -{ - return FLOAT_TO_REAL(f); -} -static inline f32 -real_to_float(r32 r) -{ - return REAL_TO_FLOAT(r); -} -static inline r32 -real_add(r32 a, r32 b) -{ - return a + b; -} -static inline r32 -real_sub(r32 a, r32 b) -{ - return a - b; -} -static inline r32 -real_mul(r32 a, r32 b) -{ - - r32 src1_whole = (r32)a >> 16; - r32 src2_whole = (r32)b >> 16; - - r32 src1_decimal = (r32)a & 16; - r32 src2_decimal = (r32)b & 16; - - r32 result = 0; - result += (src1_whole * src2_whole) << 16; - result += (src1_whole * src2_decimal); - result += (src1_decimal * src2_whole); - result += ((src1_decimal * src2_decimal) >> 16) & 16; - - return result; -} -static inline r32 -real_div(r32 a, r32 b) -{ - r32 result; - - r32 src1_val = (r32)a; - r32 src2_val = (r32)b; - u32 src2_reciprocal = 1; - - src2_reciprocal <<= 31; - src2_reciprocal = (u32)(src2_reciprocal / src2_val); - result = src1_val * src2_reciprocal; - result <<= 1; - - return result; -} -static inline r32 -real_eq(r32 a, r32 b) -{ - return a == b; -} -static inline r32 -real_ne(r32 a, r32 b) -{ - return a != b; -} -static inline r32 -real_lt(r32 a, r32 b) -{ - return a < b; -} -static inline r32 -real_le(r32 a, r32 b) -{ - return a <= b; -} -static inline r32 -real_gt(r32 a, r32 b) -{ - return a > b; -} -static inline r32 -real_ge(r32 a, r32 b) -{ - return a >= b; -} -static inline r32 -real_neg(r32 f) -{ - return -f; -} -static inline r32 -real_abs(r32 f) -{ - return (f < 0) ? -f : f; -} - -static inline char * -ascpy(const char *start, u32 length) -{ - char *str; - if(!start) return nil; - str = (char *)aalloc(length + 1); - if(!str) return nil; - scpy(str, start, length); - return str; -} - -static inline void * -amcpy(void *from, u32 length) -{ - void *ptr; - if(!from) return nil; - ptr = aalloc(length); - if(!ptr) return nil; - mcpy(ptr, from, length); - return ptr; -} - -static inline char* -int_to_string(i32 v) -{ - char buffer[MAX_LEN_INT32] = {0}; - i32 n; - u32 i = MAX_LEN_INT32; - bool neg; - n = v; - neg = n < 0; - - if(neg) n = -n; - - do { - buffer[--i] = radix_set[n % 10]; - n /= 10; - } while(n > 0); - if(neg) buffer[--i] = '-'; - /* Ensure at least one digit is written for 0 */ - if(v == 0) buffer[--i] = '0'; - - return ascpy(buffer + i, MAX_LEN_INT32 - i); -} - -static inline char* -nat_to_string(u32 v) -{ - char buffer[MAX_LEN_INT32] = {0}; - u32 n; - u32 i = MAX_LEN_INT32; - n = v; - - do { - buffer[--i] = radix_set[n % 10]; - n /= 10; - } while(n > 0); - /* Ensure at least one digit is written for 0 */ - if(v == 0) buffer[--i] = '0'; - - return ascpy(buffer + i, MAX_LEN_INT32 - i); -} - -static inline char* -real_to_string(r32 q) -{ - char buffer[MAX_LEN_REAL32] = {0}; - bool neg; - i32 int_part; - u32 frac_part; - u32 i = MAX_LEN_REAL32; - - if(q < 0) q = -q; - - int_part = q >> 16; - frac_part = q & 0xFFFF; - - do { - buffer[--i] = radix_set[frac_part % 10]; - frac_part /= 10; - } while(frac_part > 0); - - buffer[--i] = '.'; - - neg = int_part < 0; - - if(neg) int_part = -int_part; - - do { - buffer[--i] = radix_set[int_part % 10]; - int_part /= 10; - } while(int_part > 0); - - if(neg) buffer[--i] = '-'; - - return ascpy(buffer + i, MAX_LEN_REAL32 - i); -} - -typedef struct node_s Node; -struct node_s { - u32 size; - struct node_s *next; -}; - -typedef struct list_s List; -struct list_s { - Node *head; - Node *tail; - u32 count; -}; - -typedef bool (*compare_fn)(void *data, void *target); -typedef bool (*list_iter_fn)(void *data); - -List * -List_init(Arena *arena) -{ - List *l = (List*)aalloc(sizeof(List)); - if (!l) return nil; - - l->head = nil; - l->tail = nil; - l->count = 0; - - return l; -} - -void * -node_value(Node *n) -{ - return (void *)((u8 *)n + sizeof(Node)); -} - -void * -List_push(List *list, void *data, u32 data_size) -{ - void *dest; - void *ptr = aalloc(sizeof(Node) + data_size); - Node *node = (Node *)ptr; - - if (!node) return nil; - - node->size = data_size; - node->next = nil; - - if (!list->head) { - list->head = list->tail = node; - } else { - list->tail->next = node; - list->tail = node; - } - - list->count++; - - 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; - } -} - -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); -} - -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 * -List_find(List *list, compare_fn compare, void *target) -{ - Node *curr; - void *data; - - 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; -} - -typedef struct strbuf_s StrBuf; -struct strbuf_s { - Node *head; - Node *tail; - u32 count; -}; - -StrBuf * -StrBuf_init() -{ - StrBuf *l = (StrBuf*)aalloc(sizeof(StrBuf)); - if (!l) return nil; - - l->head = nil; - l->tail = nil; - l->count = 0; - - return l; -} - -void * -StrBuf_append(StrBuf *buf, char *str) -{ - u32 length = slen(str); - - void *dest; - void *ptr = aalloc(sizeof(Node) + length); - Node *node = (Node *)ptr; - - if (!node) return nil; - - node->next = nil; - node->size = length; - - if (!buf->head) { - buf->head = buf->tail = node; - } else { - buf->tail->next = node; - buf->tail = node; - } - - buf->count++; - - dest = node_value(node); - if (str && length > 0) { - mcpy(dest, str, length); - } - - return dest; -} - -char * -StrBuf_toS(StrBuf *buf) -{ - Node *curr; - char *tmp_str; - - char *str = (char *)aend(); - - if (!buf || !str) return nil; - - curr = buf->head; - while (curr) { - tmp_str = node_value(curr); - amcpy(tmp_str, curr->size); - curr = curr->next; - } - - return str; -} \ No newline at end of file diff --git a/emit/rer/emit.c b/emit/rer/emit.c new file mode 100644 index 0000000..f9f2fbb --- /dev/null +++ b/emit/rer/emit.c @@ -0,0 +1,509 @@ +#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); + exit(1); +} + +void +rer_mem(u32 a) +{ + USED(a); +} + +void +rer_prolog() +{ +} + +void +rer_epilogue() +{ + +} + +void +rer_emit_add() +{ +} + +void +rer_emit_sub() +{ +} + +void +rer_emit_mul() +{ +} + +void +rer_emit_div() +{ +} + +void +rer_emit_lt() +{ +} + +void +rer_emit_le() +{ +} + +void +rer_emit_gt() +{ +} + +void +rer_emit_ge() +{ +} + +void +rer_emit_ne() +{ +} + +void +rer_emit_eq() +{ +} + +void +rer_emit_false() +{ +} + +void +rer_emit_true() +{ +} + +void +rer_emit_nil() +{ +} + +void +rer_emit_neg() +{ +} + +void +rer_emit_not() +{ +} + +void +rer_emit_void() +{ +} + +i32 +rer_emit_bool_type(const char *str, i32 length) +{ + USED(str);USED(length); + return 1; +} + +i32 +rer_emit_byte_type(const char *str, i32 length) +{ + USED(str);USED(length); + return 1; +} + +i32 +rer_emit_int_type(const char *str, i32 length) +{ + USED(str);USED(length); + return 2; +} + +i32 +rer_emit_nat_type(const char *str, i32 length) +{ + USED(str);USED(length); + return 2; +} + +i32 +rer_emit_real_type(const char *str, i32 length) +{ + USED(str);USED(length); + return 2; +} + +i32 +rer_emit_str_type(const char *str, i32 length) +{ + USED(str);USED(length); + return 2; +} + +i32 +rer_emit_u8_type(const char *str, i32 length) +{ + USED(str);USED(length); + return 1; +} + +i32 +rer_emit_i8_type(const char *str, i32 length) +{ + USED(str);USED(length); + return 1; +} + +i32 +rer_emit_i16_type(const char *str, i32 length) +{ + USED(str);USED(length); + return 2; +} + +i32 +rer_emit_u16_type(const char *str, i32 length) +{ + USED(str);USED(length); + return 2; +} + +i32 +rer_emit_i32_type(const char *str, i32 length) +{ + USED(str);USED(length); + return 4; +} + +i32 +rer_emit_u32_type(const char *str, i32 length) +{ + USED(str);USED(length); + return 4; +} + +i32 +rer_emit_f32_type(const char *str, i32 length) +{ + USED(str);USED(length); + return 4; +} + +void +rer_emit_int(const char *str, i32 length) +{ + i32 i = (i32)strtol(str, nil, 10); + printf("#%04x ", i); + USED(length); +} + +void +rer_emit_nat(const char *str, i32 length) +{ + u32 i = (u32)strtol(str, nil, 10); + printf("#%04x ", i); + USED(length); +} + +void +rer_emit_real(const char *str, i32 length) +{ + USED(str); + USED(length); + /// TODO: implement this +} + +void +rer_emit_byte(const char *str, i32 length) +{ + u8 i = (u8)strtol(str, nil, 10); + printf("#%04x ", i); + USED(length); +} + +void +rer_emit_str(const char *str, i32 length) +{ + printf("\"%.*s ", length, str); +} + +void +rer_emit_constant(const char *str, i32 length) +{ + printf(";%.*s STA2 ", length, str); +} + +void +rer_emit_array() +{ +} + +void +rer_emit_function() +{ +} + +void +rer_emit_plex() +{ +} + +void +rer_emit_method() +{ +} + +void +rer_emit_trait() +{ +} + +void +rer_emit_const() +{ +} + +void +rer_emit_print() +{ + printf("print "); +} + +void +rer_emit_open_paren() +{ +} + +void +rer_emit_close_paren() +{ +} + +void +rer_emit_variable(Symbol *sym) +{ + printf(";%.*s LDA2 ", sym->name_length, sym->name); +} + +void +rer_emit_write() +{ +} + +void +rer_emit_read() +{ +} + +void +rer_emit_open() +{ +} + +void +rer_emit_close() +{ +} + +void +rer_emit_stat() +{ +} + +void +rer_emit_end_statement() +{ +} + +void +rer_emit_set_value() +{ +} + +void +rer_emit_plex_def() +{ +} + +void +rer_emit_cast_int_to_nat() +{ +} + +void +rer_emit_cast_int_to_real() +{ +} + +void +rer_emit_cast_int_to_str() +{ +} + +void +rer_emit_cast_nat_to_int() +{ +} + +void +rer_emit_cast_nat_to_real() +{ +} + +void +rer_emit_cast_nat_to_str() +{ +} + +void +rer_emit_cast_real_to_int() +{ +} + +void +rer_emit_cast_real_to_nat() +{ +} + +void +rer_emit_cast_real_to_str() +{ +} + +void +rer_emit_strbuf_init() +{ +} + +void +rer_emit_strbuf_append() +{ +} + +void +rer_emit_strbuf_to_str() +{ +} + +void +rer_emit_arena_fn_call() +{ +} + +void +rer_emit_arena_fn_return_plex() +{ +} + +void +rer_emit_arena_fn_return_array() +{ +} + +void +rer_emit_arena_fn_return_strbuf() +{ +} + +void +rer_emit_cast_str_to_int() +{ +} +void +rer_emit_cast_str_to_nat() +{ +} +void +rer_emit_cast_str_to_real() +{ +} + +Emitter +rer_emitter() +{ + return (Emitter){ + rer_emit_error, + 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_bool_type, + rer_emit_byte_type, + rer_emit_int_type, + rer_emit_nat_type, + rer_emit_real_type, + rer_emit_str_type, + rer_emit_u8_type, + rer_emit_i8_type, + rer_emit_i16_type, + rer_emit_u16_type, + rer_emit_i32_type, + rer_emit_u32_type, + rer_emit_f32_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_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_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, + }; +} diff --git a/emit/uxn/emit.c b/emit/uxn/emit.c index 5a5707c..71d4d6d 100644 --- a/emit/uxn/emit.c +++ b/emit/uxn/emit.c @@ -68,6 +68,12 @@ uxn_emit_error(const char *str, i32 length, i32 line) exit(1); } +void +uxn_mem(u32 a) +{ + USED(a); +} + void uxn_prolog() { @@ -83,7 +89,7 @@ uxn_epilogue() &>wp \n\ LDAk DUP ?{ POP POP2 JMP2r } \n\ #18 DEO \n\ - INC2 !&>wp\n\n"); + INC2 !&>wp\n\n"); printf("@num-to-string $12\n"); printf("@heap\n"); } @@ -365,7 +371,8 @@ uxn_emit_close_paren() } void -uxn_emit_variable(Symbol *sym) { +uxn_emit_variable(Symbol *sym) +{ printf(";%.*s LDA2 ", sym->name_length, sym->name); } @@ -394,12 +401,118 @@ uxn_emit_stat() { } +void +uxn_emit_end_statement() +{ +} + +void +uxn_emit_set_value() +{ +} + +void +uxn_emit_plex_def() +{ +} + +void +uxn_emit_cast_int_to_nat() +{ +} + +void +uxn_emit_cast_int_to_real() +{ +} + +void +uxn_emit_cast_int_to_str() +{ +} + +void +uxn_emit_cast_nat_to_int() +{ +} + +void +uxn_emit_cast_nat_to_real() +{ +} + +void +uxn_emit_cast_nat_to_str() +{ +} + +void +uxn_emit_cast_real_to_int() +{ +} + +void +uxn_emit_cast_real_to_nat() +{ +} + +void +uxn_emit_cast_real_to_str() +{ +} + +void +uxn_emit_strbuf_init() +{ +} + +void +uxn_emit_strbuf_append() +{ +} + +void +uxn_emit_strbuf_to_str() +{ +} + +void +uxn_emit_arena_fn_call() +{ +} + +void +uxn_emit_arena_fn_return_plex() +{ +} + +void +uxn_emit_arena_fn_return_array() +{ +} + +void +uxn_emit_arena_fn_return_strbuf() +{ +} + +void +uxn_emit_cast_str_to_int() +{ +} +void +uxn_emit_cast_str_to_nat() +{ +} +void +uxn_emit_cast_str_to_real() +{ +} + Emitter uxn_emitter() { return (Emitter){ - POSTFIX, - BINARY, uxn_emit_error, uxn_prolog, uxn_epilogue, @@ -452,6 +565,28 @@ uxn_emitter() uxn_emit_read, uxn_emit_open, uxn_emit_close, - uxn_emit_stat, + uxn_emit_stat, + uxn_emit_end_statement, + uxn_emit_set_value, + uxn_emit_plex_def, + uxn_emit_cast_int_to_nat, + uxn_emit_cast_int_to_real, + uxn_emit_cast_int_to_str, + uxn_emit_cast_nat_to_int, + uxn_emit_cast_nat_to_real, + uxn_emit_cast_nat_to_str, + uxn_emit_cast_real_to_int, + uxn_emit_cast_real_to_nat, + uxn_emit_cast_real_to_str, + uxn_emit_strbuf_init, + uxn_emit_strbuf_append, + uxn_emit_strbuf_to_str, + uxn_emit_arena_fn_call, + uxn_emit_arena_fn_return_plex, + uxn_emit_arena_fn_return_array, + uxn_emit_arena_fn_return_strbuf, + uxn_emit_cast_str_to_int, + uxn_emit_cast_str_to_nat, + uxn_emit_cast_str_to_real, }; } diff --git a/lexer.c b/lexer.c index 05061d2..34aa8b0 100644 --- a/lexer.c +++ b/lexer.c @@ -151,7 +151,7 @@ identifierType() case 'n': return check_keyword(2, 1, "d", TOKEN_OPERATOR_AND); case 's': - return check_keyword(2, 0, "", TOKEN_KEYWORD_AS); + return check_keyword(1, 1, "s", TOKEN_KEYWORD_AS); } } break; @@ -184,11 +184,11 @@ identifierType() if(lexer.current - lexer.start > 1) { switch(lexer.start[1]) { case 'f': - return check_keyword(2, 0, "", TOKEN_KEYWORD_IF); + return check_keyword(1, 1, "f", TOKEN_KEYWORD_IF); case 's': - return check_keyword(2, 0, "", TOKEN_KEYWORD_IS); + return check_keyword(1, 1, "s", TOKEN_KEYWORD_IS); case '8': - return check_keyword(2, 0, "", TOKEN_TYPE_I8); + return check_keyword(1, 1, "8", TOKEN_TYPE_I8); case '1': return check_keyword(2, 1, "6", TOKEN_TYPE_I16); case '3': @@ -199,7 +199,7 @@ identifierType() case 'i': return check_keyword(3, 2, "t", TOKEN_KEYWORD_INIT); case 't': - return check_keyword(3, 0, "", TOKEN_TYPE_INT); + return check_keyword(2, 1, "t", TOKEN_TYPE_INT); } } break; @@ -222,7 +222,7 @@ identifierType() case 'p': return check_keyword(2, 2, "en", TOKEN_KEYWORD_OPEN); case 'r': - return check_keyword(2, 0, "", TOKEN_OPERATOR_OR); + return check_keyword(1, 1, "r", TOKEN_OPERATOR_OR); } } break; @@ -250,9 +250,9 @@ identifierType() if(lexer.current - lexer.start > 3) { switch(lexer.start[3]) { case 'd': - return check_keyword(4, 0, "", TOKEN_KEYWORD_READ); + return check_keyword(3, 1, "d", TOKEN_KEYWORD_READ); case 'l': - return check_keyword(4, 0, "", TOKEN_TYPE_REAL); + return check_keyword(3, 1, "l", TOKEN_TYPE_REAL); } } } @@ -268,7 +268,7 @@ identifierType() if(lexer.current - lexer.start > 2) { switch(lexer.start[2]) { case 'r': - return check_keyword(3, 0, "", TOKEN_TYPE_STR); + return check_keyword(2, 1, "r", TOKEN_TYPE_STR); case 'a': return check_keyword(3, 1, "t", TOKEN_KEYWORD_STAT); } @@ -292,7 +292,7 @@ identifierType() case 's': return check_keyword(2, 1, "e", TOKEN_KEYWORD_USE); case '8': - return check_keyword(2, 0, "", TOKEN_TYPE_U8); + return check_keyword(1, 1, "8", TOKEN_TYPE_U8); case '1': return check_keyword(2, 1, "6", TOKEN_TYPE_U16); case '3': diff --git a/libc.c b/libc.c index d86bcef..5452b20 100644 --- a/libc.c +++ b/libc.c @@ -95,6 +95,31 @@ afree(Arena *arena) return freed; } +void * +aend(Arena *arena) +{ + i32 pos = arena->count; + return (void *)&arena->tape[pos]; +} + +void * +areturn(Arena *arena, u32 checkpoint, const void *src, u32 size) +{ + void *dest; + if(src == nil) return nil; + + dest = (void *)&arena->tape[checkpoint]; + if(src == dest) return dest; + + mcpy(dest, (void *)src, size); + arena->count = checkpoint + size; + + /* zero out the end of the memory copy (for strings mostly) */ + arena->tape[arena->count] = 0; + + return dest; +} + char * ascpy(Arena *arena, const char *start, u32 length) { @@ -116,3 +141,190 @@ amcpy(Arena *arena, void *from, u32 length) mcpy(ptr, from, length); return ptr; } + +/** + * Fixed Point Q16.16 + */ +r32 +int_to_real(i32 i) +{ + return i << 16; +} +i32 +real_to_int(r32 f) +{ + return f >> 16; +} +r32 +float_to_real(f32 f) +{ + return FLOAT_TO_REAL(f); +} +f32 +real_to_float(r32 r) +{ + return REAL_TO_FLOAT(r); +} +r32 +real_add(r32 a, r32 b) +{ + return a + b; +} +r32 +real_sub(r32 a, r32 b) +{ + return a - b; +} +r32 +real_mul(r32 a, r32 b) +{ + + r32 src1_whole = (r32)a >> 16; + r32 src2_whole = (r32)b >> 16; + + r32 src1_decimal = (r32)a & 16; + r32 src2_decimal = (r32)b & 16; + + r32 result = 0; + result += (src1_whole * src2_whole) << 16; + result += (src1_whole * src2_decimal); + result += (src1_decimal * src2_whole); + result += ((src1_decimal * src2_decimal) >> 16) & 16; + + return result; +} +r32 +real_div(r32 a, r32 b) +{ + r32 result; + + r32 src1_val = (r32)a; + r32 src2_val = (r32)b; + u32 src2_reciprocal = 1; + + src2_reciprocal <<= 31; + src2_reciprocal = (u32)(src2_reciprocal / src2_val); + result = src1_val * src2_reciprocal; + result <<= 1; + + return result; +} +r32 +real_eq(r32 a, r32 b) +{ + return a == b; +} +r32 +real_ne(r32 a, r32 b) +{ + return a != b; +} +r32 +real_lt(r32 a, r32 b) +{ + return a < b; +} +r32 +real_le(r32 a, r32 b) +{ + return a <= b; +} +r32 +real_gt(r32 a, r32 b) +{ + return a > b; +} +r32 +real_ge(r32 a, r32 b) +{ + return a >= b; +} +r32 +real_neg(r32 f) +{ + return -f; +} +r32 +real_abs(r32 f) +{ + return (f < 0) ? -f : f; +} + +const char radix_set[11] = "0123456789"; + +char* +int_to_string(Arena *a, i32 v) +{ + char buffer[MAX_LEN_INT32] = {0}; + i32 n; + u32 i = MAX_LEN_INT32; + bool neg; + n = v; + neg = n < 0; + + if(neg) n = -n; + + do { + buffer[--i] = radix_set[n % 10]; + n /= 10; + } while(n > 0); + if(neg) buffer[--i] = '-'; + /* Ensure at least one digit is written for 0 */ + if(v == 0) buffer[--i] = '0'; + + return ascpy(a, buffer + i, MAX_LEN_INT32 - i); +} + +char* +nat_to_string(Arena *a, u32 v) +{ + char buffer[MAX_LEN_INT32] = {0}; + u32 n; + u32 i = MAX_LEN_INT32; + n = v; + + do { + buffer[--i] = radix_set[n % 10]; + n /= 10; + } while(n > 0); + /* Ensure at least one digit is written for 0 */ + if(v == 0) buffer[--i] = '0'; + + return ascpy(a, buffer + i, MAX_LEN_INT32 - i); +} + +char* +real_to_string(Arena *a, r32 q) +{ + char buffer[MAX_LEN_REAL32] = {0}; + bool neg; + i32 int_part; + u32 frac_part; + u32 i = MAX_LEN_REAL32; + + if(q < 0) q = -q; + + int_part = q >> 16; + frac_part = q & 0xFFFF; + + do { + buffer[--i] = radix_set[frac_part % 10]; + frac_part /= 10; + } while(frac_part > 0); + + buffer[--i] = '.'; + + neg = int_part < 0; + + if(neg) int_part = -int_part; + + do { + buffer[--i] = radix_set[int_part % 10]; + int_part /= 10; + } while(int_part > 0); + + if(neg) buffer[--i] = '-'; + + return ascpy(a, buffer + i, MAX_LEN_REAL32 - i); +} + diff --git a/libc.h b/libc.h index 02c4405..47cdf3b 100644 --- a/libc.h +++ b/libc.h @@ -21,6 +21,7 @@ typedef uint16_t u16; typedef int16_t i16; typedef uint32_t u32; typedef int32_t i32; +typedef int32_t r32; typedef float f32; #else typedef unsigned char u8; @@ -29,6 +30,7 @@ typedef unsigned short u16; typedef signed short i16; typedef unsigned int u32; typedef signed int i32; +typedef signed int r32; typedef float f32; #endif @@ -69,6 +71,9 @@ typedef u8 bool; #define USED(x) ((void)(x)) +#define MAX_LEN_REAL32 12 +#define MAX_LEN_INT32 11 + typedef struct arena_s Arena; struct arena_s { u8 *tape; @@ -83,8 +88,43 @@ bool sleq(const char *s1, const char *s2, u32 length); u32 slen(const char *str); u32 snlen(const char *str, u32 max_len); void *aalloc(Arena *arena, u32 size); +void *aend(Arena *arena); +void *areturn(Arena *arena, u32 checkpoint, const void *src, u32 size); u32 afree(Arena *arena); char *ascpy(Arena *arena, const char *start, u32 length); void *amcpy(Arena *arena, void *from, u32 length); +#define ARENA_RETURN(arena, ckpt, src_ptr, type) \ + return (type *)areturn(arena, (ckpt), (src_ptr), sizeof(type)) + +#define ARENA_RETURN_ARRAY(arena, ckpt, src_ptr, type, count) \ + return (type *)areturn(arena, (ckpt), (src_ptr), sizeof(type) * (count)) + +#define ARENA_RETURN_STR(arena, ckpt, src_ptr) \ + return (char *)areturn(arena, (ckpt), (src_ptr), slen(src_ptr)) + +#define ARENA_RETURN_STRBUF(arena, ckpt, sbuf) \ + char *to_return = StrBuf_toS(arena, sbuf); \ + return (char *)areturn(arena, (ckpt), (to_return), slen(to_return)) + +r32 int_to_real(i32 i); +i32 real_to_int(r32 f); +r32 float_to_real(f32 f); +f32 real_to_float(r32 r); +r32 real_add(r32 a, r32 b); +r32 real_sub(r32 a, r32 b); +r32 real_mul(r32 a, r32 b); +r32 real_div(r32 a, r32 b); +r32 real_eq(r32 a, r32 b); +r32 real_ne(r32 a, r32 b); +r32 real_lt(r32 a, r32 b); +r32 real_le(r32 a, r32 b); +r32 real_gt(r32 a, r32 b); +r32 real_ge(r32 a, r32 b); +r32 real_neg(r32 f); +r32 real_abs(r32 f); +char *int_to_string(Arena *a, i32 v); +char *nat_to_string(Arena *a, u32 v); +char *real_to_string(Arena *a, r32 q); + #endif diff --git a/list.c b/list.c index 68103ae..65b8afc 100644 --- a/list.c +++ b/list.c @@ -1,9 +1,9 @@ #include "list.h" List * -new_list(Arena *arena) +List_init(Arena *arena) { - List *l = aalloc(arena, sizeof(List)); + List *l = (List*)aalloc(arena, sizeof(List)); if (!l) return nil; l->head = nil; @@ -20,7 +20,7 @@ node_value(Node *n) } void * -list_push(Arena *arena, List *list, void *data, u32 data_size) +List_push(Arena *arena, List *list, void *data, u32 data_size) { void *dest; void *ptr = aalloc(arena, sizeof(Node) + data_size); @@ -28,6 +28,7 @@ list_push(Arena *arena, List *list, void *data, u32 data_size) if (!node) return nil; + node->size = data_size; node->next = nil; if (!list->head) { @@ -48,20 +49,20 @@ list_push(Arena *arena, List *list, void *data, u32 data_size) } void -list_foreach(List *list, list_iter_fn func) +List_map(List *list, list_iter_fn func) { Node *curr; if (!list || !func) return; curr = list->head; while (curr) { - func(node_value(curr)); + if (!func(node_value(curr))) break; curr = curr->next; } } void * -list_get(List *list, u32 index) +List_get(List *list, u32 index) { u32 i; Node *curr; @@ -76,16 +77,15 @@ list_get(List *list, u32 index) } void -list_set(List *list, u32 index, void *data, u32 size) +List_set(List *list, u32 index, void *data, u32 size) { - void *target = list_get(list, index); - if (target) { - 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) +List_find(List *list, compare_fn compare, void *target) { Node *curr; void *data; @@ -101,4 +101,4 @@ list_find(List *list, compare_fn compare, void *target) curr = curr->next; } return nil; -} +} \ No newline at end of file diff --git a/list.h b/list.h index 8d7df04..ad8b88c 100644 --- a/list.h +++ b/list.h @@ -5,6 +5,7 @@ typedef struct node_s Node; struct node_s { + u32 size; struct node_s *next; }; @@ -16,14 +17,14 @@ struct list_s { }; typedef bool (*compare_fn)(void *data, void *target); -typedef void (*list_iter_fn)(void *data); +typedef bool (*list_iter_fn)(void *data); -List *new_list(Arena *arena); +List *List_init(Arena *arena); void *node_value(Node *n); -void *list_push(Arena *arena, List *list, void *data, u32 data_size); -void list_foreach(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_push(Arena *arena, List *list, void *data, u32 data_size); +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); #endif \ No newline at end of file diff --git a/strbuf.c b/strbuf.c new file mode 100644 index 0000000..363f667 --- /dev/null +++ b/strbuf.c @@ -0,0 +1,65 @@ +#include "strbuf.h" + +StrBuf * +StrBuf_init(Arena *a) +{ + StrBuf *l = (StrBuf*)aalloc(a, sizeof(StrBuf)); + if (!l) return nil; + + l->head = nil; + l->tail = nil; + l->count = 0; + + return l; +} + +void * +StrBuf_append(Arena *a, StrBuf *buf, char *str) +{ + u32 length = slen(str); + + void *dest; + void *ptr = aalloc(a, sizeof(Node) + length); + Node *node = (Node *)ptr; + + if (!node) return nil; + + node->next = nil; + node->size = length; + + if (!buf->head) { + buf->head = buf->tail = node; + } else { + buf->tail->next = node; + buf->tail = node; + } + + buf->count++; + + dest = node_value(node); + if (str && length > 0) { + mcpy(dest, str, length); + } + + return dest; +} + +char * +StrBuf_toS(Arena *a, StrBuf *buf) +{ + Node *curr; + char *tmp_str; + + char *str = (char *)aend(a); + + if (!buf || !str) return nil; + + curr = buf->head; + while (curr) { + tmp_str = node_value(curr); + amcpy(a, tmp_str, curr->size); + curr = curr->next; + } + + return str; +} \ No newline at end of file diff --git a/strbuf.h b/strbuf.h new file mode 100644 index 0000000..8405cd5 --- /dev/null +++ b/strbuf.h @@ -0,0 +1,17 @@ +#ifndef UNDAR_STRBUF_H +#define UNDAR_STRBUF_H + +#include "list.h" + +typedef struct strbuf_s StrBuf; +struct strbuf_s { + Node *head; + Node *tail; + u32 count; +}; + +StrBuf *StrBuf_init(Arena *a); +void *StrBuf_append(Arena *a, StrBuf *buf, char *str); +char *StrBuf_toS(Arena *a, StrBuf *buf); + +#endif \ No newline at end of file diff --git a/test/global.ul b/test/global.ul index 8eaf0db..e05fde6 100755 --- a/test/global.ul +++ b/test/global.ul @@ -1,4 +1,6 @@ int i = 122; int j = 32; -print((i - j) as str); +//function main() { + print((i - j) as str); +//} diff --git a/test/plex.c b/test/plex.c deleted file mode 100644 index aaba4c0..0000000 --- a/test/plex.c +++ /dev/null @@ -1,696 +0,0 @@ -#define __UNDAR_ARENA_SIZE__ 64000 - -#if defined(__has_include) -#if __has_include() -#define HAVE_STDINT 1 -#endif -#if __has_include() -#define HAVE_STDBOOL 1 -#endif -#if __has_include() -#define HAVE_STDDEF 1 -#endif -#endif - -#ifdef HAVE_STDINT -#include -typedef uint8_t u8; -typedef int8_t i8; -typedef uint16_t u16; -typedef int16_t i16; -typedef uint32_t u32; -typedef int32_t i32; -typedef int32_t r32; -typedef float f32; -#else -typedef unsigned char u8; -typedef signed char i8; -typedef unsigned short u16; -typedef signed short i16; -typedef unsigned int u32; -typedef signed int i32; -typedef signed int r32; -typedef float f32; -#endif - -#ifdef HAVE_STDBOOL -#include -#else -#define true 1 -#define false 0 -typedef u8 bool; -#endif - -#ifdef HAVE_STDDEF -#include -#define nil NULL -#else -#define nil ((void *)0) -#endif - -#define I8_MIN -128 -#define I8_MAX 127 -#define U8_MAX 255 - -#define I16_MIN -32768 -#define I16_MAX 32767 -#define U16_MAX 65535 - -#define I32_MIN -2147483648 -#define I32_MAX 2147483647 -#define U32_MAX 4294967295 - -#define FIXED_CONST 65536.0f - -#define AS_INT(v) ((i32)(v)) -#define AS_NAT(v) ((u32)(v)) -#define AS_REAL(v) ((r32)(v)) -#define FLOAT_TO_REAL(v) (((r32)(v)) * FIXED_CONST) -#define REAL_TO_FLOAT(v) (((f32)(v)) / FIXED_CONST) - -#define USED(x) ((void)(x)) - -#define MAX_LEN_REAL32 12 -#define MAX_LEN_INT32 11 -const char radix_set[11] = "0123456789"; - -typedef struct arena_s Arena; -struct arena_s { - u8 *tape; - u32 count; - u32 capacity; -}; - -typedef bool (*compare_fn)(void *data, void *target); -typedef bool (*list_iter_fn)(void *data); - -static inline void -mcpy(void *to, void *from, u32 length) -{ - u8 *src, *dest; - if(to == nil || from == nil) return; - - src = (u8 *)from; - dest = (u8 *)to; - - while(length-- > 0) *(dest++) = *(src++); - return; -} - -static inline i32 -scpy(char *to, const char *from, u32 length) -{ - u32 i; - if(to == nil || from == nil) return -1; - if(length == 0) return 0; - for(i = 0; i < length && from[i] != '\0'; i++) to[i] = from[i]; - to[i] = '\0'; - return 0; -} - -static inline bool -seq(const char *s1, const char *s2) -{ - if(s1 == nil && s2 == nil) return true; - if(s1 == nil || s2 == nil) return false; - - while(*s1 && *s2) { - if(*s1 != *s2) return false; - s1++; - s2++; - } - - return (*s1 == '\0' && *s2 == '\0'); -} - -static inline bool -sleq(const char *s1, const char *s2, u32 length) -{ - u32 i; - if(s1 == nil && s2 == nil) return true; - if(s1 == nil || s2 == nil) return false; - - i = 0; - while(i < length && *s1 && *s2) { - if(*s1 != *s2) return false; - s1++; - s2++; - i++; - } - if(i == length) return true; - return (*s1 == '\0' && *s2 == '\0'); -} - -static inline u32 -slen(const char *str) -{ - u32 i; - if(str == nil) return 0; - for(i = 0; str[i] != '\0'; i++); - return i; -} - -static inline u32 -snlen(const char *str, u32 max_len) -{ - u32 i; - if(str == nil) return 0; - for(i = 0; i < max_len && str[i] != '\0'; i++); - return i; -} - -u8 tape[__UNDAR_ARENA_SIZE__]; -Arena arena = {tape, 0, __UNDAR_ARENA_SIZE__}; - -static inline void * -aalloc(u32 size) -{ - u32 pos; - if(arena.count + size > arena.capacity) return nil; - - pos = arena.count; - arena.count += size; - return (void *)&arena.tape[pos]; -} - -static inline void * -aend() -{ - i32 pos = arena.count; - return (void *)&arena.tape[pos]; -} - -static inline void * -areturn(u32 checkpoint, const void *src, u32 size) -{ - void *dest; - if(src == nil) return nil; - - u32 current = arena.count; - - dest = (void *)&arena.tape[checkpoint]; - if(src == dest) return dest; - - mcpy(dest, (void *)src, size); - arena.count = checkpoint + size; - - // zero out the end of the memory copy (for strings mostly) - arena.tape[arena.count] = 0; - - return dest; -} - -#define ARENA_RETURN(ckpt, src_ptr, type) \ - return (type *)areturn((ckpt), (src_ptr), sizeof(type)) - -#define ARENA_RETURN_ARRAY(ckpt, src_ptr, type, count) \ - return (type *)areturn((ckpt), (src_ptr), sizeof(type) * (count)) - -#define ARENA_RETURN_STR(ckpt, src_ptr) \ - return (char *)areturn((ckpt), (src_ptr), slen(src_ptr)) - -#define ARENA_RETURN_STRBUF(ckpt, sbuf) \ - char *to_return = StrBuf_toS(sbuf); \ - return (char *)areturn((ckpt), (to_return), slen(to_return)) - -static inline r32 -int_to_real(i32 i) -{ - return i << 16; -} -static inline i32 -real_to_int(r32 f) -{ - return f >> 16; -} -static inline r32 -float_to_real(f32 f) -{ - return FLOAT_TO_REAL(f); -} -static inline f32 -real_to_float(r32 r) -{ - return REAL_TO_FLOAT(r); -} -static inline r32 -real_add(r32 a, r32 b) -{ - return a + b; -} -static inline r32 -real_sub(r32 a, r32 b) -{ - return a - b; -} -static inline r32 -real_mul(r32 a, r32 b) -{ - - r32 src1_whole = (r32)a >> 16; - r32 src2_whole = (r32)b >> 16; - - r32 src1_decimal = (r32)a & 16; - r32 src2_decimal = (r32)b & 16; - - r32 result = 0; - result += (src1_whole * src2_whole) << 16; - result += (src1_whole * src2_decimal); - result += (src1_decimal * src2_whole); - result += ((src1_decimal * src2_decimal) >> 16) & 16; - - return result; -} -static inline r32 -real_div(r32 a, r32 b) -{ - r32 result; - - r32 src1_val = (r32)a; - r32 src2_val = (r32)b; - u32 src2_reciprocal = 1; - - src2_reciprocal <<= 31; - src2_reciprocal = (u32)(src2_reciprocal / src2_val); - result = src1_val * src2_reciprocal; - result <<= 1; - - return result; -} -static inline r32 -real_eq(r32 a, r32 b) -{ - return a == b; -} -static inline r32 -real_ne(r32 a, r32 b) -{ - return a != b; -} -static inline r32 -real_lt(r32 a, r32 b) -{ - return a < b; -} -static inline r32 -real_le(r32 a, r32 b) -{ - return a <= b; -} -static inline r32 -real_gt(r32 a, r32 b) -{ - return a > b; -} -static inline r32 -real_ge(r32 a, r32 b) -{ - return a >= b; -} -static inline r32 -real_neg(r32 f) -{ - return -f; -} -static inline r32 -real_abs(r32 f) -{ - return (f < 0) ? -f : f; -} - -static inline char * -ascpy(const char *start, u32 length) -{ - char *str; - if(!start) return nil; - str = (char *)aalloc(length + 1); - if(!str) return nil; - scpy(str, start, length); - return str; -} - -static inline void * -amcpy(void *from, u32 length) -{ - void *ptr; - if(!from) return nil; - ptr = aalloc(length); - if(!ptr) return nil; - mcpy(ptr, from, length); - return ptr; -} - -static inline char* -int_to_string(i32 v) -{ - char buffer[MAX_LEN_INT32] = {0}; - i32 n; - u32 i = MAX_LEN_INT32; - bool neg; - n = v; - neg = n < 0; - - if(neg) n = -n; - - do { - buffer[--i] = radix_set[n % 10]; - n /= 10; - } while(n > 0); - if(neg) buffer[--i] = '-'; - /* Ensure at least one digit is written for 0 */ - if(v == 0) buffer[--i] = '0'; - - return ascpy(buffer + i, MAX_LEN_INT32 - i); -} - -static inline char* -nat_to_string(u32 v) -{ - char buffer[MAX_LEN_INT32] = {0}; - u32 n; - u32 i = MAX_LEN_INT32; - n = v; - - do { - buffer[--i] = radix_set[n % 10]; - n /= 10; - } while(n > 0); - /* Ensure at least one digit is written for 0 */ - if(v == 0) buffer[--i] = '0'; - - return ascpy(buffer + i, MAX_LEN_INT32 - i); -} - -static inline char* -real_to_string(r32 q) -{ - char buffer[MAX_LEN_REAL32] = {0}; - bool neg; - i32 int_part; - u32 frac_part; - u32 i = MAX_LEN_REAL32; - - if(q < 0) q = -q; - - int_part = q >> 16; - frac_part = q & 0xFFFF; - - do { - buffer[--i] = radix_set[frac_part % 10]; - frac_part /= 10; - } while(frac_part > 0); - - buffer[--i] = '.'; - - neg = int_part < 0; - - if(neg) int_part = -int_part; - - do { - buffer[--i] = radix_set[int_part % 10]; - int_part /= 10; - } while(int_part > 0); - - if(neg) buffer[--i] = '-'; - - return ascpy(buffer + i, MAX_LEN_REAL32 - i); -} - -typedef struct node_s Node; -struct node_s { - u32 size; - struct node_s *next; -}; - -typedef struct list_s List; -struct list_s { - Node *head; - Node *tail; - u32 count; -}; - -typedef bool (*compare_fn)(void *data, void *target); -typedef bool (*list_iter_fn)(void *data); - -List * -List_init(Arena *arena) -{ - List *l = (List*)aalloc(sizeof(List)); - if (!l) return nil; - - l->head = nil; - l->tail = nil; - l->count = 0; - - return l; -} - -void * -node_value(Node *n) -{ - return (void *)((u8 *)n + sizeof(Node)); -} - -void * -List_push(List *list, void *data, u32 data_size) -{ - void *dest; - void *ptr = aalloc(sizeof(Node) + data_size); - Node *node = (Node *)ptr; - - if (!node) return nil; - - node->size = data_size; - node->next = nil; - - if (!list->head) { - list->head = list->tail = node; - } else { - list->tail->next = node; - list->tail = node; - } - - list->count++; - - 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; - } -} - -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); -} - -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 * -List_find(List *list, compare_fn compare, void *target) -{ - Node *curr; - void *data; - - 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; -} - -typedef struct strbuf_s StrBuf; -struct strbuf_s { - Node *head; - Node *tail; - u32 count; -}; - -StrBuf * -StrBuf_init() -{ - StrBuf *l = (StrBuf*)aalloc(sizeof(StrBuf)); - if (!l) return nil; - - l->head = nil; - l->tail = nil; - l->count = 0; - - return l; -} - -void * -StrBuf_append(StrBuf *buf, char *str) -{ - u32 length = slen(str); - - void *dest; - void *ptr = aalloc(sizeof(Node) + length); - Node *node = (Node *)ptr; - - if (!node) return nil; - - node->next = nil; - node->size = length; - - if (!buf->head) { - buf->head = buf->tail = node; - } else { - buf->tail->next = node; - buf->tail = node; - } - - buf->count++; - - dest = node_value(node); - if (str && length > 0) { - mcpy(dest, str, length); - } - - return dest; -} - -char * -StrBuf_toS(StrBuf *buf) -{ - Node *curr; - char *tmp_str; - - char *str = (char *)aend(); - - if (!buf || !str) return nil; - - curr = buf->head; - while (curr) { - tmp_str = node_value(curr); - amcpy(tmp_str, curr->size); - curr = curr->next; - } - - return str; -} - -#include - -typedef struct Point Point; -struct Point { - u32 x; - u32 y; -}; - -Point * -Point_init(u32 x, u32 y) -{ - Point *this = (Point *)aalloc(sizeof(Point)); - this->x = x; - this->y = y; - return this; -} - -char* -Point_toS(Point *this) -{ - u32 __UNDAR_FN_CHECKPOINT_REF__ = arena.count; - - StrBuf *buf = StrBuf_init(); - StrBuf_append(buf, "[x:"); - StrBuf_append(buf,nat_to_string(this->x)); - StrBuf_append(buf, ", y:"); - StrBuf_append(buf,nat_to_string(this->y)); - StrBuf_append(buf, "]"); - - ARENA_RETURN_STRBUF(__UNDAR_FN_CHECKPOINT_REF__, buf); -} - -typedef struct Rect Rect; -struct Rect { - Point top_left; - Point bottom_right; - u32 width; - u32 height; -}; - -Rect * -Rect_init(Point *tl, Point *br, u32 width, u32 height) -{ - Rect *this = (Rect *)aalloc(sizeof(Rect)); - mcpy(&this->top_left, tl, sizeof(Point)); - mcpy(&this->bottom_right, br, sizeof(Point)); - this->width = width; - this->height = height; - return this; -} - -char* -Rect_toS(Rect *this) -{ - u32 __UNDAR_FN_CHECKPOINT_REF__ = arena.count; - - StrBuf *buf = StrBuf_init(); - StrBuf_append(buf, "[top_left: "); - StrBuf_append(buf,Point_toS(&this->top_left)); - StrBuf_append(buf,", bottom_right: "); - StrBuf_append(buf,Point_toS(&this->bottom_right)); - StrBuf_append(buf, ", width:"); - StrBuf_append(buf,nat_to_string(this->width)); - StrBuf_append(buf, ", height:"); - StrBuf_append(buf,nat_to_string(this->height)); - StrBuf_append(buf, "]"); - - ARENA_RETURN_STRBUF(__UNDAR_FN_CHECKPOINT_REF__, buf); -} - -Rect * -create_geometry() -{ - u32 __UNDAR_FN_CHECKPOINT_REF__ = arena.count; - - Point *tl = Point_init(10, 20); - Point *br = Point_init(100, 200); - Rect *final_rect = Rect_init(tl, br, 90, 180); - - ARENA_RETURN(__UNDAR_FN_CHECKPOINT_REF__, final_rect, Rect); -} - -int main() { - - Rect *r = create_geometry(); - printf("%s\n", Rect_toS(r)); - return 0; -}