rename parser to compiler, update build, change c to c99 so we can emit different versions, create a libundar for the emit-c99, update tests.

This commit is contained in:
zongor 2026-04-11 16:03:53 -07:00
parent d11bad79ec
commit e802fc3779
13 changed files with 1076 additions and 473 deletions

View File

@ -1,4 +1,4 @@
#include "../../parser.h" #include "../../compiler.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -45,7 +45,7 @@ readFile(const char *path)
void void
print_help() print_help()
{ {
printf("Usage: undar [options] file...\nOptions:\n\t-emit={c|u}\tEmitter " printf("Usage: undar [options] file...\nOptions:\n\t-emit={c99|uxn}\tEmitter "
"output, currently C source and Uxn binary.\n\n"); "output, currently C source and Uxn binary.\n\n");
} }
@ -65,9 +65,9 @@ main(int argc, char **argv)
} }
Emitter e; Emitter e;
if(seq(argv[1], "-emit=c")) { if(seq(argv[1], "-emit=c99")) {
e = c_emitter(); e = c_emitter();
} else if(seq(argv[1], "-emit=u")) { } 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");

8
build
View File

@ -74,17 +74,15 @@ 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 lexer.c -o $BUILD_DIR/lexer.o $VM_BUILD_FLAGS ${CC} -c lexer.c -o $BUILD_DIR/lexer.o $VM_BUILD_FLAGS
${CC} -c parser.c -o $BUILD_DIR/parser.o $VM_BUILD_FLAGS ${CC} -c compiler.c -o $BUILD_DIR/compiler.o $VM_BUILD_FLAGS
#BUILD_CMD="$CC -o $BUILD_DIR/undar $SRC_DIR/main.c libc.c list.c lexer.c parser.c -I$GEN_DIR $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/parser.o $BUILD_FLAGS $LINK_FLAGS" 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"
;; ;;
"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/parser.o -o $BUILD_DIR/undar.html $BUILD_FLAGS $LINK_FLAGS" 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"
;; ;;
esac esac

View File

@ -1,4 +1,4 @@
#include "parser.h" #include "compiler.h"
#include "emit.h" #include "emit.h"
Emitter emitter; Emitter emitter;
@ -196,77 +196,91 @@ expression()
parse_precedence(PREC_ASSIGNMENT); parse_precedence(PREC_ASSIGNMENT);
} }
static void variable() { static void
Symbol *sym = scope_get_symbol(parser.current_scope, parser.previous.start, parser.previous.length); variable()
{
Symbol *sym = scope_get_symbol(parser.current_scope, parser.previous.start,
parser.previous.length);
if(sym == nil) { if(sym == nil) {
emitter.error(parser.previous.start, parser.previous.length, parser.previous.line); emitter.error(parser.previous.start, parser.previous.length,
parser.previous.line);
} }
emitter.emit_variable(sym); emitter.emit_variable(sym);
} }
static void
cast_type()
{
}
static void static void
variable_declaration() variable_declaration()
{ {
i32 size = 0; i32 size = 0;
TokenType tt = parser.previous.type; TokenType tt = parser.previous.type;
Token var = parser.current; Token var = parser.current;
switch(tt) { switch(tt) {
case TOKEN_TYPE_INT: { case TOKEN_TYPE_INT: {
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, size); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_INT,
size);
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, size); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_NAT,
size);
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, size); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_REAL,
size);
break; break;
} }
case TOKEN_TYPE_STR: { case TOKEN_TYPE_STR: {
/* FIXME: this is wrong, we need to store the size of the string, not just size = emitter.emit_str_type(parser.current.start, parser.current.length);
* the pointer */ scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_STR,
/* size = emitter.emit_str_type(parser.current.start, parser.current.length, size);
*/
/* is_global()); */
/* scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_STR, size);
*/
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, size); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_BOOL,
size);
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, size); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_U8,
size);
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, size); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_U8,
size);
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, size); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_I8,
size);
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, size); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_U16,
size);
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, size); scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_I16,
size);
break; break;
} }
default: { default: {
@ -375,86 +389,85 @@ unary()
} }
ParseRule rules[] = { ParseRule rules[] = {
/* 0 */ {NULL, NULL, PREC_NONE}, /* TOKEN_ERROR */ /* TOKEN_ERROR */ {nil, nil, PREC_NONE},
/* 1 */ {NULL, NULL, PREC_NONE}, /* TOKEN_EOF */ /* TOKEN_EOF */ {nil, nil, PREC_NONE},
/* 2 */ {variable, NULL, PREC_NONE}, /* TOKEN_IDENTIFIER */ /* TOKEN_IDENTIFIER */ {variable, nil, PREC_NONE},
/* 3 */ {number, NULL, PREC_NONE}, /* TOKEN_LITERAL_INT */ /* TOKEN_LITERAL_INT */ {number, nil, PREC_NONE},
/* 4 */ {number, NULL, PREC_NONE}, /* TOKEN_LITERAL_NAT */ /* TOKEN_LITERAL_NAT */ {number, nil, PREC_NONE},
/* 5 */ {number, NULL, PREC_NONE}, /* TOKEN_LITERAL_REAL */ /* TOKEN_LITERAL_REAL */ {number, nil, PREC_NONE},
/* 6 */ {string, NULL, PREC_NONE}, /* TOKEN_LITERAL_STR */ /* TOKEN_LITERAL_STR */ {string, nil, PREC_NONE},
/* 7 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_I8 */ /* TOKEN_TYPE_I8 */ {nil, nil, PREC_NONE},
/* 8 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_I16 */ /* TOKEN_TYPE_I16 */ {nil, nil, PREC_NONE},
/* 9 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_INT */ /* TOKEN_TYPE_INT */ {nil, nil, PREC_NONE},
/*10 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_U8 */ /* TOKEN_TYPE_U8 */ {nil, nil, PREC_NONE},
/*11 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_U16 */ /* TOKEN_TYPE_U16 */ {nil, nil, PREC_NONE},
/*12 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_NAT */ /* TOKEN_TYPE_NAT */ {nil, nil, PREC_NONE},
/*13 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_REAL */ /* TOKEN_TYPE_REAL */ {nil, nil, PREC_NONE},
/*14 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_STR */ /* TOKEN_TYPE_STR */ {nil, nil, PREC_NONE},
/*15 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_BOOL */ /* TOKEN_TYPE_BOOL */ {nil, nil, PREC_NONE},
/*16 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_BYTE */ /* TOKEN_TYPE_BYTE */ {nil, nil, PREC_NONE},
/*17 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_VOID */ /* TOKEN_TYPE_VOID */ {nil, nil, PREC_NONE},
/*18 */ {NULL, NULL, PREC_NONE}, /* TOKEN_TYPE_PTR */ /* TOKEN_TYPE_PTR */ {nil, nil, PREC_NONE},
/*19 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_PLEX */ /* TOKEN_KEYWORD_PLEX */ {nil, nil, PREC_NONE},
/*20 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_FN */ /* TOKEN_KEYWORD_FN */ {nil, nil, PREC_NONE},
/*21 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_CONST */ /* TOKEN_KEYWORD_CONST */ {nil, nil, PREC_NONE},
/*22 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_IF */ /* TOKEN_KEYWORD_IF */ {nil, nil, PREC_NONE},
/*23 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_IS */ /* TOKEN_KEYWORD_IS */ {nil, nil, PREC_NONE},
/*24 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_AS */ /* TOKEN_KEYWORD_AS */ {nil, cast_type, PREC_NONE},
/*25 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_ELSE */ /* TOKEN_KEYWORD_ELSE */ {nil, nil, PREC_NONE},
/*26 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_WHILE */ /* TOKEN_KEYWORD_WHILE */ {nil, nil, PREC_NONE},
/*27 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_FOR */ /* TOKEN_KEYWORD_FOR */ {nil, nil, PREC_NONE},
/*28 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_RETURN */ /* TOKEN_KEYWORD_RETURN */ {nil, nil, PREC_NONE},
/*29 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_USE */ /* TOKEN_KEYWORD_USE */ {nil, nil, PREC_NONE},
/*30 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_INIT */ /* TOKEN_KEYWORD_INIT */ {nil, nil, PREC_NONE},
/*31 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_THIS */ /* TOKEN_KEYWORD_THIS */ {nil, nil, PREC_NONE},
/*32 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_GLOBAL */ /* TOKEN_KEYWORD_GLOBAL */ {nil, nil, PREC_NONE},
/*33 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_OPEN */ /* TOKEN_KEYWORD_OPEN */ {nil, nil, PREC_NONE},
/*34 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_READ */ /* TOKEN_KEYWORD_READ */ {nil, nil, PREC_NONE},
/*35 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_WRITE */ /* TOKEN_KEYWORD_WRITE */ {nil, nil, PREC_NONE},
/*36 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_STAT */ /* TOKEN_KEYWORD_STAT */ {nil, nil, PREC_NONE},
/*37 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_CLOSE */ /* TOKEN_KEYWORD_CLOSE */ {nil, nil, PREC_NONE},
/*38 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_LOOP */ /* TOKEN_KEYWORD_LOOP */ {nil, nil, PREC_NONE},
/*39 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_DO */ /* TOKEN_KEYWORD_DO */ {nil, nil, PREC_NONE},
/*40 */ {literal, NULL, PREC_NONE}, /* TOKEN_KEYWORD_NIL */ /* TOKEN_KEYWORD_NIL */ {literal, nil, PREC_NONE},
/*41 */ {literal, NULL, PREC_NONE}, /* TOKEN_KEYWORD_TRUE */ /* TOKEN_KEYWORD_TRUE */ {literal, nil, PREC_NONE},
/*42 */ {literal, NULL, PREC_NONE}, /* TOKEN_KEYWORD_FALSE */ /* TOKEN_KEYWORD_FALSE */ {literal, nil, PREC_NONE},
/*43 */ {NULL, NULL, PREC_NONE}, /* TOKEN_KEYWORD_PRINT */ /* TOKEN_KEYWORD_PRINT */ {nil, nil, PREC_NONE},
/*44 */ {NULL, NULL, PREC_NONE}, /* TOKEN_OPERATOR_NOT */ /* TOKEN_OPERATOR_NOT */ {nil, nil, PREC_NONE},
/*45 */ {NULL, NULL, PREC_NONE}, /* TOKEN_OPERATOR_AND */ /* TOKEN_OPERATOR_AND */ {nil, nil, PREC_NONE},
/*46 */ {NULL, NULL, PREC_NONE}, /* TOKEN_OPERATOR_OR */ /* TOKEN_OPERATOR_OR */ {nil, nil, PREC_NONE},
/*47 */ {unary, NULL, PREC_NONE}, /* TOKEN_BANG */ /* TOKEN_BANG */ {unary, nil, PREC_NONE},
/*48 */ {NULL, binary, PREC_EQUALITY}, /* TOKEN_BANG_EQ */ /* TOKEN_BANG_EQ */ {nil, binary, PREC_EQUALITY},
/*49 */ {NULL, NULL, PREC_NONE}, /* TOKEN_EQ */ /* TOKEN_EQ */ {nil, nil, PREC_NONE},
/*50 */ {NULL, binary, PREC_EQUALITY}, /* TOKEN_EQ_EQ */ /* TOKEN_EQ_EQ */ {nil, binary, PREC_EQUALITY},
/*51 */ {NULL, NULL, PREC_NONE}, /* TOKEN_AND */ /* TOKEN_AND */ {nil, nil, PREC_NONE},
/*52 */ {NULL, NULL, PREC_NONE}, /* TOKEN_AND_AND */ /* TOKEN_AND_AND */ {nil, nil, PREC_NONE},
/*53 */ {NULL, NULL, PREC_NONE}, /* TOKEN_PIPE */ /* TOKEN_PIPE */ {nil, nil, PREC_NONE},
/*54 */ {NULL, NULL, PREC_NONE}, /* TOKEN_PIPE_PIPE */ /* TOKEN_PIPE_PIPE */ {nil, nil, PREC_NONE},
/*55 */ {NULL, NULL, PREC_NONE}, /* TOKEN_QUESTION */ /* TOKEN_QUESTION */ {nil, nil, PREC_NONE},
/*56 */ {NULL, NULL, PREC_NONE}, /* TOKEN_QUESTION_DOT */ /* TOKEN_QUESTION_DOT */ {nil, nil, PREC_NONE},
/*57 */ {NULL, binary, PREC_TERM}, /* TOKEN_PLUS */ /* TOKEN_PLUS */ {nil, binary, PREC_TERM},
/*58 */ {unary, binary, PREC_TERM}, /* TOKEN_MINUS */ /* TOKEN_MINUS */ {unary, binary, PREC_TERM},
/*59 */ {NULL, binary, PREC_FACTOR}, /* TOKEN_STAR */ /* TOKEN_STAR */ {nil, binary, PREC_FACTOR},
/*60 */ {NULL, binary, PREC_FACTOR}, /* TOKEN_SLASH */ /* TOKEN_SLASH */ {nil, binary, PREC_FACTOR},
/*61 */ {NULL, NULL, PREC_NONE}, /* TOKEN_MESH */ /* TOKEN_MESH */ {nil, nil, PREC_NONE},
/*62 */ {NULL, NULL, PREC_NONE}, /* TOKEN_BIG_MONEY */ /* TOKEN_BIG_MONEY */ {nil, nil, PREC_NONE},
/*63 */ {NULL, binary, PREC_COMPARISON}, /* TOKEN_GT */ /* TOKEN_GT */ {nil, binary, PREC_COMPARISON},
/*64 */ {NULL, binary, PREC_COMPARISON}, /* TOKEN_LT */ /* TOKEN_LT */ {nil, binary, PREC_COMPARISON},
/*65 */ {NULL, binary, PREC_COMPARISON}, /* TOKEN_GTE */ /* TOKEN_GTE */ {nil, binary, PREC_COMPARISON},
/*66 */ {NULL, binary, PREC_COMPARISON}, /* TOKEN_LTE */ /* TOKEN_LTE */ {nil, binary, PREC_COMPARISON},
/*67 */ {NULL, NULL, PREC_NONE}, /* TOKEN_DOT */ /* TOKEN_DOT */ {nil, nil, PREC_NONE},
/*68 */ {NULL, NULL, PREC_NONE}, /* TOKEN_COMMA */ /* TOKEN_COMMA */ {nil, nil, PREC_NONE},
/*69 */ {NULL, NULL, PREC_NONE}, /* TOKEN_COLON */ /* TOKEN_COLON */ {nil, nil, PREC_NONE},
/*70 */ {NULL, NULL, PREC_NONE}, /* TOKEN_CARET */ /* TOKEN_CARET */ {nil, nil, PREC_NONE},
/*71 */ {NULL, NULL, PREC_NONE}, /* TOKEN_SEMICOLON */ /* TOKEN_SEMICOLON */ {nil, nil, PREC_NONE},
/*72 */ {grouping, NULL, PREC_NONE}, /* TOKEN_LPAREN */ /* TOKEN_LPAREN */ {grouping, nil, PREC_NONE},
/*73 */ {NULL, NULL, PREC_NONE}, /* TOKEN_RPAREN */ /* TOKEN_RPAREN */ {nil, nil, PREC_NONE},
/*74 */ {NULL, NULL, PREC_NONE}, /* TOKEN_LBRACE */ /* TOKEN_LBRACE */ {nil, nil, PREC_NONE},
/*75 */ {NULL, NULL, PREC_NONE}, /* TOKEN_RBRACE */ /* TOKEN_RBRACE */ {nil, nil, PREC_NONE},
/*76 */ {NULL, NULL, PREC_NONE}, /* TOKEN_LBRACKET */ /* TOKEN_LBRACKET */ {nil, nil, PREC_NONE},
/*77 */ {NULL, NULL, PREC_NONE}, /* TOKEN_RBRACKET */ /* TOKEN_RBRACKET */ {nil, nil, PREC_NONE},
/*78 */ {NULL, NULL, PREC_NONE} /* TOKEN_ARROW_RIGHT */ /* TOKEN_ARROW_RIGHT */ {nil, nil, PREC_NONE}};
};
static void static void
parse_precedence(Precedence precedence) parse_precedence(Precedence precedence)
@ -464,7 +477,7 @@ parse_precedence(Precedence precedence)
advance(); advance();
prefixRule = get_rule(parser.previous.type)->prefix; prefixRule = get_rule(parser.previous.type)->prefix;
if(prefixRule == NULL) return; if(prefixRule == nil) return;
prefixRule(); prefixRule();

5
emit.h
View File

@ -73,6 +73,11 @@ struct emitter_s {
VoidArgEmit emit_close_paren; VoidArgEmit emit_close_paren;
StrArgEmit emit_constant; StrArgEmit emit_constant;
SymbolEmit emit_variable; SymbolEmit emit_variable;
VoidArgEmit emit_write;
VoidArgEmit emit_read;
VoidArgEmit emit_open;
VoidArgEmit emit_close;
VoidArgEmit emit_stat;
}; };
Emitter c_emitter(); Emitter c_emitter();

View File

@ -1,353 +0,0 @@
#include "../../emit.h"
#include <stdio.h>
#include <stdlib.h>
void
c_emit_error(const char *str, i32 length, i32 line)
{
printf("Error at line: %d > %.*s\n ", line, length, str);
exit(1);
}
void
c_prolog()
{
}
void
c_epilogue()
{
}
void
c_emit_add()
{
printf("+ ");
}
void
c_emit_sub()
{
printf("- ");
}
void
c_emit_mul()
{
printf("* ");
}
void
c_emit_div()
{
printf("/ ");
}
void
c_emit_lt()
{
printf("< ");
}
void
c_emit_le()
{
printf("<= ");
}
void
c_emit_gt()
{
printf("> ");
}
void
c_emit_ge()
{
printf(">= ");
}
void
c_emit_ne()
{
printf("!= ");
}
void
c_emit_eq()
{
printf("== ");
}
void
c_emit_false()
{
printf("false ");
}
void
c_emit_true()
{
printf("true ");
}
void
c_emit_nil()
{
printf("NULL ");
}
void
c_emit_neg()
{
printf("-");
}
void
c_emit_not()
{
printf("!");
}
void
c_emit_void()
{
}
i32
c_emit_bool_type(const char *str, i32 length)
{
printf("%.*s ", length, str);
return 1;
}
i32
c_emit_byte_type(const char *str, i32 length)
{
printf("%.*s ", length, str);
return 1;
}
i32
c_emit_int_type(const char *str, i32 length)
{
printf("%.*s ", length, str);
return 2;
}
i32
c_emit_nat_type(const char *str, i32 length)
{
printf("%.*s ", length, str);
return 2;
}
i32
c_emit_real_type(const char *str, i32 length)
{
printf("%.*s ", length, str);
return 2;
}
i32
c_emit_str_type(const char *str, i32 length)
{
printf("%.*s ", length, str);
return 2;
}
i32
c_emit_u8_type(const char *str, i32 length)
{
printf("%.*s ", length, str);
return 1;
}
i32
c_emit_i8_type(const char *str, i32 length)
{
printf("%.*s ", length, str);
return 1;
}
i32
c_emit_i16_type(const char *str, i32 length)
{
printf("%.*s ", length, str);
return 2;
}
i32
c_emit_u16_type(const char *str, i32 length)
{
printf("%.*s ", length, str);
return 2;
}
i32
c_emit_i32_type(const char *str, i32 length)
{
printf("%.*s ", length, str);
return 4;
}
i32
c_emit_u32_type(const char *str, i32 length)
{
printf("%.*s ", length, str);
return 4;
}
i32
c_emit_f32_type(const char *str, i32 length)
{
printf("%.*s ", length, str);
return 4;
}
void
c_emit_int(const char *str, i32 length)
{
printf("%.*s ", length, str);
}
void
c_emit_nat(const char *str, i32 length)
{
printf("%.*s ", length, str);
}
void
c_emit_real(const char *str, i32 length)
{
printf("%.*s ", length, str);
}
void
c_emit_byte(const char *str, i32 length)
{
printf("%.*s ", length, str);
}
void
c_emit_str(const char *str, i32 length)
{
printf("%.*s ", length, str);
}
void
c_emit_array()
{
}
void
c_emit_function()
{
}
void
c_emit_plex()
{
}
void
c_emit_method()
{
}
void
c_emit_trait()
{
}
void
c_emit_const()
{
}
void
c_emit_print()
{
printf("putchar");
}
void
c_emit_open_paren()
{
printf("(");
}
void
c_emit_close_paren()
{
printf(")");
}
void
c_emit_constant(const char *str, i32 length)
{
USED(str);
USED(length);
}
void
c_emit_variable(Symbol *sym) {
USED(sym);
}
Emitter
c_emitter()
{
return (Emitter){
INFIX,
TEXT,
c_emit_error,
c_prolog,
c_epilogue,
c_emit_add,
c_emit_sub,
c_emit_mul,
c_emit_div,
c_emit_lt,
c_emit_le,
c_emit_gt,
c_emit_ge,
c_emit_ne,
c_emit_eq,
c_emit_false,
c_emit_true,
c_emit_nil,
c_emit_void,
c_emit_int,
c_emit_nat,
c_emit_real,
c_emit_byte,
c_emit_str,
c_emit_bool_type,
c_emit_byte_type,
c_emit_int_type,
c_emit_nat_type,
c_emit_real_type,
c_emit_str_type,
c_emit_u8_type,
c_emit_i8_type,
c_emit_i16_type,
c_emit_u16_type,
c_emit_i32_type,
c_emit_u32_type,
c_emit_f32_type,
c_emit_array,
c_emit_function,
c_emit_plex,
c_emit_method,
c_emit_trait,
c_emit_const,
c_emit_print,
c_emit_neg,
c_emit_not,
c_emit_open_paren,
c_emit_close_paren,
c_emit_constant,
c_emit_variable,
};
}

384
emit/c99/emit.c Normal file
View File

@ -0,0 +1,384 @@
#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,
};
}

511
emit/c99/libundar.c Normal file
View File

@ -0,0 +1,511 @@
#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 struct node_s Node;
struct node_s {
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 void (*list_iter_fn)(void *data);
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;
}
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;
}
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');
}
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');
}
u32
slen(const char *str)
{
u32 i;
if(str == nil) return 0;
for(i = 0; str[i] != '\0'; i++);
return i;
}
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;
}
void *
aalloc(Arena *arena, u32 size)
{
u32 pos;
if(arena == nil) return nil;
if(arena->count + size > arena->capacity) return nil;
pos = arena->count;
arena->count += size;
return (void *)&arena->tape[pos];
}
void *
areturn(Arena *arena, u32 checkpoint, const void *src, u32 size)
{
void *dest;
if(arena == nil || src == nil) return nil;
dest = (void *)&arena->tape[checkpoint];
if(src == dest) return dest;
mcpy(dest, (void *)src, size);
arena->count = checkpoint + size;
return dest;
}
#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))
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_tor32oat(r32 f)
{
return REAL_TO_FLOAT(f);
}
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;
}
char *
ascpy(Arena *arena, const char *start, u32 length)
{
char *str;
if(!start) return nil;
str = (char *)aalloc(arena, length + 1);
if(!str) return nil;
scpy(str, start, length);
return str;
}
void *
amcpy(Arena *arena, void *from, u32 length)
{
void *ptr;
if(!from) return nil;
ptr = aalloc(arena, length);
if(!ptr) return nil;
mcpy(ptr, from, length);
return ptr;
}
void
int_to_string(i32 v, char *str)
{
char buffer[MAX_LEN_INT32];
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';
scpy(str, buffer + i, MAX_LEN_INT32 - i);
}
void
nat_to_string(u32 v, char *str)
{
char buffer[MAX_LEN_INT32];
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';
scpy(str, buffer + i, MAX_LEN_INT32 - i);
}
void
real_to_string(r32 q, char *str)
{
char buffer[MAX_LEN_REAL32];
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] = '-';
scpy(str, buffer + i, MAX_LEN_REAL32 - i);
}
List *
new_list(Arena *arena)
{
List *l = aalloc(arena, 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(Arena *arena, List *list, void *data, u32 data_size)
{
void *dest;
void *ptr = aalloc(arena, sizeof(Node) + data_size);
Node *node = (Node *)ptr;
if (!node) return nil;
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_foreach(List *list, list_iter_fn func)
{
Node *curr;
if (!list || !func) return;
curr = list->head;
while (curr) {
func(node_value(curr));
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) {
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;
}

View File

@ -71,13 +71,21 @@ uxn_emit_error(const char *str, i32 length, i32 line)
void void
uxn_prolog() uxn_prolog()
{ {
/* essentially the "main" function */ printf("|100 @main ( -> )\n");
printf("|100 @on-reset ( -> )\n");
} }
void void
uxn_epilogue() uxn_epilogue()
{ {
/* https://wiki.xxiivv.com/etc/lib.math.tal.txt */
printf("\n@nat-to-str ( -- ) \n\
&>wp \n\
LDAk DUP ?{ POP POP2 JMP2r } \n\
#18 DEO \n\
INC2 !&>wp\n\n");
printf("@num-to-string $12\n");
printf("@heap\n");
} }
void void
@ -175,9 +183,6 @@ uxn_emit_void()
{ {
} }
/* @global $size */
/* &local $size */
i32 i32
uxn_emit_bool_type(const char *str, i32 length) uxn_emit_bool_type(const char *str, i32 length)
{ {
@ -346,13 +351,14 @@ uxn_emit_const()
void void
uxn_emit_print() uxn_emit_print()
{ {
printf("#18 DEO "); printf("print ");
} }
void void
uxn_emit_open_paren() uxn_emit_open_paren()
{ {
} }
void void
uxn_emit_close_paren() uxn_emit_close_paren()
{ {
@ -363,6 +369,31 @@ uxn_emit_variable(Symbol *sym) {
printf(";%.*s LDA2 ", sym->name_length, sym->name); printf(";%.*s LDA2 ", sym->name_length, sym->name);
} }
void
uxn_emit_write()
{
}
void
uxn_emit_read()
{
}
void
uxn_emit_open()
{
}
void
uxn_emit_close()
{
}
void
uxn_emit_stat()
{
}
Emitter Emitter
uxn_emitter() uxn_emitter()
{ {
@ -417,5 +448,10 @@ uxn_emitter()
uxn_emit_close_paren, uxn_emit_close_paren,
uxn_emit_constant, uxn_emit_constant,
uxn_emit_variable, uxn_emit_variable,
uxn_emit_write,
uxn_emit_read,
uxn_emit_open,
uxn_emit_close,
uxn_emit_stat,
}; };
} }

View File

@ -1,6 +1,6 @@
nat i = 0; nat i = 0;
for (nat x in 10) { for (nat x in [0..10]) {
print(x as str); print(x as str);
} }

View File

@ -1,4 +1,4 @@
int i = 122; int i = 122;
int j = 32; int j = 32;
print((i - j)); // prints ascii `Z` print((i - j) as str);

View File

@ -1 +1,2 @@
print("nuqneH 'u'?"); str msg = "nuqneH 'u'?";
print(msg);

8
test/str.ul Executable file
View File

@ -0,0 +1,8 @@
str msg = " damage inflicted!\n"
int AT = 14;
int accuracy = 150;
int dmg = ((AT * accuracy) / 20) - 3;
print(dmg as str);
print(msg);