Add arena return to libc, add strbuf, add reality engine rom emitter, remove C emitter

This commit is contained in:
zongor 2026-04-20 23:24:38 -07:00
parent 20f44d6ad8
commit 38585bf105
22 changed files with 1304 additions and 1797 deletions

View File

@ -26,52 +26,49 @@ cd undar-lang && ./build
* Memory Management * 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. **Built in Types**
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**
| Type | Description | | Type | Description |
|------+------------------------------------| |------+------------------------------------|
| =byte= | Character/8 bit unsigned int | | =byte= | Character (architecture specific) |
| =u8= | 8 bit unsigned int | | =u8= | exactly 8-bit unsigned int |
| =i8= | 8 bit signed int | | =i8= | exactly 8-bit signed int |
| =u16= | 16 bit unsigned int | | =u16= | exactly 16-bit unsigned int |
| =i16= | 16 bit signed int | | =i16= | exactly 16-bit signed int |
| =u32= | exactly 32-bit unsigned integer | | =u32= | exactly 32-bit unsigned integer |
| =i32= | exactly 32-bit signed integer | | =i32= | exactly 32-bit signed integer |
| =int= | signed number | | =int= | 1 word signed number |
| =nat= | unsigned number | | =nat= | 1 word unsigned number |
| =real= | Q16.16 fixed-point real number | | =real= | Q16.16 fixed-point real number |
| =str= | fat pointer [length + data] string | | =str= | fat pointer [length + data] string |
| =bool= | true/false | | =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
[[./ROADMAP.org][Compiler, Plex, Immidate mode GUI, Constructive solid geometry, Tunnels, Actor model]] [[./ROADMAP.org][Compiler, Plex, Immidate mode GUI, Constructive solid geometry, Tunnels, Actor model]]
* License * License
MIT-0 [[./LICENSE][MIT]]
* Inspirations * Inspirations
- [[https://plan9.io/][Plan 9]] / 9P - Unified I/O, Tunnels. - [[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://fortran-lang.org/][Fortran]] - Array semantics.
- [[https://en.wikipedia.org/wiki/C_(programming_language)][C]] / [[https://ziglang.org/][Zig]] - Portability, control, minimalism. - [[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. - [[https://lua.org][Lua]] - Friendly syntax, portable, and minimal VM.
- [[https://www.craftinginterpreters.com/the-lox-language.html][Lox]] - The start of my programming language creation journey. - [[https://www.craftinginterpreters.com/the-lox-language.html][Lox]] - Lexer & Parser logic.
- [[https://wiki.xxiivv.com/site/uxn.html][Uxn]] - Major inspiration, espeically around the core VM. - [[https://wiki.xxiivv.com/site/uxn.html][Uxn]] - Major inspiration.
- [[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
- Retro Systems - N64, PS1, Mac Classic, Windows 95 - UI esthetics - Retro Systems - N64, PS1, Mac Classic, Windows 95 - UI esthetics

View File

@ -2,16 +2,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#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 * static char *
readFile(const char *path) readFile(const char *path)
{ {
@ -45,11 +35,11 @@ readFile(const char *path)
void void
print_help() print_help()
{ {
printf("Usage: undar [options] file...\nOptions:\n\t-emit={c99|uxn}\tEmitter " printf("Usage: undar [options] file...\nOptions:\n\t-emit={rer|uxn}\tEmitter "
"output, currently C source and Uxn binary.\n\n"); "output, currently Uxn tal code and Reality Engine rom.\n\n");
} }
#define MEM_SIZE 68000 #define MEM_SIZE 64000
int int
main(int argc, char **argv) main(int argc, char **argv)
@ -65,14 +55,15 @@ main(int argc, char **argv)
} }
Emitter e; Emitter e;
if(seq(argv[1], "-emit=c99")) { if(seq(argv[1], "-emit=rer")) {
e = c_emitter(); e = rer_emitter();
} else if(seq(argv[1], "-emit=uxn")) { } else if(seq(argv[1], "-emit=uxn")) {
e = uxn_emitter(); e = uxn_emitter();
} else { } else {
printf("unknown emitter type\n"); printf("unknown emitter type\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
u8 tape[MEM_SIZE]; u8 tape[MEM_SIZE];
Arena a = {tape, 0, MEM_SIZE}; Arena a = {tape, 0, MEM_SIZE};

5
build
View File

@ -73,16 +73,17 @@ esac
VM_BUILD_FLAGS="$BUILD_FLAGS -std=c89 -ffreestanding -nostdlib -fno-builtin" 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 libc.c -o $BUILD_DIR/libc.o $VM_BUILD_FLAGS
${CC} -c list.c -o $BUILD_DIR/list.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 lexer.c -o $BUILD_DIR/lexer.o $VM_BUILD_FLAGS
${CC} -c compiler.c -o $BUILD_DIR/compiler.o $VM_BUILD_FLAGS ${CC} -c compiler.c -o $BUILD_DIR/compiler.o $VM_BUILD_FLAGS
# Set up the final build command # Set up the final build command
case $ARCH in case $ARCH in
"linux") "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") "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 esac

View File

@ -1,10 +1,10 @@
#ifndef UNDAR_COMMON_H #ifndef UNDAR_COMMON_H
#define UNDAR_COMMON_H #define UNDAR_COMMON_H
#include "libc.h"
#include "list.h" #include "list.h"
typedef enum symbol_type_e { typedef enum symbol_type_e {
SYMBOL_UNDEFINED,
SYMBOL_VOID, SYMBOL_VOID,
SYMBOL_BOOL, SYMBOL_BOOL,
SYMBOL_BYTE, SYMBOL_BYTE,
@ -41,4 +41,6 @@ struct symbol_s {
List *fields; /* either plex variable fields, or method signatures */ List *fields; /* either plex variable fields, or method signatures */
}; };
void *node_value(Node *n);
#endif #endif

View File

@ -1,4 +1,5 @@
#include "compiler.h" #include "compiler.h"
#include "common.h"
#include "emit.h" #include "emit.h"
Emitter emitter; Emitter emitter;
@ -13,7 +14,7 @@ void
scope_push() scope_push()
{ {
Scope *child = aalloc(arena, sizeof(Scope)); Scope *child = aalloc(arena, sizeof(Scope));
child->symbols = new_list(arena); child->symbols = List_init(arena);
child->parent = parser.current_scope; child->parent = parser.current_scope;
parser.current_scope = child; parser.current_scope = child;
@ -34,7 +35,7 @@ scope_get_symbol(Scope *scope, const char *name, u32 name_length)
count = scope->symbols->count; count = scope->symbols->count;
for(i = 0; i < count; i++) { 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; 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->size = size;
sym->ref = 0; sym->ref = 0;
if(type == SYMBOL_PLEX || type == SYMBOL_METHOD || type == SYMBOL_TRAIT) { if(type == SYMBOL_PLEX || type == SYMBOL_METHOD || type == SYMBOL_TRAIT) {
sym->args = new_list(arena); sym->args = List_init(arena);
sym->fields = new_list(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; return sym;
} }
@ -130,7 +131,6 @@ binary()
TokenType operatorType = parser.previous.type; TokenType operatorType = parser.previous.type;
ParseRule *rule = get_rule(operatorType); ParseRule *rule = get_rule(operatorType);
if(emitter.notation == POSTFIX)
parse_precedence((Precedence)(rule->precedence + 1)); parse_precedence((Precedence)(rule->precedence + 1));
switch(operatorType) { switch(operatorType) {
@ -167,9 +167,6 @@ binary()
default: default:
return; return;
} }
if(emitter.notation == INFIX)
parse_precedence((Precedence)(rule->precedence + 1));
} }
static void static void
@ -206,12 +203,104 @@ variable()
parser.previous.line); parser.previous.line);
} }
parser.current_type = sym->type;
emitter.emit_variable(sym); emitter.emit_variable(sym);
} }
static void static void
cast_type() 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 static void
@ -227,60 +316,70 @@ variable_declaration()
size = emitter.emit_int_type(parser.current.start, parser.current.length); size = emitter.emit_int_type(parser.current.start, parser.current.length);
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_INT, scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_INT,
size); size);
parser.current_type = SYMBOL_INT;
break; break;
} }
case TOKEN_TYPE_NAT: { case TOKEN_TYPE_NAT: {
size = emitter.emit_nat_type(parser.current.start, parser.current.length); size = emitter.emit_nat_type(parser.current.start, parser.current.length);
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_NAT, scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_NAT,
size); size);
parser.current_type = SYMBOL_NAT;
break; break;
} }
case TOKEN_TYPE_REAL: { case TOKEN_TYPE_REAL: {
size = emitter.emit_real_type(parser.current.start, parser.current.length); size = emitter.emit_real_type(parser.current.start, parser.current.length);
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_REAL, scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_REAL,
size); size);
parser.current_type = SYMBOL_REAL;
break; break;
} }
case TOKEN_TYPE_STR: { case TOKEN_TYPE_STR: {
size = emitter.emit_str_type(parser.current.start, parser.current.length); size = emitter.emit_str_type(parser.current.start, parser.current.length);
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_STR, scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_STR,
size); size);
parser.current_type = SYMBOL_STR;
break; break;
} }
case TOKEN_TYPE_BOOL: { case TOKEN_TYPE_BOOL: {
size = emitter.emit_bool_type(parser.current.start, parser.current.length); size = emitter.emit_bool_type(parser.current.start, parser.current.length);
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_BOOL, scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_BOOL,
size); size);
parser.current_type = SYMBOL_BOOL;
break; break;
} }
case TOKEN_TYPE_BYTE: { case TOKEN_TYPE_BYTE: {
size = emitter.emit_byte_type(parser.current.start, parser.current.length); size = emitter.emit_byte_type(parser.current.start, parser.current.length);
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_U8, scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_U8,
size); size);
parser.current_type = SYMBOL_BYTE;
break; break;
} }
case TOKEN_TYPE_U8: { case TOKEN_TYPE_U8: {
size = emitter.emit_u8_type(parser.current.start, parser.current.length); size = emitter.emit_u8_type(parser.current.start, parser.current.length);
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_U8, scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_U8,
size); size);
parser.current_type = SYMBOL_U8;
break; break;
} }
case TOKEN_TYPE_I8: { case TOKEN_TYPE_I8: {
size = emitter.emit_i8_type(parser.current.start, parser.current.length); size = emitter.emit_i8_type(parser.current.start, parser.current.length);
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_I8, scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_I8,
size); size);
parser.current_type = SYMBOL_I8;
break; break;
} }
case TOKEN_TYPE_U16: { case TOKEN_TYPE_U16: {
size = emitter.emit_u16_type(parser.current.start, parser.current.length); size = emitter.emit_u16_type(parser.current.start, parser.current.length);
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_U16, scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_U16,
size); size);
parser.current_type = SYMBOL_U16;
break; break;
} }
case TOKEN_TYPE_I16: { case TOKEN_TYPE_I16: {
size = emitter.emit_i16_type(parser.current.start, parser.current.length); size = emitter.emit_i16_type(parser.current.start, parser.current.length);
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_I16, scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_I16,
size); size);
parser.current_type = SYMBOL_I16;
break; break;
} }
default: { default: {
@ -292,11 +391,14 @@ variable_declaration()
advance(); advance();
if(match(TOKEN_EQ)) { if(match(TOKEN_EQ)) {
emitter.emit_set_value();
expression(); expression();
emitter.emit_constant(var.start, var.length); emitter.emit_constant(var.start, var.length);
} }
consume(TOKEN_SEMICOLON); consume(TOKEN_SEMICOLON);
emitter.emit_end_statement();
parser.current_type = SYMBOL_UNDEFINED;
} }
static void static void
@ -317,10 +419,10 @@ declaration()
static void static void
print_statement() print_statement()
{ {
if(emitter.notation == INFIX) emitter.emit_print();
expression(); expression();
consume(TOKEN_SEMICOLON); consume(TOKEN_SEMICOLON);
if(emitter.notation == POSTFIX) emitter.emit_print(); emitter.emit_end_statement();
emitter.emit_print();
} }
static void static void
@ -372,7 +474,7 @@ static void
unary() unary()
{ {
TokenType operatorType = parser.previous.type; TokenType operatorType = parser.previous.type;
if(emitter.notation == POSTFIX) parse_precedence(PREC_UNARY); parse_precedence(PREC_UNARY);
switch(operatorType) { switch(operatorType) {
case TOKEN_MINUS: case TOKEN_MINUS:
@ -384,8 +486,6 @@ unary()
default: default:
return; return;
} }
if(emitter.notation == INFIX) parse_precedence(PREC_UNARY);
} }
ParseRule rules[] = { ParseRule rules[] = {
@ -413,7 +513,7 @@ ParseRule rules[] = {
/* TOKEN_KEYWORD_CONST */ {nil, nil, PREC_NONE}, /* TOKEN_KEYWORD_CONST */ {nil, nil, PREC_NONE},
/* TOKEN_KEYWORD_IF */ {nil, nil, PREC_NONE}, /* TOKEN_KEYWORD_IF */ {nil, nil, PREC_NONE},
/* TOKEN_KEYWORD_IS */ {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_ELSE */ {nil, nil, PREC_NONE},
/* TOKEN_KEYWORD_WHILE */ {nil, nil, PREC_NONE}, /* TOKEN_KEYWORD_WHILE */ {nil, nil, PREC_NONE},
/* TOKEN_KEYWORD_FOR */ {nil, nil, PREC_NONE}, /* TOKEN_KEYWORD_FOR */ {nil, nil, PREC_NONE},

View File

@ -24,6 +24,7 @@ typedef enum {
PREC_TERM, /* + - */ PREC_TERM, /* + - */
PREC_FACTOR, /* * / */ PREC_FACTOR, /* * / */
PREC_UNARY, /* ! - */ PREC_UNARY, /* ! - */
PREC_CAST, /* as */
PREC_CALL, /* . () */ PREC_CALL, /* . () */
PREC_PRIMARY PREC_PRIMARY
} Precedence; } Precedence;
@ -40,6 +41,7 @@ struct parser_s {
Scope *current_scope; Scope *current_scope;
Token current; Token current;
Token previous; Token previous;
SymbolType current_type;
}; };
bool compile(Arena *a, Emitter e, char *source); bool compile(Arena *a, Emitter e, char *source);

16
docs/VM.org Normal file
View File

@ -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.

View File

@ -0,0 +1,93 @@
#define __UNDAR_ARENA_SIZE__ 64000
#include "../libc.h"
#include "../strbuf.h"
#include <stdio.h>
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;
}

37
emit.h
View File

@ -4,17 +4,6 @@
#include "common.h" #include "common.h"
#include "libc.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 (*SymbolEmit)(Symbol *sym);
typedef void (*ErrorMsg)(const char *str, i32 length, i32 line); typedef void (*ErrorMsg)(const char *str, i32 length, i32 line);
typedef void (*VoidArgEmit)(); typedef void (*VoidArgEmit)();
@ -23,8 +12,6 @@ typedef i32 (*TypeVariableEmit)(const char *str, i32 length);
typedef struct emitter_s Emitter; typedef struct emitter_s Emitter;
struct emitter_s { struct emitter_s {
NotationType notation;
OutputType output;
ErrorMsg error; ErrorMsg error;
VoidArgEmit prolog; VoidArgEmit prolog;
VoidArgEmit epilogue; VoidArgEmit epilogue;
@ -78,9 +65,31 @@ struct emitter_s {
VoidArgEmit emit_open; VoidArgEmit emit_open;
VoidArgEmit emit_close; VoidArgEmit emit_close;
VoidArgEmit emit_stat; 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(); Emitter uxn_emitter();
#endif #endif

View File

@ -1,384 +0,0 @@
#include "../../emit.h"
#include <stdio.h>
#include <stdlib.h>
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,
};
}

View File

@ -1,605 +0,0 @@
#if defined(__has_include)
#if __has_include(<stdint.h>)
#define HAVE_STDINT 1
#endif
#if __has_include(<stdbool.h>)
#define HAVE_STDBOOL 1
#endif
#if __has_include(<stddef.h>)
#define HAVE_STDDEF 1
#endif
#endif
#ifdef HAVE_STDINT
#include <stdint.h>
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 <stdbool.h>
#else
#define true 1
#define false 0
typedef u8 bool;
#endif
#ifdef HAVE_STDDEF
#include <stddef.h>
#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;
}

509
emit/rer/emit.c Normal file
View File

@ -0,0 +1,509 @@
#include "../../emit.h"
#include <stdio.h>
#include <stdlib.h>
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,
};
}

View File

@ -68,6 +68,12 @@ uxn_emit_error(const char *str, i32 length, i32 line)
exit(1); exit(1);
} }
void
uxn_mem(u32 a)
{
USED(a);
}
void void
uxn_prolog() uxn_prolog()
{ {
@ -365,7 +371,8 @@ uxn_emit_close_paren()
} }
void void
uxn_emit_variable(Symbol *sym) { uxn_emit_variable(Symbol *sym)
{
printf(";%.*s LDA2 ", sym->name_length, sym->name); 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 Emitter
uxn_emitter() uxn_emitter()
{ {
return (Emitter){ return (Emitter){
POSTFIX,
BINARY,
uxn_emit_error, uxn_emit_error,
uxn_prolog, uxn_prolog,
uxn_epilogue, uxn_epilogue,
@ -453,5 +566,27 @@ uxn_emitter()
uxn_emit_open, uxn_emit_open,
uxn_emit_close, 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,
}; };
} }

20
lexer.c
View File

@ -151,7 +151,7 @@ identifierType()
case 'n': case 'n':
return check_keyword(2, 1, "d", TOKEN_OPERATOR_AND); return check_keyword(2, 1, "d", TOKEN_OPERATOR_AND);
case 's': case 's':
return check_keyword(2, 0, "", TOKEN_KEYWORD_AS); return check_keyword(1, 1, "s", TOKEN_KEYWORD_AS);
} }
} }
break; break;
@ -184,11 +184,11 @@ identifierType()
if(lexer.current - lexer.start > 1) { if(lexer.current - lexer.start > 1) {
switch(lexer.start[1]) { switch(lexer.start[1]) {
case 'f': case 'f':
return check_keyword(2, 0, "", TOKEN_KEYWORD_IF); return check_keyword(1, 1, "f", TOKEN_KEYWORD_IF);
case 's': case 's':
return check_keyword(2, 0, "", TOKEN_KEYWORD_IS); return check_keyword(1, 1, "s", TOKEN_KEYWORD_IS);
case '8': case '8':
return check_keyword(2, 0, "", TOKEN_TYPE_I8); return check_keyword(1, 1, "8", TOKEN_TYPE_I8);
case '1': case '1':
return check_keyword(2, 1, "6", TOKEN_TYPE_I16); return check_keyword(2, 1, "6", TOKEN_TYPE_I16);
case '3': case '3':
@ -199,7 +199,7 @@ identifierType()
case 'i': case 'i':
return check_keyword(3, 2, "t", TOKEN_KEYWORD_INIT); return check_keyword(3, 2, "t", TOKEN_KEYWORD_INIT);
case 't': case 't':
return check_keyword(3, 0, "", TOKEN_TYPE_INT); return check_keyword(2, 1, "t", TOKEN_TYPE_INT);
} }
} }
break; break;
@ -222,7 +222,7 @@ identifierType()
case 'p': case 'p':
return check_keyword(2, 2, "en", TOKEN_KEYWORD_OPEN); return check_keyword(2, 2, "en", TOKEN_KEYWORD_OPEN);
case 'r': case 'r':
return check_keyword(2, 0, "", TOKEN_OPERATOR_OR); return check_keyword(1, 1, "r", TOKEN_OPERATOR_OR);
} }
} }
break; break;
@ -250,9 +250,9 @@ identifierType()
if(lexer.current - lexer.start > 3) { if(lexer.current - lexer.start > 3) {
switch(lexer.start[3]) { switch(lexer.start[3]) {
case 'd': case 'd':
return check_keyword(4, 0, "", TOKEN_KEYWORD_READ); return check_keyword(3, 1, "d", TOKEN_KEYWORD_READ);
case 'l': 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) { if(lexer.current - lexer.start > 2) {
switch(lexer.start[2]) { switch(lexer.start[2]) {
case 'r': case 'r':
return check_keyword(3, 0, "", TOKEN_TYPE_STR); return check_keyword(2, 1, "r", TOKEN_TYPE_STR);
case 'a': case 'a':
return check_keyword(3, 1, "t", TOKEN_KEYWORD_STAT); return check_keyword(3, 1, "t", TOKEN_KEYWORD_STAT);
} }
@ -292,7 +292,7 @@ identifierType()
case 's': case 's':
return check_keyword(2, 1, "e", TOKEN_KEYWORD_USE); return check_keyword(2, 1, "e", TOKEN_KEYWORD_USE);
case '8': case '8':
return check_keyword(2, 0, "", TOKEN_TYPE_U8); return check_keyword(1, 1, "8", TOKEN_TYPE_U8);
case '1': case '1':
return check_keyword(2, 1, "6", TOKEN_TYPE_U16); return check_keyword(2, 1, "6", TOKEN_TYPE_U16);
case '3': case '3':

212
libc.c
View File

@ -95,6 +95,31 @@ afree(Arena *arena)
return freed; 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 * char *
ascpy(Arena *arena, const char *start, u32 length) ascpy(Arena *arena, const char *start, u32 length)
{ {
@ -116,3 +141,190 @@ amcpy(Arena *arena, void *from, u32 length)
mcpy(ptr, from, length); mcpy(ptr, from, length);
return ptr; 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);
}

40
libc.h
View File

@ -21,6 +21,7 @@ typedef uint16_t u16;
typedef int16_t i16; typedef int16_t i16;
typedef uint32_t u32; typedef uint32_t u32;
typedef int32_t i32; typedef int32_t i32;
typedef int32_t r32;
typedef float f32; typedef float f32;
#else #else
typedef unsigned char u8; typedef unsigned char u8;
@ -29,6 +30,7 @@ typedef unsigned short u16;
typedef signed short i16; typedef signed short i16;
typedef unsigned int u32; typedef unsigned int u32;
typedef signed int i32; typedef signed int i32;
typedef signed int r32;
typedef float f32; typedef float f32;
#endif #endif
@ -69,6 +71,9 @@ typedef u8 bool;
#define USED(x) ((void)(x)) #define USED(x) ((void)(x))
#define MAX_LEN_REAL32 12
#define MAX_LEN_INT32 11
typedef struct arena_s Arena; typedef struct arena_s Arena;
struct arena_s { struct arena_s {
u8 *tape; u8 *tape;
@ -83,8 +88,43 @@ bool sleq(const char *s1, const char *s2, u32 length);
u32 slen(const char *str); u32 slen(const char *str);
u32 snlen(const char *str, u32 max_len); u32 snlen(const char *str, u32 max_len);
void *aalloc(Arena *arena, u32 size); 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); u32 afree(Arena *arena);
char *ascpy(Arena *arena, const char *start, u32 length); char *ascpy(Arena *arena, const char *start, u32 length);
void *amcpy(Arena *arena, void *from, 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 #endif

22
list.c
View File

@ -1,9 +1,9 @@
#include "list.h" #include "list.h"
List * 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; if (!l) return nil;
l->head = nil; l->head = nil;
@ -20,7 +20,7 @@ node_value(Node *n)
} }
void * 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 *dest;
void *ptr = aalloc(arena, sizeof(Node) + data_size); 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; if (!node) return nil;
node->size = data_size;
node->next = nil; node->next = nil;
if (!list->head) { if (!list->head) {
@ -48,20 +49,20 @@ list_push(Arena *arena, List *list, void *data, u32 data_size)
} }
void void
list_foreach(List *list, list_iter_fn func) List_map(List *list, list_iter_fn func)
{ {
Node *curr; Node *curr;
if (!list || !func) return; if (!list || !func) return;
curr = list->head; curr = list->head;
while (curr) { while (curr) {
func(node_value(curr)); if (!func(node_value(curr))) break;
curr = curr->next; curr = curr->next;
} }
} }
void * void *
list_get(List *list, u32 index) List_get(List *list, u32 index)
{ {
u32 i; u32 i;
Node *curr; Node *curr;
@ -76,16 +77,15 @@ list_get(List *list, u32 index)
} }
void 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); void *target = List_get(list, index);
if (target) { if (!target) return;
mcpy(target, data, size); mcpy(target, data, size);
}
} }
void * void *
list_find(List *list, compare_fn compare, void *target) List_find(List *list, compare_fn compare, void *target)
{ {
Node *curr; Node *curr;
void *data; void *data;

15
list.h
View File

@ -5,6 +5,7 @@
typedef struct node_s Node; typedef struct node_s Node;
struct node_s { struct node_s {
u32 size;
struct node_s *next; struct node_s *next;
}; };
@ -16,14 +17,14 @@ struct list_s {
}; };
typedef bool (*compare_fn)(void *data, void *target); 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 *node_value(Node *n);
void *list_push(Arena *arena, List *list, void *data, u32 data_size); void *List_push(Arena *arena, List *list, void *data, u32 data_size);
void list_foreach(List *list, list_iter_fn func); void List_map(List *list, list_iter_fn func);
void *list_find(List *list, compare_fn compare, void *target); void *List_find(List *list, compare_fn compare, void *target);
void *list_get(List *list, u32 index); void *List_get(List *list, u32 index);
void list_set(List *list, u32 index, void *data, u32 size); void List_set(List *list, u32 index, void *data, u32 size);
#endif #endif

65
strbuf.c Normal file
View File

@ -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;
}

17
strbuf.h Normal file
View File

@ -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

View File

@ -1,4 +1,6 @@
int i = 122; int i = 122;
int j = 32; int j = 32;
print((i - j) as str); //function main() {
print((i - j) as str);
//}

View File

@ -1,696 +0,0 @@
#define __UNDAR_ARENA_SIZE__ 64000
#if defined(__has_include)
#if __has_include(<stdint.h>)
#define HAVE_STDINT 1
#endif
#if __has_include(<stdbool.h>)
#define HAVE_STDBOOL 1
#endif
#if __has_include(<stddef.h>)
#define HAVE_STDDEF 1
#endif
#endif
#ifdef HAVE_STDINT
#include <stdint.h>
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 <stdbool.h>
#else
#define true 1
#define false 0
typedef u8 bool;
#endif
#ifdef HAVE_STDDEF
#include <stddef.h>
#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 <stdio.h>
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;
}