Add and, or, xor, mod, sll, srl, locals, putchar, getchar, simple if (WIP)

This commit is contained in:
zongor 2026-04-22 00:15:31 -07:00
parent 38585bf105
commit cf1f665e56
9 changed files with 512 additions and 197 deletions

View File

@ -1,9 +1,10 @@
#include "compiler.h"
#include "common.h"
#include "emit.h"
#include "lexer.h"
Emitter emitter;
Parser parser;
Emitter emitter = {0};
Parser parser = {0};
Arena *arena;
/****************************************************
@ -141,7 +142,7 @@ binary()
emitter.emit_eq();
break;
case TOKEN_GT:
emitter.emit_ge();
emitter.emit_gt();
break;
case TOKEN_GTE:
emitter.emit_ge();
@ -164,6 +165,24 @@ binary()
case TOKEN_SLASH:
emitter.emit_div();
break;
case TOKEN_OPERATOR_AND:
emitter.emit_and();
break;
case TOKEN_OPERATOR_OR:
emitter.emit_or();
break;
case TOKEN_OPERATOR_XOR:
emitter.emit_xor();
break;
case TOKEN_OPERATOR_MOD:
emitter.emit_mod();
break;
case TOKEN_SLL:
emitter.emit_sll();
break;
case TOKEN_SRL:
emitter.emit_srl();
break;
default:
return;
}
@ -204,7 +223,7 @@ variable()
}
parser.current_type = sym->type;
emitter.emit_variable(sym);
emitter.emit_variable(sym, parser.depth);
}
static void
@ -233,7 +252,7 @@ cast_type()
emitter.error("Not castable to this type", 26, parser.previous.line);
}
break;
break;
}
case TOKEN_TYPE_NAT:{
switch(st) {
@ -313,77 +332,77 @@ variable_declaration()
switch(tt) {
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, parser.depth);
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_INT,
size);
parser.current_type = SYMBOL_INT;
break;
}
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, parser.depth);
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_NAT,
size);
parser.current_type = SYMBOL_NAT;
break;
}
case TOKEN_TYPE_REAL: {
size = emitter.emit_real_type(parser.current.start, parser.current.length);
size = emitter.emit_real_type(parser.current.start, parser.current.length, parser.depth);
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_REAL,
size);
parser.current_type = SYMBOL_REAL;
break;
}
case TOKEN_TYPE_STR: {
size = emitter.emit_str_type(parser.current.start, parser.current.length);
size = emitter.emit_str_type(parser.current.start, parser.current.length, parser.depth);
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_STR,
size);
parser.current_type = SYMBOL_STR;
break;
}
case TOKEN_TYPE_BOOL: {
size = emitter.emit_bool_type(parser.current.start, parser.current.length);
size = emitter.emit_bool_type(parser.current.start, parser.current.length, parser.depth);
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_BOOL,
size);
parser.current_type = SYMBOL_BOOL;
break;
}
case TOKEN_TYPE_BYTE: {
size = emitter.emit_byte_type(parser.current.start, parser.current.length);
size = emitter.emit_byte_type(parser.current.start, parser.current.length, parser.depth);
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_U8,
size);
parser.current_type = SYMBOL_BYTE;
break;
}
case TOKEN_TYPE_U8: {
size = emitter.emit_u8_type(parser.current.start, parser.current.length);
size = emitter.emit_u8_type(parser.current.start, parser.current.length, parser.depth);
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_U8,
size);
parser.current_type = SYMBOL_U8;
break;
}
case TOKEN_TYPE_I8: {
size = emitter.emit_i8_type(parser.current.start, parser.current.length);
size = emitter.emit_i8_type(parser.current.start, parser.current.length, parser.depth);
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_I8,
size);
parser.current_type = SYMBOL_I8;
break;
}
case TOKEN_TYPE_U16: {
size = emitter.emit_u16_type(parser.current.start, parser.current.length);
size = emitter.emit_u16_type(parser.current.start, parser.current.length, parser.depth);
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_U16,
size);
parser.current_type = SYMBOL_U16;
break;
}
case TOKEN_TYPE_I16: {
size = emitter.emit_i16_type(parser.current.start, parser.current.length);
size = emitter.emit_i16_type(parser.current.start, parser.current.length, parser.depth);
scope_add_symbol(parser.current.start, parser.current.length, SYMBOL_I16,
size);
parser.current_type = SYMBOL_I16;
break;
}
default: {
/* probably a variable */
/* probably a plex */
break;
}
}
@ -393,7 +412,7 @@ variable_declaration()
if(match(TOKEN_EQ)) {
emitter.emit_set_value();
expression();
emitter.emit_constant(var.start, var.length);
emitter.emit_constant(var.start, var.length, parser.depth);
}
consume(TOKEN_SEMICOLON);
@ -425,6 +444,35 @@ print_statement()
emitter.emit_print();
}
static void
putchar_statement()
{
expression();
consume(TOKEN_SEMICOLON);
emitter.emit_end_statement();
emitter.emit_putchar();
}
static void
getchar_statement()
{
expression();
consume(TOKEN_SEMICOLON);
emitter.emit_end_statement();
emitter.emit_putchar();
}
static void
if_statement()
{
consume(TOKEN_LPAREN);
expression();
consume(TOKEN_RPAREN);
emitter.emit_jump();
statement();
emitter.emit_patch_jump();
}
static void
block()
{
@ -440,8 +488,14 @@ statement()
scope_push();
block();
scope_pop();
} else if(match(TOKEN_KEYWORD_IF)) {
if_statement();
} else if(match(TOKEN_KEYWORD_PRINT)) {
print_statement();
print_statement();
} else if(match(TOKEN_KEYWORD_PUTCHAR)) {
putchar_statement();
} else if(match(TOKEN_KEYWORD_GETCHAR)) {
getchar_statement();
} else {
expression();
}
@ -521,7 +575,6 @@ ParseRule rules[] = {
/* TOKEN_KEYWORD_USE */ {nil, nil, PREC_NONE},
/* TOKEN_KEYWORD_INIT */ {nil, nil, PREC_NONE},
/* TOKEN_KEYWORD_THIS */ {nil, nil, PREC_NONE},
/* TOKEN_KEYWORD_GLOBAL */ {nil, nil, PREC_NONE},
/* TOKEN_KEYWORD_OPEN */ {nil, nil, PREC_NONE},
/* TOKEN_KEYWORD_READ */ {nil, nil, PREC_NONE},
/* TOKEN_KEYWORD_WRITE */ {nil, nil, PREC_NONE},
@ -532,10 +585,12 @@ ParseRule rules[] = {
/* TOKEN_KEYWORD_NIL */ {literal, nil, PREC_NONE},
/* TOKEN_KEYWORD_TRUE */ {literal, nil, PREC_NONE},
/* TOKEN_KEYWORD_FALSE */ {literal, nil, PREC_NONE},
/* TOKEN_KEYWORD_PRINT */ {nil, nil, PREC_NONE},
/* TOKEN_OPERATOR_NOT */ {nil, nil, PREC_NONE},
/* TOKEN_OPERATOR_AND */ {nil, nil, PREC_NONE},
/* TOKEN_OPERATOR_OR */ {nil, nil, PREC_NONE},
/* TOKEN_KEYWORD_PUTCHAR */ {nil, nil, PREC_NONE},
/* TOKEN_KEYWORD_GETCHAR */ {nil, nil, PREC_NONE},
/* TOKEN_OPERATOR_AND */ {nil, binary, PREC_NONE},
/* TOKEN_OPERATOR_OR */ {nil, binary, PREC_NONE},
/* TOKEN_OPERATOR_XOR */ {nil, binary, PREC_NONE},
/* TOKEN_OPERATOR_MOD */ {nil, binary, PREC_NONE},
/* TOKEN_BANG */ {unary, nil, PREC_NONE},
/* TOKEN_BANG_EQ */ {nil, binary, PREC_EQUALITY},
/* TOKEN_EQ */ {nil, nil, PREC_NONE},
@ -567,7 +622,10 @@ ParseRule rules[] = {
/* TOKEN_RBRACE */ {nil, nil, PREC_NONE},
/* TOKEN_LBRACKET */ {nil, nil, PREC_NONE},
/* TOKEN_RBRACKET */ {nil, nil, PREC_NONE},
/* TOKEN_ARROW_RIGHT */ {nil, nil, PREC_NONE}};
/* TOKEN_ARROW_RIGHT */ {nil, nil, PREC_NONE},
/* TOKEN_SLL */ {nil, binary, PREC_NONE},
/* TOKEN_SRL */ {nil, binary, PREC_NONE},
/*TOKEN_KEYWORD_PRINT*/{nil, binary, PREC_NONE} };
static void
parse_precedence(Precedence precedence)

View File

@ -42,6 +42,7 @@ struct parser_s {
Token current;
Token previous;
SymbolType current_type;
u32 depth;
};
bool compile(Arena *a, Emitter e, char *source);

18
emit.h
View File

@ -8,7 +8,9 @@ typedef void (*SymbolEmit)(Symbol *sym);
typedef void (*ErrorMsg)(const char *str, i32 length, i32 line);
typedef void (*VoidArgEmit)();
typedef void (*StrArgEmit)(const char *str, i32 length);
typedef i32 (*TypeVariableEmit)(const char *str, i32 length);
typedef i32 (*TypeVariableEmit)(const char *str, i32 length, bool local);
typedef void (*ConstEmit)(const char *str, i32 length, bool local);
typedef void (*VarEmit)(Symbol *sym, bool local);
typedef struct emitter_s Emitter;
struct emitter_s {
@ -54,12 +56,14 @@ struct emitter_s {
VoidArgEmit emit_trait;
VoidArgEmit emit_const;
VoidArgEmit emit_print;
VoidArgEmit emit_putchar;
VoidArgEmit emit_getchar;
VoidArgEmit emit_neg;
VoidArgEmit emit_not;
VoidArgEmit emit_open_paren;
VoidArgEmit emit_close_paren;
StrArgEmit emit_constant;
SymbolEmit emit_variable;
ConstEmit emit_constant;
VarEmit emit_variable;
VoidArgEmit emit_write;
VoidArgEmit emit_read;
VoidArgEmit emit_open;
@ -87,6 +91,14 @@ struct emitter_s {
VoidArgEmit emit_cast_str_to_int;
VoidArgEmit emit_cast_str_to_nat;
VoidArgEmit emit_cast_str_to_real;
VoidArgEmit emit_sll;
VoidArgEmit emit_srl;
VoidArgEmit emit_xor;
VoidArgEmit emit_mod;
VoidArgEmit emit_and;
VoidArgEmit emit_or;
VoidArgEmit emit_jump;
VoidArgEmit emit_patch_jump;
};
Emitter rer_emitter();

View File

@ -2,6 +2,25 @@
#include <stdio.h>
#include <stdlib.h>
#define RER_OP_2 (1 << 5)
#define RER_OP_R (1 << 6)
#define RER_OP_K (1 << 7)
enum rer_opcode {
/* Stack I */ /* Logic */ /* Memory I */ /* Arithmetic*/
BRK = 0x00, EQU = 0x08, LDZ = 0x10, ADD = 0x18,
INC = 0x01, NEQ = 0x09, STZ = 0x11, SUB = 0x19,
POP = 0x02, GTH = 0x0A, LDR = 0x12, MUL = 0x1A,
NIP = 0x03, LTH = 0x0B, STR = 0x13, DIV = 0x1B,
/* Stack II */ /* Stash */ /* Memory II */ /* Bitwise */
SWP = 0x04, JMP = 0x0C, LDA = 0x14, AND = 0x1C,
ROT = 0x05, JCN = 0x0D, STA = 0x15, ORA = 0x1D,
DUP = 0x06, JSR = 0x0E, DEI = 0x16, EOR = 0x1E,
OVR = 0x07, STH = 0x0F, DEO = 0x17, SFT = 0x1F,
LIT = 0x80, JCI = 0x20, JMI = 0x40, JSI = 0x60,
};
void
rer_emit_error(const char *str, i32 length, i32 line)
{
@ -18,87 +37,106 @@ rer_mem(u32 a)
void
rer_prolog()
{
printf("|100\n");
}
void
rer_epilogue()
{
printf("\n\n@str/<print> ( str* -- )\n\
LDAk DUP ?{ POP POP2 JMP2r }\n\
#18 DEO\n\
INC2 !/<print>\n");
}
void
rer_emit_add()
{
printf("ADD2 ");
}
void
rer_emit_sub()
{
printf("SUB2 ");
}
void
rer_emit_mul()
{
printf("MUL2 ");
}
void
rer_emit_div()
{
printf("DIV2 ");
}
void
rer_emit_lt()
{
printf("LTH2 ");
}
void
rer_emit_le()
{
printf("ROT SWP LTH ?{ LTH #00 EQU JMPr } GTH JMPr ");
}
void
rer_emit_gt()
{
printf("GTH2 ");
}
void
rer_emit_ge()
{
printf("ROT SWP GTH ?{ GTH #00 EQU JMPr } LTH JMPr ");
}
void
rer_emit_ne()
{
printf("NEQ2 ");
}
void
rer_emit_eq()
{
printf("EQU2 ");
}
void
rer_emit_false()
{
printf("#0000 ");
}
void
rer_emit_true()
{
printf("#0001 ");
}
void
rer_emit_nil()
{
printf("#0000 ");
}
void
rer_emit_neg()
{
printf("#0000 SUB2 ");
}
void
rer_emit_not()
{
printf("#FFFF EOR2 ");
}
void
@ -107,93 +145,133 @@ rer_emit_void()
}
i32
rer_emit_bool_type(const char *str, i32 length)
rer_emit_bool_type(const char *str, i32 length, bool local)
{
USED(str);USED(length);
if(local)
printf("!{ &%.*s $1 } ", length, str);
else
printf("!{ @%.*s $1 } ", length, str);
return 1;
}
i32
rer_emit_byte_type(const char *str, i32 length)
rer_emit_byte_type(const char *str, i32 length, bool local)
{
USED(str);USED(length);
if(local)
printf("!{ &%.*s $1 } ", length, str);
else
printf("!{ @%.*s $1 } ", length, str);
return 1;
}
i32
rer_emit_int_type(const char *str, i32 length)
rer_emit_int_type(const char *str, i32 length, bool local)
{
USED(str);USED(length);
if(local)
printf("!{ &%.*s $2 } ", length, str);
else
printf("!{ @%.*s $2 } ", length, str);
return 2;
}
i32
rer_emit_nat_type(const char *str, i32 length)
rer_emit_nat_type(const char *str, i32 length, bool local)
{
USED(str);USED(length);
if(local)
printf("!{ &%.*s $2 } ", length, str);
else
printf("!{ @%.*s $2 } ", length, str);
return 2;
}
i32
rer_emit_real_type(const char *str, i32 length)
rer_emit_real_type(const char *str, i32 length, bool local)
{
USED(str);USED(length);
if(local)
printf("!{ &%.*s $2 } ", length, str);
else
printf("!{ @%.*s $2 } ", length, str);
return 2;
}
i32
rer_emit_str_type(const char *str, i32 length)
rer_emit_str_type(const char *str, i32 length, bool local)
{
USED(str);USED(length);
if(local)
printf("!{ &%.*s $2 } ", length, str);
else
printf("!{ @%.*s $2 } ", length, str);
return 2;
}
i32
rer_emit_u8_type(const char *str, i32 length)
rer_emit_u8_type(const char *str, i32 length, bool local)
{
USED(str);USED(length);
if(local)
printf("!{ &%.*s $1 } ", length, str);
else
printf("!{ @%.*s $1 } ", length, str);
return 1;
}
i32
rer_emit_i8_type(const char *str, i32 length)
rer_emit_i8_type(const char *str, i32 length, bool local)
{
USED(str);USED(length);
if(local)
printf("!{ &%.*s $1 } ", length, str);
else
printf("!{ @%.*s $1 } ", length, str);
return 1;
}
i32
rer_emit_i16_type(const char *str, i32 length)
rer_emit_i16_type(const char *str, i32 length, bool local)
{
USED(str);USED(length);
if(local)
printf("!{ &%.*s $2 } ", length, str);
else
printf("!{ @%.*s $2 } ", length, str);
return 2;
}
i32
rer_emit_u16_type(const char *str, i32 length)
rer_emit_u16_type(const char *str, i32 length, bool local)
{
USED(str);USED(length);
if(local)
printf("!{ &%.*s $2 } ", length, str);
else
printf("!{ @%.*s $2 } ", length, str);
return 2;
}
i32
rer_emit_i32_type(const char *str, i32 length)
rer_emit_i32_type(const char *str, i32 length, bool local)
{
USED(str);USED(length);
if(local)
printf("!{ &%.*s $4 } ", length, str);
else
printf("!{ @%.*s $4 } ", length, str);
return 4;
}
i32
rer_emit_u32_type(const char *str, i32 length)
rer_emit_u32_type(const char *str, i32 length, bool local)
{
USED(str);USED(length);
if(local)
printf("!{ &%.*s $4 } ", length, str);
else
printf("!{ @%.*s $4 } ", length, str);
return 4;
}
i32
rer_emit_f32_type(const char *str, i32 length)
rer_emit_f32_type(const char *str, i32 length, bool local)
{
USED(str);USED(length);
if(local)
printf("!{ &%.*s $4 } ", length, str);
else
printf("!{ @%.*s $4 } ", length, str);
return 4;
}
@ -232,13 +310,23 @@ rer_emit_byte(const char *str, i32 length)
void
rer_emit_str(const char *str, i32 length)
{
printf("\"%.*s ", length, str);
/* set a pointer to the string literal and then jump over it */
printf(";{ #0002 ADD2 } !{ ");
for (i32 i = 1; i < length - 1 ; i++) {
printf("#%02x ", str[i]);
}
printf("#00 } ");
}
void
rer_emit_constant(const char *str, i32 length)
rer_emit_constant(const char *str, i32 length, bool local)
{
printf(";%.*s STA2 ", length, str);
if(local)
printf(",/%.*s STR2 ", length, str);
else
printf(";%.*s STA2 ", length, str);
}
void
@ -272,9 +360,15 @@ rer_emit_const()
}
void
rer_emit_print()
rer_emit_putchar()
{
printf("print ");
printf("#18 DEO ");
}
void
rer_emit_getchar()
{
printf("#12 DEI ");
}
void
@ -288,9 +382,12 @@ rer_emit_close_paren()
}
void
rer_emit_variable(Symbol *sym)
rer_emit_variable(Symbol *sym, bool local)
{
printf(";%.*s LDA2 ", sym->name_length, sym->name);
if(local)
printf(",/%.*s LDR2 ", sym->name_length, sym->name);
else
printf(";%.*s LDA2 ", sym->name_length, sym->name);
}
void
@ -426,6 +523,60 @@ rer_emit_cast_str_to_real()
{
}
void
rer_emit_sll()
{
printf("#40 SFT SFT ");
}
void
rer_emit_srl()
{
printf("SFT ");
}
void
rer_emit_xor()
{
printf("EOR2 ");
}
void
rer_emit_mod()
{
printf("DIV2k MUL2 SUB2 ");
}
void
rer_emit_or()
{
printf("ORA2 ");
}
void
rer_emit_and()
{
printf("AND2 ");
}
void
rer_emit_print()
{
printf("str/<print> ");
}
void
rer_emit_jump()
{
printf("?{ ");
}
void
rer_emit_patch_jump()
{
printf("} ");
}
Emitter
rer_emitter()
{
@ -472,6 +623,8 @@ rer_emitter()
rer_emit_trait,
rer_emit_const,
rer_emit_print,
rer_emit_putchar,
rer_emit_getchar,
rer_emit_neg,
rer_emit_not,
rer_emit_open_paren,
@ -505,5 +658,13 @@ rer_emitter()
rer_emit_cast_str_to_int,
rer_emit_cast_str_to_nat,
rer_emit_cast_str_to_real,
rer_emit_sll,
rer_emit_srl,
rer_emit_xor,
rer_emit_mod,
rer_emit_and,
rer_emit_or,
rer_emit_jump,
rer_emit_patch_jump,
};
}

View File

@ -7,60 +7,20 @@
#define UXN_OP_K (1 << 7)
enum uxn_opcode {
/* Stack I */ /* Logic */ /* Memory I */ /* Arithmetic*/
BRK = 0x00,
EQU = 0x08,
LDZ = 0x10,
ADD = 0x18,
INC = 0x01,
NEQ = 0x09,
STZ = 0x11,
SUB = 0x19,
POP = 0x02,
GTH = 0x0A,
LDR = 0x12,
MUL = 0x1A,
NIP = 0x03,
LTH = 0x0B,
STR = 0x13,
DIV = 0x1B,
/* Stack I */ /* Logic */ /* Memory I */ /* Arithmetic*/
BRK = 0x00, EQU = 0x08, LDZ = 0x10, ADD = 0x18,
INC = 0x01, NEQ = 0x09, STZ = 0x11, SUB = 0x19,
POP = 0x02, GTH = 0x0A, LDR = 0x12, MUL = 0x1A,
NIP = 0x03, LTH = 0x0B, STR = 0x13, DIV = 0x1B,
/* Stack II */ /* Stash */ /* Memory II */ /* Bitwise */
SWP = 0x04,
JMP = 0x0C,
LDA = 0x14,
AND = 0x1C,
ROT = 0x05,
JCN = 0x0D,
STA = 0x15,
ORA = 0x1D,
DUP = 0x06,
JSR = 0x0E,
DEI = 0x16,
EOR = 0x1E,
OVR = 0x07,
STH = 0x0F,
DEO = 0x17,
SFT = 0x1F,
SWP = 0x04, JMP = 0x0C, LDA = 0x14, AND = 0x1C,
ROT = 0x05, JCN = 0x0D, STA = 0x15, ORA = 0x1D,
DUP = 0x06, JSR = 0x0E, DEI = 0x16, EOR = 0x1E,
OVR = 0x07, STH = 0x0F, DEO = 0x17, SFT = 0x1F,
LIT = 0x80,
JCI = 0x20,
JMI = 0x40,
JSI = 0x60,
LIT = 0x80, JCI = 0x20, JMI = 0x40, JSI = 0x60,
};
/*
https://rosettacode.org/wiki/Bitwise_operations#Uxntal
%not { #ff EOR }
%and { AND }
%or { ORA }
%xor { EOR }
%shl { #40 SFT SFT }
%shr { SFT }
%rol { #40 SFT #00 ROT ROT SFT2 ORA }
%ror { SWP #00 ROT SFT2 ORA }
*/
void
uxn_emit_error(const char *str, i32 length, i32 line)
{
@ -77,21 +37,16 @@ uxn_mem(u32 a)
void
uxn_prolog()
{
printf("|100 @main ( -> )\n");
printf("|100\n");
}
void
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");
printf("BRK\n\n@str/<print> ( str* -- )\n\
LDAk DUP ?{ POP POP2 JMP2r }\n\
#18 DEO\n\
INC2 !/<print>\n");
}
void
@ -181,7 +136,7 @@ uxn_emit_neg()
void
uxn_emit_not()
{
printf("#FFFF EOR2 ");
printf("#ffff EOR2 ");
}
void
@ -190,93 +145,133 @@ uxn_emit_void()
}
i32
uxn_emit_bool_type(const char *str, i32 length)
uxn_emit_bool_type(const char *str, i32 length, bool local)
{
printf("!{ @%.*s $1 } ", length, str);
if(local)
printf("!{ &%.*s $2 } ", length, str);
else
printf("!{ @%.*s $2 } ", length, str);
return 2;
}
i32
uxn_emit_byte_type(const char *str, i32 length, bool local)
{
if(local)
printf("!{ &%.*s $1 } ", length, str);
else
printf("!{ @%.*s $1 } ", length, str);
return 1;
}
i32
uxn_emit_byte_type(const char *str, i32 length)
uxn_emit_int_type(const char *str, i32 length, bool local)
{
printf("!{ @%.*s $1 } ", length, str);
if(local)
printf("!{ &%.*s $2 } ", length, str);
else
printf("!{ @%.*s $2 } ", length, str);
return 2;
}
i32
uxn_emit_nat_type(const char *str, i32 length, bool local)
{
if(local)
printf("!{ &%.*s $2 } ", length, str);
else
printf("!{ @%.*s $2 } ", length, str);
return 2;
}
i32
uxn_emit_real_type(const char *str, i32 length, bool local)
{
if(local)
printf("!{ &%.*s $2 } ", length, str);
else
printf("!{ @%.*s $2 } ", length, str);
return 2;
}
i32
uxn_emit_str_type(const char *str, i32 length, bool local)
{
if(local)
printf("!{ &%.*s $2 } ", length, str);
else
printf("!{ @%.*s $2 } ", length, str);
return 2;
}
i32
uxn_emit_u8_type(const char *str, i32 length, bool local)
{
if(local)
printf("!{ &%.*s $1 } ", length, str);
else
printf("!{ @%.*s $1 } ", length, str);
return 1;
}
i32
uxn_emit_int_type(const char *str, i32 length)
uxn_emit_i8_type(const char *str, i32 length, bool local)
{
printf("!{ @%.*s $2 } ", length, str);
return 2;
}
i32
uxn_emit_nat_type(const char *str, i32 length)
{
printf("!{ @%.*s $2 } ", length, str);
return 2;
}
i32
uxn_emit_real_type(const char *str, i32 length)
{
printf("!{ @%.*s $2 } ", length, str);
return 2;
}
i32
uxn_emit_str_type(const char *str, i32 length)
{
printf("!{ @%.*s $2 } ", length, str);
return 2;
}
i32
uxn_emit_u8_type(const char *str, i32 length)
{
printf("!{ @%.*s $1 } ", length, str);
if(local)
printf("!{ &%.*s $1 } ", length, str);
else
printf("!{ @%.*s $1 } ", length, str);
return 1;
}
i32
uxn_emit_i8_type(const char *str, i32 length)
uxn_emit_i16_type(const char *str, i32 length, bool local)
{
printf("!{ @%.*s $1 } ", length, str);
return 1;
}
i32
uxn_emit_i16_type(const char *str, i32 length)
{
printf("!{ @%.*s $2 } ", length, str);
if(local)
printf("!{ &%.*s $2 } ", length, str);
else
printf("!{ @%.*s $2 } ", length, str);
return 2;
}
i32
uxn_emit_u16_type(const char *str, i32 length)
uxn_emit_u16_type(const char *str, i32 length, bool local)
{
printf("!{ @%.*s $2 } ", length, str);
if(local)
printf("!{ &%.*s $2 } ", length, str);
else
printf("!{ @%.*s $2 } ", length, str);
return 2;
}
i32
uxn_emit_i32_type(const char *str, i32 length)
uxn_emit_i32_type(const char *str, i32 length, bool local)
{
printf("!{ @%.*s $4 } ", length, str);
if(local)
printf("!{ &%.*s $4 } ", length, str);
else
printf("!{ @%.*s $4 } ", length, str);
return 4;
}
i32
uxn_emit_u32_type(const char *str, i32 length)
uxn_emit_u32_type(const char *str, i32 length, bool local)
{
printf("!{ @%.*s $4 } ", length, str);
if(local)
printf("!{ &%.*s $4 } ", length, str);
else
printf("!{ @%.*s $4 } ", length, str);
return 4;
}
i32
uxn_emit_f32_type(const char *str, i32 length)
uxn_emit_f32_type(const char *str, i32 length, bool local)
{
printf("!{ @%.*s $4 } ", length, str);
if(local)
printf("!{ &%.*s $4 } ", length, str);
else
printf("!{ @%.*s $4 } ", length, str);
return 4;
}
@ -315,13 +310,23 @@ uxn_emit_byte(const char *str, i32 length)
void
uxn_emit_str(const char *str, i32 length)
{
printf("\"%.*s ", length, str);
/* set a pointer to the string literal and then jump over it */
printf(";{ #0002 ADD2 } !{ ");
for (i32 i = 1; i < length - 1 ; i++) {
printf("#%02x ", str[i]);
}
printf("#00 } ");
}
void
uxn_emit_constant(const char *str, i32 length)
uxn_emit_constant(const char *str, i32 length, bool local)
{
printf(";%.*s STA2 ", length, str);
if(local)
printf(",/%.*s STR2 ", length, str);
else
printf(";%.*s STA2 ", length, str);
}
void
@ -355,9 +360,15 @@ uxn_emit_const()
}
void
uxn_emit_print()
uxn_emit_putchar()
{
printf("print ");
printf("#18 DEO ");
}
void
uxn_emit_getchar()
{
printf("#12 DEI ");
}
void
@ -371,9 +382,12 @@ uxn_emit_close_paren()
}
void
uxn_emit_variable(Symbol *sym)
uxn_emit_variable(Symbol *sym, bool local)
{
printf(";%.*s LDA2 ", sym->name_length, sym->name);
if(local)
printf(",/%.*s LDR2 ", sym->name_length, sym->name);
else
printf(";%.*s LDA2 ", sym->name_length, sym->name);
}
void
@ -509,6 +523,60 @@ uxn_emit_cast_str_to_real()
{
}
void
uxn_emit_sll()
{
printf("#40 SFT SFT ");
}
void
uxn_emit_srl()
{
printf("SFT ");
}
void
uxn_emit_xor()
{
printf("EOR2 ");
}
void
uxn_emit_mod()
{
printf("DIV2k MUL2 SUB2 ");
}
void
uxn_emit_or()
{
printf("ORA2 ");
}
void
uxn_emit_and()
{
printf("AND2 ");
}
void
uxn_emit_print()
{
printf("str/<print> ");
}
void
uxn_emit_jump()
{
printf("?{ ");
}
void
uxn_emit_patch_jump()
{
printf("} ");
}
Emitter
uxn_emitter()
{
@ -555,6 +623,8 @@ uxn_emitter()
uxn_emit_trait,
uxn_emit_const,
uxn_emit_print,
uxn_emit_putchar,
uxn_emit_getchar,
uxn_emit_neg,
uxn_emit_not,
uxn_emit_open_paren,
@ -588,5 +658,13 @@ uxn_emitter()
uxn_emit_cast_str_to_int,
uxn_emit_cast_str_to_nat,
uxn_emit_cast_str_to_real,
uxn_emit_sll,
uxn_emit_srl,
uxn_emit_xor,
uxn_emit_mod,
uxn_emit_and,
uxn_emit_or,
uxn_emit_jump,
uxn_emit_patch_jump,
};
}

20
lexer.c
View File

@ -233,8 +233,10 @@ identifierType()
return check_keyword(2, 1, "r", TOKEN_TYPE_PTR);
case 'l':
return check_keyword(2, 2, "ex", TOKEN_KEYWORD_PLEX);
case 'u':
return check_keyword(2, 5, "tchar", TOKEN_KEYWORD_PUTCHAR);
case 'r':
return check_keyword(2, 3, "int", TOKEN_KEYWORD_PRINT);
return check_keyword(2, 3, "int", TOKEN_KEYWORD_PRINT);
}
}
break;
@ -321,13 +323,17 @@ identifierType()
}
break;
case 'g':
return check_keyword(1, 5, "lobal", TOKEN_KEYWORD_GLOBAL);
return check_keyword(1, 6, "etchar", TOKEN_KEYWORD_GETCHAR);
case 'l':
return check_keyword(1, 3, "oop", TOKEN_KEYWORD_LOOP);
case 'd':
return check_keyword(1, 1, "o", TOKEN_KEYWORD_DO);
case 'v':
return check_keyword(1, 3, "oid", TOKEN_TYPE_VOID);
case 'x':
return check_keyword(1, 2, "or", TOKEN_OPERATOR_XOR);
case 'm':
return check_keyword(1, 2, "od", TOKEN_OPERATOR_MOD);
}
return TOKEN_IDENTIFIER;
@ -426,9 +432,9 @@ next_token()
case '=':
return make_token(match('=') ? TOKEN_EQ_EQ : TOKEN_EQ);
case '<':
return make_token(match('=') ? TOKEN_LTE : TOKEN_LT);
return make_token(match('=') ? TOKEN_LTE : match('<') ? TOKEN_SLL : TOKEN_LT);
case '>':
return make_token(match('=') ? TOKEN_GTE : TOKEN_GT);
return make_token(match('=') ? TOKEN_GTE : match('>') ? TOKEN_SRL : TOKEN_GT);
case '"':
return string();
}
@ -504,10 +510,8 @@ token_type_to_string(TokenType type)
return "KEYWORD_TRUE";
case TOKEN_KEYWORD_FALSE:
return "KEYWORD_FALSE";
case TOKEN_KEYWORD_GLOBAL:
return "KEYWORD_GLOBAL";
case TOKEN_OPERATOR_NOT:
return "OPERATOR_NOT";
case TOKEN_KEYWORD_GETCHAR:
return "KEYWORD_GETCHAR";
case TOKEN_OPERATOR_AND:
return "OPERATOR_AND";
case TOKEN_OPERATOR_OR:

12
lexer.h
View File

@ -36,7 +36,6 @@ typedef enum {
TOKEN_KEYWORD_USE,
TOKEN_KEYWORD_INIT,
TOKEN_KEYWORD_THIS,
TOKEN_KEYWORD_GLOBAL,
TOKEN_KEYWORD_OPEN,
TOKEN_KEYWORD_READ,
TOKEN_KEYWORD_WRITE,
@ -47,10 +46,12 @@ typedef enum {
TOKEN_KEYWORD_NIL,
TOKEN_KEYWORD_TRUE,
TOKEN_KEYWORD_FALSE,
TOKEN_KEYWORD_PRINT,
TOKEN_OPERATOR_NOT,
TOKEN_KEYWORD_PUTCHAR,
TOKEN_KEYWORD_GETCHAR,
TOKEN_OPERATOR_AND,
TOKEN_OPERATOR_OR,
TOKEN_OPERATOR_XOR,
TOKEN_OPERATOR_MOD,
TOKEN_BANG,
TOKEN_BANG_EQ,
TOKEN_EQ,
@ -82,7 +83,10 @@ typedef enum {
TOKEN_RBRACE,
TOKEN_LBRACKET,
TOKEN_RBRACKET,
TOKEN_ARROW_RIGHT
TOKEN_ARROW_RIGHT,
TOKEN_SLL,
TOKEN_SRL,
TOKEN_KEYWORD_PRINT
} TokenType;
typedef struct token_s Token;

View File

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

View File

@ -2,5 +2,5 @@ function main() {
int i = 122;
int j = 32;
print((i - j)); // prints ascii `Z`
putchar((i - j)); // prints ascii `Z`
}