Add arena return to libc, add strbuf, add reality engine rom emitter, remove C emitter
This commit is contained in:
parent
20f44d6ad8
commit
38585bf105
51
README.org
51
README.org
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
5
build
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
4
common.h
4
common.h
|
|
@ -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
|
||||||
130
compiler.c
130
compiler.c
|
|
@ -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},
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
||||||
|
|
@ -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
37
emit.h
|
|
@ -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
|
||||||
|
|
|
||||||
384
emit/c99/emit.c
384
emit/c99/emit.c
|
|
@ -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,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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,
|
||||||
|
};
|
||||||
|
}
|
||||||
141
emit/uxn/emit.c
141
emit/uxn/emit.c
|
|
@ -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
20
lexer.c
|
|
@ -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
212
libc.c
|
|
@ -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
40
libc.h
|
|
@ -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
22
list.c
|
|
@ -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
15
list.h
|
|
@ -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
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
int i = 122;
|
int i = 122;
|
||||||
int j = 32;
|
int j = 32;
|
||||||
|
|
||||||
|
//function main() {
|
||||||
print((i - j) as str);
|
print((i - j) as str);
|
||||||
|
//}
|
||||||
|
|
|
||||||
696
test/plex.c
696
test/plex.c
|
|
@ -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;
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue