Add and, or, xor, mod, sll, srl, locals, putchar, getchar, simple if (WIP)
This commit is contained in:
parent
38585bf105
commit
cf1f665e56
102
compiler.c
102
compiler.c
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
} 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)
|
||||
|
|
|
|||
|
|
@ -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
18
emit.h
|
|
@ -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();
|
||||
|
|
|
|||
225
emit/rer/emit.c
225
emit/rer/emit.c
|
|
@ -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,12 +310,22 @@ 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)
|
||||
{
|
||||
if(local)
|
||||
printf(",/%.*s STR2 ", length, str);
|
||||
else
|
||||
printf(";%.*s STA2 ", length, str);
|
||||
}
|
||||
|
||||
|
|
@ -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,8 +382,11 @@ rer_emit_close_paren()
|
|||
}
|
||||
|
||||
void
|
||||
rer_emit_variable(Symbol *sym)
|
||||
rer_emit_variable(Symbol *sym, bool local)
|
||||
{
|
||||
if(local)
|
||||
printf(",/%.*s LDR2 ", sym->name_length, sym->name);
|
||||
else
|
||||
printf(";%.*s LDA2 ", sym->name_length, sym->name);
|
||||
}
|
||||
|
||||
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
290
emit/uxn/emit.c
290
emit/uxn/emit.c
|
|
@ -8,59 +8,19 @@
|
|||
|
||||
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,
|
||||
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\
|
||||
printf("BRK\n\n@str/<print> ( str* -- )\n\
|
||||
LDAk DUP ?{ POP POP2 JMP2r }\n\
|
||||
#18 DEO\n\
|
||||
INC2 !&>wp\n\n");
|
||||
printf("@num-to-string $12\n");
|
||||
printf("@heap\n");
|
||||
INC2 !/<print>\n");
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -181,7 +136,7 @@ uxn_emit_neg()
|
|||
void
|
||||
uxn_emit_not()
|
||||
{
|
||||
printf("#FFFF EOR2 ");
|
||||
printf("#ffff EOR2 ");
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -190,92 +145,132 @@ uxn_emit_void()
|
|||
}
|
||||
|
||||
i32
|
||||
uxn_emit_bool_type(const char *str, i32 length)
|
||||
uxn_emit_bool_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_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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
uxn_emit_i8_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_i8_type(const char *str, i32 length)
|
||||
{
|
||||
printf("!{ @%.*s $1 } ", length, str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
i32
|
||||
uxn_emit_i16_type(const char *str, i32 length)
|
||||
uxn_emit_i16_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_u16_type(const char *str, i32 length)
|
||||
uxn_emit_u16_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_i32_type(const char *str, i32 length)
|
||||
uxn_emit_i32_type(const char *str, i32 length, bool local)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if(local)
|
||||
printf("!{ &%.*s $4 } ", length, str);
|
||||
else
|
||||
printf("!{ @%.*s $4 } ", length, str);
|
||||
return 4;
|
||||
}
|
||||
|
|
@ -315,12 +310,22 @@ 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)
|
||||
{
|
||||
if(local)
|
||||
printf(",/%.*s STR2 ", length, str);
|
||||
else
|
||||
printf(";%.*s STA2 ", length, str);
|
||||
}
|
||||
|
||||
|
|
@ -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,8 +382,11 @@ uxn_emit_close_paren()
|
|||
}
|
||||
|
||||
void
|
||||
uxn_emit_variable(Symbol *sym)
|
||||
uxn_emit_variable(Symbol *sym, bool local)
|
||||
{
|
||||
if(local)
|
||||
printf(",/%.*s LDR2 ", sym->name_length, sym->name);
|
||||
else
|
||||
printf(";%.*s LDA2 ", sym->name_length, sym->name);
|
||||
}
|
||||
|
||||
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
18
lexer.c
18
lexer.c
|
|
@ -233,6 +233,8 @@ 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);
|
||||
}
|
||||
|
|
@ -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
12
lexer.h
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
int i = 122;
|
||||
int j = 32;
|
||||
|
||||
//function main() {
|
||||
print((i - j) as str);
|
||||
//}
|
||||
putchar((i - j));
|
||||
|
|
|
|||
|
|
@ -2,5 +2,5 @@ function main() {
|
|||
int i = 122;
|
||||
int j = 32;
|
||||
|
||||
print((i - j)); // prints ascii `Z`
|
||||
putchar((i - j)); // prints ascii `Z`
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue