Browse Source

Implement Tilde operator (#187)

* implement tilde operator

* add tests for tilde operator
pull/185/head
letmutx 5 years ago committed by Jason Williams
parent
commit
6e04f8f393
  1. 47
      src/lib/exec.rs
  2. 1
      src/lib/syntax/ast/expr.rs
  3. 3
      src/lib/syntax/ast/op.rs
  4. 4
      src/lib/syntax/parser.rs

47
src/lib/exec.rs

@ -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!(),
})
}
@ -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
src/lib/syntax/ast/expr.rs

@ -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(),

3
src/lib/syntax/ast/op.rs

@ -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 {
@ -77,6 +79,7 @@ impl Display for UnaryOp {
UnaryOp::Plus => "+",
UnaryOp::Minus => "-",
UnaryOp::Not => "!",
UnaryOp::Tilde => "~",
}
)
}

4
src/lib/syntax/parser.rs

@ -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()?))

Loading…
Cancel
Save