diff --git a/examples/lop.b b/examples/lop.b new file mode 100644 index 00000000..a33a8e93 --- /dev/null +++ b/examples/lop.b @@ -0,0 +1,11 @@ +main () { + extrn printf; + printf("LOP1: (%d)\n", 1 || 0); + printf("LOP2: (%d)\n", 1 || 1); + printf("LOP3: (%d)\n", 0 || 1); + printf("LOP4: (%d)\n", 0 || 0); + printf("LOP5: (%d)\n", 0 && 1); + printf("LOP6: (%d)\n", 1 && 0); + printf("LOP7: (%d)\n", 1 && 1); + printf("LOP8: (%d)\n", 0 && 0); +} \ No newline at end of file diff --git a/src/b.rs b/src/b.rs index 0193e3da..1f1a9549 100644 --- a/src/b.rs +++ b/src/b.rs @@ -237,6 +237,8 @@ pub unsafe fn define_goto_label(c: *mut Compiler, name: *const c_char, loc: Loc, // The higher the index of the row in this table the higher the precedence of the Binop pub const PRECEDENCE: *const [*const [Binop]] = &[ + &[Binop::LogOr], + &[Binop::LogAnd], &[Binop::BitOr], &[Binop::BitAnd], &[Binop::BitShl, Binop::BitShr], @@ -283,6 +285,8 @@ impl Binop { Token::And => Some(Binop::BitAnd), Token::Shl => Some(Binop::BitShl), Token::Shr => Some(Binop::BitShr), + Token::Lor => Some(Binop::LogOr), + Token::Land => Some(Binop::LogAnd), _ => None, } } @@ -528,15 +532,61 @@ pub unsafe fn compile_binop_expression(l: *mut Lexer, c: *mut Compiler, preceden if binop.precedence() != precedence { break; } let (rhs, _) = compile_binop_expression(l, c, precedence + 1)?; - - let index = allocate_auto_var(&mut (*c).auto_vars_ator); - push_opcode(Op::Binop {binop, index, lhs, rhs}, (*l).loc, c); - lhs = Arg::AutoVar(index); - - lvalue = false; - - saved_point = (*l).parse_point; - lexer::get_token(l)?; + match binop { + Binop::LogOr => { + let result = allocate_auto_var(&mut (*c).auto_vars_ator); + + let t_label = allocate_label_index(c); + let e_label = allocate_label_index(c); + + push_opcode(Op::Binop { binop: Binop::Equal, index: result, lhs, rhs: Arg::Literal(0) }, (*l).loc, c); + push_opcode(Op::JmpIfNotLabel {label: t_label, arg: Arg::AutoVar(result) }, (*l).loc, c); + push_opcode(Op::Binop { binop: Binop::Equal, index: result, lhs: rhs, rhs: Arg::Literal(0) }, (*l).loc, c); + push_opcode(Op::JmpIfNotLabel {label: t_label, arg: Arg::AutoVar(result) }, (*l).loc, c); + push_opcode(Op::AutoAssign {index: result, arg: Arg::Literal(0)}, (*l).loc, c); + push_opcode(Op::JmpLabel {label: e_label}, (*l).loc, c); + + push_opcode(Op::Label {label: t_label}, (*l).loc, c); + push_opcode(Op::AutoAssign {index: result, arg: Arg::Literal(1)}, (*l).loc, c); + push_opcode(Op::Label {label: e_label}, (*l).loc, c); + + lhs = Arg::AutoVar(result); + lvalue = false; + saved_point = (*l).parse_point; + lexer::get_token(l)?; + } + Binop::LogAnd => { + let result = allocate_auto_var(&mut (*c).auto_vars_ator); + + let t_label = allocate_label_index(c); + let e_label = allocate_label_index(c); + + push_opcode(Op::Binop { binop: Binop::Equal, index: result, lhs, rhs: Arg::Literal(1) }, (*l).loc, c); + push_opcode(Op::JmpIfNotLabel {label: t_label, arg: Arg::AutoVar(result) }, (*l).loc, c); + push_opcode(Op::Binop { binop: Binop::Equal, index: result, lhs: rhs, rhs: Arg::Literal(1) }, (*l).loc, c); + push_opcode(Op::JmpIfNotLabel {label: t_label, arg: Arg::AutoVar(result) }, (*l).loc, c); + push_opcode(Op::AutoAssign {index: result, arg: Arg::Literal(1)}, (*l).loc, c); + push_opcode(Op::JmpLabel {label: e_label}, (*l).loc, c); + + push_opcode(Op::Label {label: t_label}, (*l).loc, c); + push_opcode(Op::AutoAssign {index: result, arg: Arg::Literal(0)}, (*l).loc, c); + push_opcode(Op::Label {label: e_label}, (*l).loc, c); + + lhs = Arg::AutoVar(result); + lvalue = false; + saved_point = (*l).parse_point; + lexer::get_token(l)?; + } + _ => { + let index = allocate_auto_var(&mut (*c).auto_vars_ator); + push_opcode(Op::Binop {binop, index, lhs, rhs}, (*l).loc, c); + lhs = Arg::AutoVar(index); + + lvalue = false; + saved_point = (*l).parse_point; + lexer::get_token(l)?; + } + } } } } @@ -561,7 +611,7 @@ pub unsafe fn compile_assign_expression(l: *mut Lexer, c: *mut Compiler) -> Opti } if let Some(binop) = binop { - compile_binop(lhs, rhs, binop, binop_loc, c); + compile_binop(lhs, rhs, binop, binop_loc, c); } else { match lhs { Arg::Deref(index) => { diff --git a/src/codegen/gas_aarch64/mod.rs b/src/codegen/gas_aarch64/mod.rs index 99b8020b..bc2371f4 100644 --- a/src/codegen/gas_aarch64/mod.rs +++ b/src/codegen/gas_aarch64/mod.rs @@ -188,8 +188,10 @@ pub unsafe fn generate_function(name: *const c_char, _name_loc: Loc, params_coun }, Op::Binop {binop, index, lhs, rhs} => { match binop { + Binop::LogAnd => todo!(), + Binop::LogOr => todo!(), Binop::BitOr => { - load_arg_to_reg(lhs, c!("x0"), output, op.loc, os); + load_arg_to_reg(lhs, c!("x0"), output, op.loc, os); load_arg_to_reg(rhs, c!("x1"), output, op.loc, os); sb_appendf(output, c!(" orr x0, x0, x1\n")); sb_appendf(output, c!(" str x0, [x29, -%zu]\n"), index*8); diff --git a/src/codegen/gas_x86_64/mod.rs b/src/codegen/gas_x86_64/mod.rs index 4d918594..b978e79f 100644 --- a/src/codegen/gas_x86_64/mod.rs +++ b/src/codegen/gas_x86_64/mod.rs @@ -179,9 +179,12 @@ pub unsafe fn generate_function(name: *const c_char, name_loc: Loc, func_index: } Op::Binop {binop, index, lhs, rhs} => { load_arg_to_reg(lhs, c!("rax"), output, os); - load_arg_to_reg(rhs, c!("rcx"), output, os); + load_arg_to_reg(rhs, c!("rcx"), output, os); + match binop { - Binop::BitOr => { sb_appendf(output, c!(" orq %%rcx, %%rax\n")); } + Binop::BitOr => { + sb_appendf(output, c!(" orq %%rcx, %%rax\n")); + } Binop::BitAnd => { sb_appendf(output, c!(" andq %%rcx, %%rax\n")); } Binop::BitShl => { load_arg_to_reg(rhs, c!("rcx"), output, os); @@ -216,7 +219,7 @@ pub unsafe fn generate_function(name: *const c_char, name_loc: Loc, func_index: Binop::NotEqual => sb_appendf(output, c!(" setne %%dl\n")), Binop::GreaterEqual => sb_appendf(output, c!(" setge %%dl\n")), Binop::LessEqual => sb_appendf(output, c!(" setle %%dl\n")), - _ => unreachable!(), + _ => unreachable!(), }; sb_appendf(output, c!(" movq %%rdx, -%zu(%%rbp)\n"), index * 8); continue; diff --git a/src/codegen/mos6502.rs b/src/codegen/mos6502.rs index 57114c8b..d53a50b8 100644 --- a/src/codegen/mos6502.rs +++ b/src/codegen/mos6502.rs @@ -1270,6 +1270,7 @@ pub unsafe fn generate_function(name: *const c_char, loc: Loc, params_count: usi // zero extend result instr8(out, LDY, IMM, 0); }, + _ => unreachable!(), } store_auto(out, index, asm); }, diff --git a/src/codegen/uxn/mod.rs b/src/codegen/uxn/mod.rs index 48995ad9..e24ff394 100644 --- a/src/codegen/uxn/mod.rs +++ b/src/codegen/uxn/mod.rs @@ -335,7 +335,7 @@ pub unsafe fn generate_function(name: *const c_char, name_loc: Loc, params_count for i in 0..body.len() { let op = (*body)[i]; match op.opcode { - Op::Bogus => unreachable!("bogus-amogus"), + Op::Bogus => unreachable!("bogus-amogus"), Op::UnaryNot {result, arg} => { load_arg(arg, op.loc, output, assembler); // if arg == 0 then 1 else 0 @@ -572,7 +572,7 @@ pub unsafe fn generate_function(name: *const c_char, name_loc: Loc, params_count write_op(output, UxnOp::SFT2); store_auto(output, index); } - Op::AutoAssign {index, arg} => { + Op::AutoAssign {index, arg} => { load_arg(arg, op.loc, output, assembler); store_auto(output, index); } @@ -653,6 +653,7 @@ pub unsafe fn generate_function(name: *const c_char, name_loc: Loc, params_count write_op(output, UxnOp::ADD2); store_auto(output, result); }, + _ => unreachable!() } } diff --git a/src/ir.rs b/src/ir.rs index 75a4f13b..08d7fa6e 100644 --- a/src/ir.rs +++ b/src/ir.rs @@ -50,6 +50,8 @@ pub enum Binop { BitAnd, BitShl, BitShr, + LogOr, + LogAnd, } #[derive(Clone, Copy)] @@ -200,6 +202,8 @@ pub unsafe fn dump_op(op: OpWithLocation, output: *mut String_Builder) { sb_appendf(output, c!(" auto[%zu] = "), index); dump_arg(output, lhs); match binop { + Binop::LogAnd => sb_appendf(output, c!(" && ")), + Binop::LogOr => sb_appendf(output, c!(" || ")), Binop::BitOr => sb_appendf(output, c!(" | ")), Binop::BitAnd => sb_appendf(output, c!(" & ")), Binop::BitShl => sb_appendf(output, c!(" << ")), diff --git a/src/lexer.rs b/src/lexer.rs index 926d6472..d3480060 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -80,7 +80,9 @@ pub enum Token { Colon, SemiColon, Comma, - + Lor, // || + Land, // && + // Keywords Auto, Extrn, @@ -146,6 +148,8 @@ pub unsafe fn display_token(token: Token) -> *const c_char { Token::Colon => c!("`:`"), Token::SemiColon => c!("`;`"), Token::Comma => c!("`,`"), + Token::Lor => c!("`||`"), + Token::Land => c!("`&&`"), Token::Auto => c!("keyword `auto`"), Token::Extrn => c!("keyword `extrn`"), @@ -193,8 +197,10 @@ pub const PUNCTS: *const [(*const c_char, Token)] = &[ (c!("/="), Token::DivEq), (c!("/"), Token::Div), (c!("|="), Token::OrEq), + (c!("||"), Token::Lor), (c!("|"), Token::Or), (c!("&="), Token::AndEq), + (c!("&&"), Token::Land), (c!("&"), Token::And), (c!("=="), Token::EqEq), (c!("="), Token::Eq),