Skip to content

Commit

Permalink
Implement Tilde operator (#187)
Browse files Browse the repository at this point in the history
* implement tilde operator

* add tests for tilde operator
  • Loading branch information
letmutx authored and jasonwilliams committed Oct 25, 2019
1 parent dfb3e78 commit 6e04f8f
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 0 deletions.
47 changes: 47 additions & 0 deletions src/lib/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,15 @@ impl Executor for Interpreter {
UnaryOp::Minus => to_value(-v_a.to_num()),
UnaryOp::Plus => to_value(v_a.to_num()),
UnaryOp::Not => Gc::new(!v_a),
UnaryOp::Tilde => {
let num_v_a = v_a.to_num();
// NOTE: possible UB: https://github.com/rust-lang/rust/issues/10184
to_value(if num_v_a.is_nan() {
-1
} else {
!(num_v_a as i32)
})
}
_ => unreachable!(),
})
}
Expand Down Expand Up @@ -751,4 +760,42 @@ mod tests {
"#;
assert_eq!(exec(non_num_key_wont_affect_length), String::from("3"));
}

#[test]
fn test_tilde_operator() {
let float = r#"
let f = -1.2;
~f
"#;
assert_eq!(exec(float), String::from("0"));

let numeric = r#"
let f = 1789;
~f
"#;
assert_eq!(exec(numeric), String::from("-1790"));

// TODO: enable test after we have NaN
// let nan = r#"
// var m = NaN;
// ~m
// "#;
// assert_eq!(exec(nan), String::from("-1"));

let object = r#"
let m = {};
~m
"#;
assert_eq!(exec(object), String::from("-1"));

let boolean_true = r#"
~true
"#;
assert_eq!(exec(boolean_true), String::from("-2"));

let boolean_false = r#"
~false
"#;
assert_eq!(exec(boolean_false), String::from("-1"));
}
}
1 change: 1 addition & 0 deletions src/lib/syntax/ast/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ impl Operator for ExprDef {
| ExprDef::UnaryOp(UnaryOp::DecrementPost, _)
| ExprDef::UnaryOp(UnaryOp::DecrementPre, _) => 3,
ExprDef::UnaryOp(UnaryOp::Not, _)
| ExprDef::UnaryOp(UnaryOp::Tilde, _)
| ExprDef::UnaryOp(UnaryOp::Minus, _)
| ExprDef::TypeOf(_) => 4,
ExprDef::BinOp(op, _, _) => op.get_precedence(),
Expand Down
3 changes: 3 additions & 0 deletions src/lib/syntax/ast/op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ pub enum UnaryOp {
Plus,
/// `!a` - get the opposite of the boolean value
Not,
/// `~a` - bitwise-not of the value
Tilde,
}

impl Display for UnaryOp {
Expand All @@ -77,6 +79,7 @@ impl Display for UnaryOp {
UnaryOp::Plus => "+",
UnaryOp::Minus => "-",
UnaryOp::Not => "!",
UnaryOp::Tilde => "~",
}
)
}
Expand Down
4 changes: 4 additions & 0 deletions src/lib/syntax/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,10 @@ impl Parser {
self,
ExprDef::UnaryOp(UnaryOp::Not, Box::new(self.parse()?))
),
TokenData::Punctuator(Punctuator::Neg) => mk!(
self,
ExprDef::UnaryOp(UnaryOp::Tilde, Box::new(self.parse()?))
),
TokenData::Punctuator(Punctuator::Inc) => mk!(
self,
ExprDef::UnaryOp(UnaryOp::IncrementPre, Box::new(self.parse()?))
Expand Down

0 comments on commit 6e04f8f

Please sign in to comment.