Compare commits

..

No commits in common. "84785dc3cfae494cf9a503adc52bf5d4a23c9adc" and "97e8e32ebcaf0fbc6ab386602488e009773b491d" have entirely different histories.

11 changed files with 41 additions and 167 deletions

View File

@ -3,7 +3,7 @@ k := 0
iterations := 100 iterations := 100
while k < iterations { while k - iterations {
k_f := float(k) k_f := float(k)
sum = sum + 1.0 / pow(16.0, k_f) * sum = sum + 1.0 / pow(16.0, k_f) *
(4.0 / (8.0 * k_f + 1.0) - (4.0 / (8.0 * k_f + 1.0) -

16
ir.c
View File

@ -10,10 +10,6 @@ const char *irinstr_str[IRInstrEnumSize] = {
[IRSub] = "sub", [IRSub] = "sub",
[IRMul] = "mul", [IRMul] = "mul",
[IRDiv] = "div", [IRDiv] = "div",
[IREq] = "eq",
[IRLt] = "lt",
[IRLe] = "le",
[IRNot] = "not",
[IRJmp] = "jmp", [IRJmp] = "jmp",
[IRJnz] = "jnz", [IRJnz] = "jnz",
[IRCallInternal] = "calli", [IRCallInternal] = "calli",
@ -81,9 +77,6 @@ static void print_val(const Value *v) {
case TypeInt: case TypeInt:
printf("%zd", v->Int); printf("%zd", v->Int);
break; break;
case TypeBool:
printf("%s", v->Bool ? "true" : "false");
break;
default: default:
printf("(unknown type)"); printf("(unknown type)");
break; break;
@ -112,13 +105,10 @@ void print_ir(IRToks *v, const BuiltinFunc *builtin_funcs) {
case IRSub: case IRSub:
case IRDiv: case IRDiv:
case IRMul: case IRMul:
case IREq: printf(" %%%zx ", v->toks[i].Arith.addr);
case IRLt: print_irparam(&v->toks[i].Arith.lhs);
case IRLe:
printf(" %%%zx ", v->toks[i].Binary.addr);
print_irparam(&v->toks[i].Binary.lhs);
printf(" "); printf(" ");
print_irparam(&v->toks[i].Binary.rhs); print_irparam(&v->toks[i].Arith.rhs);
break; break;
case IRJmp: case IRJmp:
printf(" %zx", v->toks[i].Jmp.iaddr); printf(" %zx", v->toks[i].Jmp.iaddr);

6
ir.h
View File

@ -18,10 +18,6 @@ enum IRInstr {
IRSub, IRSub,
IRMul, IRMul,
IRDiv, IRDiv,
IREq,
IRLt,
IRLe,
IRNot,
IRJmp, IRJmp,
IRJnz, IRJnz,
IRCallInternal, IRCallInternal,
@ -63,7 +59,7 @@ typedef struct IRTok {
struct { struct {
size_t addr; size_t addr;
IRParam lhs, rhs; IRParam lhs, rhs;
} Binary; } Arith;
struct { struct {
size_t iaddr; size_t iaddr;

35
lex.c
View File

@ -58,10 +58,6 @@ TokList lex(const char *s) {
emit(&toks, &pos, (Tok){ .kind = TokElse }); emit(&toks, &pos, (Tok){ .kind = TokElse });
else if (streq_0_n("while", start, i)) else if (streq_0_n("while", start, i))
emit(&toks, &pos, (Tok){ .kind = TokWhile }); emit(&toks, &pos, (Tok){ .kind = TokWhile });
else if (streq_0_n("true", start, i))
emit(&toks, &pos, (Tok){ .kind = TokVal, .Val = { .type = { .kind = TypeBool, }, .Bool = true, }, });
else if (streq_0_n("false", start, i))
emit(&toks, &pos, (Tok){ .kind = TokVal, .Val = { .type = { .kind = TypeBool, }, .Bool = false, }, });
else { else {
emit(&toks, &pos, (Tok){ emit(&toks, &pos, (Tok){
.kind = TokIdent, .kind = TokIdent,
@ -166,39 +162,15 @@ TokList lex(const char *s) {
break; break;
case ':': case ':':
consume(&pos, *(s++)); consume(&pos, *(s++));
if (s[0] == '=') if (s[0] == '=') {
emit(&toks, &pos, (Tok){ .kind = TokDeclare }); emit(&toks, &pos, (Tok){ .kind = TokDeclare });
else { } else {
set_err("Expected ':='"); set_err("Expected ':='");
return toks; return toks;
} }
break; break;
case '=': case '=':
consume(&pos, *(s++)); emit(&toks, &pos, (Tok){ .kind = TokAssign });
if (s[0] == '=')
emit(&toks, &pos, (Tok){ .kind = TokOp, .Op = OpEq });
else {
emit(&toks, &pos, (Tok){ .kind = TokAssign });
continue;
}
break;
case '<':
consume(&pos, *(s++));
if (s[0] == '=')
emit(&toks, &pos, (Tok){ .kind = TokOp, .Op = OpLe });
else {
emit(&toks, &pos, (Tok){ .kind = TokOp, .Op = OpLt });
continue;
}
break;
case '>':
consume(&pos, *(s++));
if (s[0] == '=')
emit(&toks, &pos, (Tok){ .kind = TokOp, .Op = OpGe });
else {
emit(&toks, &pos, (Tok){ .kind = TokOp, .Op = OpGt });
continue;
}
break; break;
case '{': case '{':
case '}': case '}':
@ -208,7 +180,6 @@ TokList lex(const char *s) {
case '+': case '+':
case '-': case '-':
case '*': case '*':
case '!':
emit(&toks, &pos, (Tok){ emit(&toks, &pos, (Tok){
.kind = TokOp, .kind = TokOp,
.Op = s[0], .Op = s[0],

7
main.c
View File

@ -35,10 +35,9 @@ static void die(const char *fmt, ...) {
static Value fn_print(Value *args) { static Value fn_print(Value *args) {
switch (args[0].type.kind) { switch (args[0].type.kind) {
case TypeVoid: printf("(void)\n"); break; case TypeVoid: printf("(void)\n"); break;
case TypeFloat: printf("%f\n", args[0].Float); break; case TypeFloat: printf("%f\n", args[0].Float); break;
case TypeInt: printf("%zd\n", args[0].Int); break; case TypeInt: printf("%zd\n", args[0].Int); break;
case TypeBool: printf("%s\n", args[0].Bool ? "true" : "false"); break;
default: default:
ASSERT_UNREACHED(); ASSERT_UNREACHED();
} }

55
parse.c
View File

@ -46,17 +46,13 @@ static void set_irtok_dest_addr(IRTok *t, size_t addr) {
switch (t->instr) { switch (t->instr) {
case IRSet: case IRSet:
case IRNeg: case IRNeg:
case IRNot:
t->Unary.addr = addr; t->Unary.addr = addr;
break; break;
case IRAdd: case IRAdd:
case IRSub: case IRSub:
case IRMul: case IRMul:
case IRDiv: case IRDiv:
case IREq: t->Arith.addr = addr;
case IRLt:
case IRLe:
t->Binary.addr = addr;
break; break;
case IRCallInternal: case IRCallInternal:
t->CallI.ret_addr = addr; t->CallI.ret_addr = addr;
@ -176,19 +172,11 @@ static ExprRet expr(IRToks *out_ir, TokList *toks, Map *funcs, Scope *parent_sc,
Scope sc = make_scope(parent_sc, false); Scope sc = make_scope(parent_sc, false);
for (;;) { for (;;) {
/* Prepare to collapse unary operation. */ /* Prepare to collapse negative factor. */
bool perform_unary = false; bool negate = false;
IRInstr unary_op; if (t->tok.kind == TokOp && t->tok.Op == OpSub) {
if (t->tok.kind == TokOp) { t = t->next;
if (t->tok.Op == OpSub) { negate = true;
t = t->next;
perform_unary = true;
unary_op = IRNeg;
} else if (t->tok.Op == OpNot) {
t = t->next;
perform_unary = true;
unary_op = IRNot;
}
} }
/* Delete newline if we're definitely expecting an operand. */ /* Delete newline if we're definitely expecting an operand. */
@ -324,28 +312,28 @@ static ExprRet expr(IRToks *out_ir, TokList *toks, Map *funcs, Scope *parent_sc,
} }
} }
/* Collapse unary operation. */ /* Collapse negative factor. */
if (perform_unary) { if (negate) {
Tok *v = &t->tok; /* what we want to perform the operation on */ Tok *v = &t->tok; /* what we want to negate */
t = t->prev; /* go back to the '-' sign */ t = t->prev; /* go back to the '-' sign */
toklist_del(toks, t->next, t->next); /* again, just removing the reference */ toklist_del(toks, t->next, t->next); /* again, just removing the reference */
bool is_last_operation = t == start && t->next->tok.kind == TokOp && op_prec[t->next->tok.Op] == PREC_DELIM; bool is_last_operation = t == start && t->next->tok.kind == TokOp && op_prec[t->next->tok.Op] == PREC_DELIM;
if (v->kind == TokVal) { if (v->kind == TokVal) {
/* immediately perform operation */ /* immediately negate value */
t->tok.kind = TokVal; t->tok.kind = TokVal;
TRY_RET(t->tok.Val = eval_unary(unary_op, &v->Val), (ExprRet){0}); t->tok.Val = eval_unary(IRNeg, &v->Val);
} else { } else {
size_t res_addr = is_last_operation ? 0 : sc.mem_addr++; size_t res_addr = is_last_operation ? 0 : sc.mem_addr++;
/* unary IR instruction */ /* Instruction to negate. */
IRParam v_irparam; IRParam v_irparam;
TRY_RET(v_irparam = tok_to_irparam(&sc, v), (ExprRet){0}); TRY_RET(v_irparam = tok_to_irparam(&sc, v), (ExprRet){0});
IRTok ir = { IRTok ir = {
.ln = t->tok.ln, .ln = t->tok.ln,
.col = t->tok.col, .col = t->tok.col,
.instr = unary_op, .instr = IRNeg,
.Unary = { .Unary = {
.addr = res_addr, .addr = res_addr,
.val = v_irparam, .val = v_irparam,
@ -433,19 +421,12 @@ static ExprRet expr(IRToks *out_ir, TokList *toks, Map *funcs, Scope *parent_sc,
* because we're still using their values later on) */ * because we're still using their values later on) */
toklist_del(toks, t->next, t->next->next); toklist_del(toks, t->next, t->next->next);
bool swap_operands = false;
IRInstr instr; IRInstr instr;
switch (l_op->Op) { switch (l_op->Op) {
case OpAdd: instr = IRAdd; break; case OpAdd: instr = IRAdd; break;
case OpSub: instr = IRSub; break; case OpSub: instr = IRSub; break;
case OpMul: instr = IRMul; break; case OpMul: instr = IRMul; break;
case OpDiv: instr = IRDiv; break; case OpDiv: instr = IRDiv; break;
case OpEq: instr = IREq; break;
case OpLt: instr = IRLt; break;
case OpLe: instr = IRLe; break;
case OpGt: instr = IRLt; swap_operands = true; break;
case OpGe: instr = IRLe; swap_operands = true; break;
default: default:
mark_err(l_op); mark_err(l_op);
set_err("Unknown operation: '%s'", op_str[l_op->Op]); set_err("Unknown operation: '%s'", op_str[l_op->Op]);
@ -454,10 +435,8 @@ static ExprRet expr(IRToks *out_ir, TokList *toks, Map *funcs, Scope *parent_sc,
if (lhs->kind == TokVal && rhs->kind == TokVal) { if (lhs->kind == TokVal && rhs->kind == TokVal) {
/* evaluate the constant expression immediately */ /* evaluate the constant expression immediately */
Value *lhs_val = swap_operands ? &rhs->Val : &lhs->Val;
Value *rhs_val = swap_operands ? &lhs->Val : &rhs->Val;
lhs->kind = TokVal; lhs->kind = TokVal;
TRY_RET(lhs->Val = eval_binary(instr, lhs_val, rhs_val), (ExprRet){0}); TRY_RET(lhs->Val = eval_arith(instr, &lhs->Val, &rhs->Val), (ExprRet){0});
} else { } else {
bool is_last_operation = t == start && r_op_prec == PREC_DELIM; bool is_last_operation = t == start && r_op_prec == PREC_DELIM;
@ -471,10 +450,10 @@ static ExprRet expr(IRToks *out_ir, TokList *toks, Map *funcs, Scope *parent_sc,
.ln = l_op->ln, .ln = l_op->ln,
.col = l_op->col, .col = l_op->col,
.instr = instr, .instr = instr,
.Binary = { .Arith = {
.addr = res_addr, .addr = res_addr,
.lhs = swap_operands ? rhs_irparam : lhs_irparam, .lhs = lhs_irparam,
.rhs = swap_operands ? lhs_irparam : rhs_irparam, .rhs = rhs_irparam,
}, },
}; };

View File

@ -2,7 +2,7 @@
#include "util.h" #include "util.h"
Value eval_binary(IRInstr instr, const Value *lhs, const Value *rhs) { Value eval_arith(IRInstr instr, const Value *lhs, const Value *rhs) {
switch (instr) { switch (instr) {
case IRAdd: case IRAdd:
case IRSub: case IRSub:
@ -39,32 +39,6 @@ Value eval_binary(IRInstr instr, const Value *lhs, const Value *rhs) {
return (Value){0}; return (Value){0};
} }
} }
case IREq:
case IRLt:
case IRLe:
bool res;
if (lhs->type.kind == TypeInt && rhs->type.kind == TypeInt) {
switch (instr) {
case IREq: res = lhs->Int == rhs->Int; break;
case IRLt: res = lhs->Int < rhs->Int; break;
case IRLe: res = lhs->Int <= rhs->Int; break;
default: ASSERT_UNREACHED();
};
} else if (lhs->type.kind == TypeFloat && rhs->type.kind == TypeFloat) {
switch (instr) {
case IREq: res = lhs->Float == rhs->Float; break;
case IRLt: res = lhs->Float < rhs->Float; break;
case IRLe: res = lhs->Float <= rhs->Float; break;
default: ASSERT_UNREACHED();
};
} else {
set_err("Unsupported types for operation '%s'", irinstr_str[instr]);
return (Value){0};
}
return (Value){
.type.kind = TypeBool,
.Bool = res,
};
default: default:
ASSERT_UNREACHED(); ASSERT_UNREACHED();
} }
@ -81,14 +55,7 @@ Value eval_unary(IRInstr instr, const Value *v) {
else if (v->type.kind == TypeFloat) else if (v->type.kind == TypeFloat)
return (Value){ .type.kind = TypeFloat, .Float = -v->Float }; return (Value){ .type.kind = TypeFloat, .Float = -v->Float };
else { else {
set_err("Unsupported type for operation '%s'", irinstr_str[instr]); set_err("Unsupported types for operation '%s'", irinstr_str[instr]);
return (Value){0};
}
case IRNot:
if (v->type.kind == TypeBool) {
return (Value){ .type.kind = TypeBool, .Bool = !v->Bool };
} else {
set_err("Unsupported type for operation '%s'", irinstr_str[instr]);
return (Value){0}; return (Value){0};
} }
default: default:
@ -100,7 +67,6 @@ bool is_nonzero(const Value *v) {
switch (v->type.kind) { switch (v->type.kind) {
case TypeInt: return v->Int != 0; case TypeInt: return v->Int != 0;
case TypeFloat: return v->Float != 0.0; case TypeFloat: return v->Float != 0.0;
case TypeBool: return v->Bool;
default: ASSERT_UNREACHED(); default: ASSERT_UNREACHED();
} }
} }
@ -109,9 +75,8 @@ Value zero_val(Type ty) {
Value ret; Value ret;
ret.type = ty; ret.type = ty;
switch (ty.kind) { switch (ty.kind) {
case TypeInt: ret.Int = 0; break; case TypeInt: ret.Int = 0; break;
case TypeFloat: ret.Float = 0.0; break; case TypeFloat: ret.Float = 0.0; break;
case TypeBool: ret.Bool = false; break;
default: ASSERT_UNREACHED(); default: ASSERT_UNREACHED();
} }
return ret; return ret;

View File

@ -3,7 +3,7 @@
#include "ir.h" #include "ir.h"
Value eval_binary(IRInstr instr, const Value *lhs, const Value *rhs); Value eval_arith(IRInstr instr, const Value *lhs, const Value *rhs);
Value eval_unary(IRInstr instr, const Value *v); Value eval_unary(IRInstr instr, const Value *v);
bool is_nonzero(const Value *v); bool is_nonzero(const Value *v);
Value zero_val(Type ty); Value zero_val(Type ty);

22
tok.c
View File

@ -11,15 +11,10 @@ int8_t op_prec[OperatorEnumSize] = {
[OpLCurl] = PREC_DELIM, [OpLCurl] = PREC_DELIM,
[OpRParen] = PREC_DELIM, [OpRParen] = PREC_DELIM,
[OpComma] = PREC_DELIM, [OpComma] = PREC_DELIM,
[OpEq] = 0, [OpAdd] = 0,
[OpLt] = 0, [OpSub] = 0,
[OpGt] = 0, [OpMul] = 1,
[OpLe] = 0, [OpDiv] = 1,
[OpGe] = 0,
[OpAdd] = 1,
[OpSub] = 1,
[OpMul] = 2,
[OpDiv] = 2,
}; };
const char *op_str[OperatorEnumSize] = { const char *op_str[OperatorEnumSize] = {
@ -32,14 +27,8 @@ const char *op_str[OperatorEnumSize] = {
[OpSub] = "-", [OpSub] = "-",
[OpMul] = "*", [OpMul] = "*",
[OpDiv] = "/", [OpDiv] = "/",
[OpNot] = "!",
[OpNewLn] = "\\n", [OpNewLn] = "\\n",
[OpEOF] = "EOF", [OpEOF] = "EOF",
[OpEq] = "==",
[OpLt] = "<",
[OpGt] = ">",
[OpLe] = "<=",
[OpGe] = ">=",
}; };
const char *tok_str[TokKindEnumSize] = { const char *tok_str[TokKindEnumSize] = {
@ -112,9 +101,6 @@ void print_toks(TokList *l) {
case TypeInt: case TypeInt:
printf(": " C_ICYAN "%zd" C_RESET, i->tok.Val.Int); printf(": " C_ICYAN "%zd" C_RESET, i->tok.Val.Int);
break; break;
case TypeBool:
printf(": " C_ICYAN "%s" C_RESET, i->tok.Val.Bool ? "true" : "false");
break;
default: default:
printf(" " C_ICYAN "(unknown type)" C_RESET); printf(" " C_ICYAN "(unknown type)" C_RESET);
break; break;

8
tok.h
View File

@ -11,7 +11,6 @@ typedef struct Type {
TypeVoid = 0, TypeVoid = 0,
TypeFloat, TypeFloat,
TypeInt, TypeInt,
TypeBool,
} kind; } kind;
/*union { /*union {
@ -24,7 +23,6 @@ typedef struct Value {
union { union {
double Float; double Float;
ssize_t Int; ssize_t Int;
bool Bool;
}; };
} Value; } Value;
@ -38,13 +36,7 @@ enum Operator {
OpSub = '-', OpSub = '-',
OpMul = '*', OpMul = '*',
OpDiv = '/', OpDiv = '/',
OpNot = '!',
OpBeginNonchars = 256, OpBeginNonchars = 256,
OpEq,
OpLt,
OpGt,
OpLe,
OpGe,
OpNewLn, OpNewLn,
OpEOF, OpEOF,
OperatorEnumSize, OperatorEnumSize,

12
vm.c
View File

@ -55,7 +55,6 @@ void run(const IRToks *ir, const BuiltinFunc *builtin_funcs) {
switch (instr->instr) { switch (instr->instr) {
case IRSet: case IRSet:
case IRNeg: case IRNeg:
case IRNot:
stack_fit(&s, instr->Unary.addr); stack_fit(&s, instr->Unary.addr);
TRY_ELSE(s.mem[instr->Unary.addr] = eval_unary(instr->instr, irparam_to_val(&s, &instr->Unary.val)), TRY_ELSE(s.mem[instr->Unary.addr] = eval_unary(instr->instr, irparam_to_val(&s, &instr->Unary.val)),
{free(fn_args); stack_term(&s);}); {free(fn_args); stack_term(&s);});
@ -64,13 +63,10 @@ void run(const IRToks *ir, const BuiltinFunc *builtin_funcs) {
case IRSub: case IRSub:
case IRDiv: case IRDiv:
case IRMul: case IRMul:
case IREq: stack_fit(&s, instr->Arith.addr);
case IRLt: TRY_ELSE(s.mem[instr->Arith.addr] = eval_arith(instr->instr,
case IRLe: irparam_to_val(&s, &instr->Arith.lhs),
stack_fit(&s, instr->Binary.addr); irparam_to_val(&s, &instr->Arith.rhs)),
TRY_ELSE(s.mem[instr->Binary.addr] = eval_binary(instr->instr,
irparam_to_val(&s, &instr->Binary.lhs),
irparam_to_val(&s, &instr->Binary.rhs)),
{free(fn_args); stack_term(&s);}); {free(fn_args); stack_term(&s);});
break; break;
case IRJmp: case IRJmp: