Skip to content

Commit

Permalink
Merge pull request #135 from jakbyte/rem-op
Browse files Browse the repository at this point in the history
feat: remainder operator
  • Loading branch information
baszalmstra authored Apr 18, 2020
2 parents 39babc4 + bc52b76 commit 5ee17f3
Show file tree
Hide file tree
Showing 11 changed files with 116 additions and 38 deletions.
24 changes: 20 additions & 4 deletions crates/mun_codegen/src/ir/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,9 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> {
.expect("no rhs value")
.into_int_value();
match op {
BinaryOp::ArithOp(op) => Some(self.gen_arith_bin_op_int(lhs, rhs, op).into()),
BinaryOp::ArithOp(op) => {
Some(self.gen_arith_bin_op_int(lhs, rhs, op, signedness).into())
}
BinaryOp::CmpOp(op) => {
let (name, predicate) = match op {
CmpOp::Eq { negated: false } => ("eq", IntPredicate::EQ),
Expand Down Expand Up @@ -717,7 +719,7 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> {
}
BinaryOp::Assignment { op } => {
let rhs = match op {
Some(op) => self.gen_arith_bin_op_int(lhs, rhs, op),
Some(op) => self.gen_arith_bin_op_int(lhs, rhs, op, signedness),
None => rhs,
};
let place = self.gen_place_expr(lhs_expr);
Expand All @@ -728,12 +730,25 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> {
}
}

fn gen_arith_bin_op_int(&mut self, lhs: IntValue, rhs: IntValue, op: ArithOp) -> IntValue {
fn gen_arith_bin_op_int(
&mut self,
lhs: IntValue,
rhs: IntValue,
op: ArithOp,
signedness: hir::Signedness,
) -> IntValue {
match op {
ArithOp::Add => self.builder.build_int_add(lhs, rhs, "add"),
ArithOp::Subtract => self.builder.build_int_sub(lhs, rhs, "sub"),
ArithOp::Divide => self.builder.build_int_signed_div(lhs, rhs, "div"),
ArithOp::Divide => match signedness {
hir::Signedness::Signed => self.builder.build_int_signed_div(lhs, rhs, "div"),
hir::Signedness::Unsigned => self.builder.build_int_unsigned_div(lhs, rhs, "div"),
},
ArithOp::Multiply => self.builder.build_int_mul(lhs, rhs, "mul"),
ArithOp::Remainder => match signedness {
hir::Signedness::Signed => self.builder.build_int_signed_rem(lhs, rhs, "rem"),
hir::Signedness::Unsigned => self.builder.build_int_unsigned_rem(lhs, rhs, "rem"),
},
}
}

Expand All @@ -748,6 +763,7 @@ impl<'a, 'b, D: IrDatabase> BodyIrGenerator<'a, 'b, D> {
ArithOp::Subtract => self.builder.build_float_sub(lhs, rhs, "sub"),
ArithOp::Divide => self.builder.build_float_div(lhs, rhs, "div"),
ArithOp::Multiply => self.builder.build_float_mul(lhs, rhs, "mul"),
ArithOp::Remainder => self.builder.build_float_rem(lhs, rhs, "rem"),
}
}

Expand Down
14 changes: 13 additions & 1 deletion crates/mun_codegen/src/snapshots/test__binary_expressions.snap
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
source: crates/mun_codegen/src/test.rs
expression: "pub fn add(a:int, b:int) -> int {\n a+b\n}\n\npub fn subtract(a:int, b:int) -> int {\n a-b\n}\n\npub fn multiply(a:int, b:int) -> int {\n a*b\n}"
expression: "pub fn add(a:int, b:int) -> int {\n a+b\n}\n\npub fn subtract(a:int, b:int) -> int {\n a-b\n}\n\npub fn multiply(a:int, b:int) -> int {\n a*b\n}\n\npub fn divide(a:int, b:int) -> int {\n a/b\n}\n\npub fn remainder(a:int, b:int) -> int {\n a%b\n}"
---
; == FILE IR =====================================
; ModuleID = 'main.mun'
Expand Down Expand Up @@ -28,6 +28,18 @@ body:
ret i64 %mul
}

define i64 @divide(i64, i64) {
body:
%div = sdiv i64 %0, %1
ret i64 %div
}

define i64 @remainder(i64, i64) {
body:
%rem = srem i64 %0, %1
ret i64 %rem
}


; == GROUP IR ====================================
; ModuleID = 'group_name'
Expand Down
8 changes: 7 additions & 1 deletion crates/mun_codegen/src/snapshots/test__update_operators.snap
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
source: crates/mun_codegen/src/test.rs
expression: "pub fn add(a:int, b:int) -> int {\n let result = a\n result += b\n result\n}\n\npub fn subtract(a:int, b:int) -> int {\n let result = a\n result -= b\n result\n}\n\npub fn multiply(a:int, b:int) -> int {\n let result = a\n result *= b\n result\n}\n\npub fn divide(a:int, b:int) -> int {\n let result = a\n result /= b\n result\n}"
expression: "pub fn add(a:int, b:int) -> int {\n let result = a\n result += b\n result\n}\n\npub fn subtract(a:int, b:int) -> int {\n let result = a\n result -= b\n result\n}\n\npub fn multiply(a:int, b:int) -> int {\n let result = a\n result *= b\n result\n}\n\npub fn divide(a:int, b:int) -> int {\n let result = a\n result /= b\n result\n}\n\npub fn remainder(a:int, b:int) -> int {\n let result = a\n result %= b\n result\n}"
---
; == FILE IR =====================================
; ModuleID = 'main.mun'
Expand Down Expand Up @@ -34,6 +34,12 @@ body:
ret i64 %div
}

define i64 @remainder(i64, i64) {
body:
%rem = srem i64 %0, %1
ret i64 %rem
}


; == GROUP IR ====================================
; ModuleID = 'group_name'
Expand Down
14 changes: 14 additions & 0 deletions crates/mun_codegen/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,14 @@ fn binary_expressions() {
pub fn multiply(a:int, b:int) -> int {
a*b
}
pub fn divide(a:int, b:int) -> int {
a/b
}
pub fn remainder(a:int, b:int) -> int {
a%b
}
"#,
);
}
Expand Down Expand Up @@ -143,6 +151,12 @@ fn update_operators() {
result /= b
result
}
pub fn remainder(a:int, b:int) -> int {
let result = a
result %= b
result
}
"#,
);
}
Expand Down
10 changes: 6 additions & 4 deletions crates/mun_hir/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ pub enum ArithOp {
Multiply,
Subtract,
Divide,
//Remainder,
Remainder,
//Power,
}

Expand Down Expand Up @@ -549,7 +549,7 @@ where
| op @ BinOp::LessEqual
| op @ BinOp::Greater
| op @ BinOp::GreatEqual
//| op @ BinOp::Remainder
| op @ BinOp::Remainder
//| op @ BinOp::Power
=> {
let op = match op {
Expand All @@ -563,7 +563,7 @@ where
BinOp::LessEqual => BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: false } ),
BinOp::Greater => BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: true } ),
BinOp::GreatEqual => BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: false } ),
//BinOp::Remainder => BinaryOp::ArithOp(ArithOp::Remainder),
BinOp::Remainder => BinaryOp::ArithOp(ArithOp::Remainder),
//BinOp::Power => BinaryOp::ArithOp(ArithOp::Power),
_ => unreachable!(),
};
Expand All @@ -582,14 +582,16 @@ where
| op @ BinOp::AddAssign
| op @ BinOp::SubtractAssign
| op @ BinOp::MultiplyAssign
| op @ BinOp::DivideAssign => {
| op @ BinOp::DivideAssign
| op @ BinOp::RemainderAssign => {

let assign_op = match op {
BinOp::Assign => None,
BinOp::AddAssign => Some(ArithOp::Add),
BinOp::SubtractAssign => Some(ArithOp::Subtract),
BinOp::MultiplyAssign => Some(ArithOp::Multiply),
BinOp::DivideAssign => Some(ArithOp::Divide),
BinOp::RemainderAssign => Some(ArithOp::Remainder),
_ => unreachable!("invalid assignment operator")
} ;

Expand Down
50 changes: 28 additions & 22 deletions crates/mun_hir/src/ty/snapshots/tests__update_operators.snap
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
---
source: crates/mun_hir/src/ty/tests.rs
expression: "fn foo(a:int, b:float) {\n a += 3;\n a -= 3;\n a *= 3;\n a /= 3;\n b += 3.0;\n b -= 3.0;\n b *= 3.0;\n b /= 3.0;\n a *= 3.0; // mismatched type\n b *= 3; // mismatched type\n}"
expression: "fn foo(a:int, b:float) {\n a += 3;\n a -= 3;\n a *= 3;\n a /= 3;\n a %= 3;\n b += 3.0;\n b -= 3.0;\n b *= 3.0;\n b /= 3.0;\n b %= 3.0;\n a *= 3.0; // mismatched type\n b *= 3; // mismatched type\n}"
---
[138; 141): mismatched type
[171; 172): mismatched type
[164; 167): mismatched type
[197; 198): mismatched type
[7; 8) 'a': int
[14; 15) 'b': float
[23; 194) '{ ...type }': nothing
[23; 220) '{ ...type }': nothing
[29; 30) 'a': int
[29; 35) 'a += 3': nothing
[34; 35) '3': int
Expand All @@ -19,21 +19,27 @@ expression: "fn foo(a:int, b:float) {\n a += 3;\n a -= 3;\n a *= 3;\n
[65; 66) 'a': int
[65; 71) 'a /= 3': nothing
[70; 71) '3': int
[77; 78) 'b': float
[77; 85) 'b += 3.0': nothing
[82; 85) '3.0': float
[91; 92) 'b': float
[91; 99) 'b -= 3.0': nothing
[96; 99) '3.0': float
[105; 106) 'b': float
[105; 113) 'b *= 3.0': nothing
[110; 113) '3.0': float
[119; 120) 'b': float
[119; 127) 'b /= 3.0': nothing
[124; 127) '3.0': float
[133; 134) 'a': int
[133; 141) 'a *= 3.0': nothing
[138; 141) '3.0': float
[166; 167) 'b': float
[166; 172) 'b *= 3': nothing
[171; 172) '3': int
[77; 78) 'a': int
[77; 83) 'a %= 3': nothing
[82; 83) '3': int
[89; 90) 'b': float
[89; 97) 'b += 3.0': nothing
[94; 97) '3.0': float
[103; 104) 'b': float
[103; 111) 'b -= 3.0': nothing
[108; 111) '3.0': float
[117; 118) 'b': float
[117; 125) 'b *= 3.0': nothing
[122; 125) '3.0': float
[131; 132) 'b': float
[131; 139) 'b /= 3.0': nothing
[136; 139) '3.0': float
[145; 146) 'b': float
[145; 153) 'b %= 3.0': nothing
[150; 153) '3.0': float
[159; 160) 'a': int
[159; 167) 'a *= 3.0': nothing
[164; 167) '3.0': float
[192; 193) 'b': float
[192; 198) 'b *= 3': nothing
[197; 198) '3': int
2 changes: 2 additions & 0 deletions crates/mun_hir/src/ty/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,12 @@ fn update_operators() {
a -= 3;
a *= 3;
a /= 3;
a %= 3;
b += 3.0;
b -= 3.0;
b *= 3.0;
b /= 3.0;
b %= 3.0;
a *= 3.0; // mismatched type
b *= 3; // mismatched type
}
Expand Down
18 changes: 18 additions & 0 deletions crates/mun_runtime/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -790,3 +790,21 @@ fn can_add_external_without_return() {
.insert_fn("foo", foo as extern "C" fn(i64) -> ());
let _: () = invoke_fn!(driver.runtime_mut(), "main").unwrap();
}

#[test]
fn signed_and_unsigned_rem() {
let mut driver = TestDriver::new(
r#"
pub fn signed() -> int {
(0 - 2) % 5
}
pub fn unsigned() -> int {
2 % 5
}
"#,
);

assert_invoke_eq!(i64, -2, driver, "signed");
assert_invoke_eq!(i64, 2, driver, "unsigned");
}
8 changes: 4 additions & 4 deletions crates/mun_syntax/src/ast/expr_extensions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ pub enum BinOp {
Subtract,
Divide,
Multiply,
// Remainder,
Remainder,
// Power,
Assign,
AddAssign,
SubtractAssign,
DivideAssign,
MultiplyAssign,
// RemainderAssign,
RemainderAssign,
// PowerAssign,
Equals,
NotEquals,
Expand All @@ -62,14 +62,14 @@ impl BinExpr {
MINUS => Some((c, BinOp::Subtract)),
SLASH => Some((c, BinOp::Divide)),
STAR => Some((c, BinOp::Multiply)),
// PERCENT => Some((c, BinOp::Remainder)),
PERCENT => Some((c, BinOp::Remainder)),
// CARET => Some((c, BinOp::Power)),
T![=] => Some((c, BinOp::Assign)),
PLUSEQ => Some((c, BinOp::AddAssign)),
MINUSEQ => Some((c, BinOp::SubtractAssign)),
SLASHEQ => Some((c, BinOp::DivideAssign)),
STAREQ => Some((c, BinOp::MultiplyAssign)),
// PERCENTEQ => Some((c, BinOp::RemainderAssign)),
PERCENTEQ => Some((c, BinOp::RemainderAssign)),
// CARETEQ => Some((c, BinOp::PowerAssign)),
EQEQ => Some((c, BinOp::Equals)),
NEQ => Some((c, BinOp::NotEquals)),
Expand Down
2 changes: 2 additions & 0 deletions crates/mun_syntax/src/parsing/grammar/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ fn current_op(p: &Parser) -> (u8, SyntaxKind) {
T![*] => (11, T![*]),
T![/] if p.at(T![/=]) => (1, T![/=]),
T![/] => (11, T![/]),
T![%] if p.at(T![%=]) => (1, T![%=]),
T![%] => (11, T![%]),
T![=] if p.at(T![==]) => (5, T![==]),
T![=] => (1, T![=]),
T![!] if p.at(T![!=]) => (5, T![!=]),
Expand Down
4 changes: 2 additions & 2 deletions crates/mun_syntax/src/parsing/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ impl<'t> Parser<'t> {
T![/=] => self.at_composite2(n, T![/], T![=]),
//T![&&] => self.at_composite2(n, T![&], T![&]),
//T![&=] => self.at_composite2(n, T![&], T![=]),
//T![%=] => self.at_composite2(n, T![%], T![=]),
T![%=] => self.at_composite2(n, T![%], T![=]),
//T![^=] => self.at_composite2(n, T![^], T![=]),
T![+=] => self.at_composite2(n, T![+], T![=]),
//T![<<] => self.at_composite2(n, T![<], T![<]),
Expand Down Expand Up @@ -193,7 +193,7 @@ impl<'t> Parser<'t> {
| T![/=]
//| T![&&]
//| T![&=]
//| T![%=]
| T![%=]
//| T![^=]
| T![+=]
//| T![<<]
Expand Down

0 comments on commit 5ee17f3

Please sign in to comment.