boolean operators
This commit is contained in:
parent
652106135c
commit
4ef3fdb46d
4 changed files with 31 additions and 6 deletions
21
src/eval.rs
21
src/eval.rs
|
@ -152,6 +152,8 @@ pub fn eval_expr(expr: &Expr, env: EnvRef) -> Result<Value, RuntimeError> {
|
||||||
=> eval_assignment(lhs, rhs, op, env),
|
=> eval_assignment(lhs, rhs, op, env),
|
||||||
Some(OpType::Additive) | Some(OpType::Multiplicative)
|
Some(OpType::Additive) | Some(OpType::Multiplicative)
|
||||||
=> eval_binary(lhs, rhs, op, env),
|
=> eval_binary(lhs, rhs, op, env),
|
||||||
|
Some(OpType::Boolean)
|
||||||
|
=> eval_boolean(lhs, rhs, op, env),
|
||||||
Some(OpType::Comparison)
|
Some(OpType::Comparison)
|
||||||
=> eval_comp(lhs, rhs, op, env),
|
=> eval_comp(lhs, rhs, op, env),
|
||||||
o => todo!("{:?}", o) // TODO other operations
|
o => todo!("{:?}", o) // TODO other operations
|
||||||
|
@ -178,7 +180,6 @@ pub fn eval_expr(expr: &Expr, env: EnvRef) -> Result<Value, RuntimeError> {
|
||||||
let idx = eval_expr(index, env)?;
|
let idx = eval_expr(index, env)?;
|
||||||
l.index(&idx).map_err(|e| RuntimeError { message: e, pos: pos.clone() })
|
l.index(&idx).map_err(|e| RuntimeError { message: e, pos: pos.clone() })
|
||||||
},
|
},
|
||||||
e => todo!("{:?}", e) // TODO other expression types
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,6 +276,23 @@ pub fn eval_binary(lhs: &Box<Expr>, rhs: &Box<Expr>, op: &Token, env: EnvRef) ->
|
||||||
}.map_err(|e| RuntimeError { message: e, pos: op.pos.clone() })
|
}.map_err(|e| RuntimeError { message: e, pos: op.pos.clone() })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn eval_boolean(lhs: &Box<Expr>, rhs: &Box<Expr>, op: &Token, env: EnvRef) -> Result<Value, RuntimeError> {
|
||||||
|
let l = eval_expr(lhs, env.clone())?;
|
||||||
|
match op.ty {
|
||||||
|
TokenType::DoubleAmper => if l.truthy() {
|
||||||
|
eval_expr(rhs, env)
|
||||||
|
} else {
|
||||||
|
Ok(l)
|
||||||
|
},
|
||||||
|
TokenType::DoublePipe => if !l.truthy() {
|
||||||
|
eval_expr(rhs, env)
|
||||||
|
} else {
|
||||||
|
Ok(l)
|
||||||
|
},
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn eval_comp(lhs: &Box<Expr>, rhs: &Box<Expr>, op: &Token, env: EnvRef) -> Result<Value, RuntimeError> {
|
pub fn eval_comp(lhs: &Box<Expr>, rhs: &Box<Expr>, op: &Token, env: EnvRef) -> Result<Value, RuntimeError> {
|
||||||
let l = eval_expr(lhs, env.clone())?;
|
let l = eval_expr(lhs, env.clone())?;
|
||||||
let r = eval_expr(rhs, env)?;
|
let r = eval_expr(rhs, env)?;
|
||||||
|
@ -308,6 +326,7 @@ pub fn eval_unary(arg: &Box<Expr>, op: &Token, env: EnvRef) -> Result<Value, Run
|
||||||
let a = eval_expr(arg, env)?;
|
let a = eval_expr(arg, env)?;
|
||||||
match op.ty {
|
match op.ty {
|
||||||
TokenType::Minus => -a,
|
TokenType::Minus => -a,
|
||||||
|
TokenType::Bang => Ok(Value::Bool(!a.truthy())),
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}.map_err(|e| RuntimeError { message: e, pos: op.pos.clone() })
|
}.map_err(|e| RuntimeError { message: e, pos: op.pos.clone() })
|
||||||
}
|
}
|
|
@ -261,7 +261,11 @@ impl Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pipeline(&mut self) -> Result<Expr, ParserError> {
|
fn pipeline(&mut self) -> Result<Expr, ParserError> {
|
||||||
self.expr(OpType::Pipeline, Self::comparison)
|
self.expr(OpType::Pipeline, Self::boolean)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn boolean(&mut self) -> Result<Expr, ParserError> {
|
||||||
|
self.expr(OpType::Boolean, Self::comparison)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn comparison(&mut self) -> Result<Expr, ParserError> {
|
fn comparison(&mut self) -> Result<Expr, ParserError> {
|
||||||
|
|
|
@ -58,6 +58,8 @@ impl TokenType {
|
||||||
| Self::StarEqual | Self::SlashEqual | Self::DoubleSlashEqual
|
| Self::StarEqual | Self::SlashEqual | Self::DoubleSlashEqual
|
||||||
| Self::CaretEqual | Self::PercentEqual => Some(OpType::Assignment),
|
| Self::CaretEqual | Self::PercentEqual => Some(OpType::Assignment),
|
||||||
|
|
||||||
|
Self::DoubleAmper | Self::DoublePipe => Some(OpType::Boolean),
|
||||||
|
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,7 +67,7 @@ impl TokenType {
|
||||||
|
|
||||||
#[derive(Clone,Copy,Debug,PartialEq)]
|
#[derive(Clone,Copy,Debug,PartialEq)]
|
||||||
pub enum OpType {
|
pub enum OpType {
|
||||||
Assignment, Comparison, Pipeline, Additive, Multiplicative, Exponential
|
Assignment, Comparison, Pipeline, Additive, Multiplicative, Exponential, Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OpType {
|
impl OpType {
|
||||||
|
|
|
@ -151,7 +151,7 @@ impl Value {
|
||||||
|
|
||||||
pub fn assign_index(&self, idx: &Value, value: Value) -> Result<(), String> {
|
pub fn assign_index(&self, idx: &Value, value: Value) -> Result<(), String> {
|
||||||
match self {
|
match self {
|
||||||
Self::String(s) => todo!("Can't mutate strings yet"),
|
Self::String(_) => todo!("Can't mutate strings yet"),
|
||||||
Self::List(l) => match idx {
|
Self::List(l) => match idx {
|
||||||
Value::Int(i) if *i >= 0 && (*i as usize) < l.borrow().len() => {
|
Value::Int(i) if *i >= 0 && (*i as usize) < l.borrow().len() => {
|
||||||
l.borrow_mut()[*i as usize] = value;
|
l.borrow_mut()[*i as usize] = value;
|
||||||
|
@ -314,7 +314,7 @@ impl_numeric_op!(Add, add, {
|
||||||
Ok(s.into())
|
Ok(s.into())
|
||||||
}
|
}
|
||||||
(List(a), List(b)) => {
|
(List(a), List(b)) => {
|
||||||
let mut a = (**a).clone();
|
let a = (**a).clone();
|
||||||
a.borrow_mut().append(&mut (**b).borrow().clone());
|
a.borrow_mut().append(&mut (**b).borrow().clone());
|
||||||
Ok(a.into())
|
Ok(a.into())
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue