mirror of
https://github.com/nushell/nushell
synced 2024-11-10 07:04:13 +00:00
Add a few operators. Needs parser work
This commit is contained in:
parent
739425431a
commit
35c3622405
6 changed files with 546 additions and 21 deletions
|
@ -5,6 +5,9 @@ edition = "2018"
|
|||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[workspace]
|
||||
members = ["crates/nu-cli", "crates/nu-engine", "crates/nu-parser"]
|
||||
|
||||
[dependencies]
|
||||
reedline = { git = "https://github.com/jntrnr/reedline", branch = "main" }
|
||||
codespan-reporting = "0.11.1"
|
||||
|
|
|
@ -273,6 +273,15 @@ pub fn report_shell_error(
|
|||
.with_labels(vec![Label::primary(diag_file_id, diag_range)
|
||||
.with_message(format!("can't convert to {}", s))])
|
||||
}
|
||||
ShellError::DivisionByZero(span) => {
|
||||
let (diag_file_id, diag_range) = convert_span_to_diag(working_set, span)?;
|
||||
|
||||
Diagnostic::error()
|
||||
.with_message("Division by zero")
|
||||
.with_labels(vec![
|
||||
Label::primary(diag_file_id, diag_range).with_message("division by zero")
|
||||
])
|
||||
}
|
||||
};
|
||||
|
||||
// println!("DIAG");
|
||||
|
|
|
@ -16,6 +16,7 @@ pub enum ShellError {
|
|||
InternalError(String),
|
||||
VariableNotFound(Span),
|
||||
CantConvert(String, Span),
|
||||
DivisionByZero(Span),
|
||||
}
|
||||
|
||||
pub fn eval_operator(op: &Expression) -> Result<Operator, ShellError> {
|
||||
|
@ -227,7 +228,16 @@ pub fn eval_expression(state: &State, expr: &Expression) -> Result<Value, ShellE
|
|||
|
||||
match op {
|
||||
Operator::Plus => lhs.add(op_span, &rhs),
|
||||
_ => Ok(Value::Nothing { span: expr.span }),
|
||||
Operator::Minus => lhs.sub(op_span, &rhs),
|
||||
Operator::Multiply => lhs.mul(op_span, &rhs),
|
||||
Operator::Divide => lhs.div(op_span, &rhs),
|
||||
Operator::LessThan => lhs.lt(op_span, &rhs),
|
||||
Operator::LessThanOrEqual => lhs.lte(op_span, &rhs),
|
||||
Operator::GreaterThan => lhs.gt(op_span, &rhs),
|
||||
Operator::GreaterThanOrEqual => lhs.gte(op_span, &rhs),
|
||||
Operator::Equal => lhs.eq(op_span, &rhs),
|
||||
Operator::NotEqual => lhs.ne(op_span, &rhs),
|
||||
_ => Err(ShellError::Unsupported(op_span)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -131,4 +131,306 @@ impl Value {
|
|||
}),
|
||||
}
|
||||
}
|
||||
pub fn sub(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
|
||||
let span = nu_parser::span(&[self.span(), rhs.span()]);
|
||||
|
||||
match (self, rhs) {
|
||||
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Int {
|
||||
val: lhs - rhs,
|
||||
span,
|
||||
}),
|
||||
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
|
||||
val: *lhs as f64 - *rhs,
|
||||
span,
|
||||
}),
|
||||
(Value::Float { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Float {
|
||||
val: *lhs - *rhs as f64,
|
||||
span,
|
||||
}),
|
||||
(Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
|
||||
val: lhs - rhs,
|
||||
span,
|
||||
}),
|
||||
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
op_span: op,
|
||||
lhs_ty: self.get_type(),
|
||||
lhs_span: self.span(),
|
||||
rhs_ty: rhs.get_type(),
|
||||
rhs_span: rhs.span(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
pub fn mul(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
|
||||
let span = nu_parser::span(&[self.span(), rhs.span()]);
|
||||
|
||||
match (self, rhs) {
|
||||
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Int {
|
||||
val: lhs * rhs,
|
||||
span,
|
||||
}),
|
||||
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
|
||||
val: *lhs as f64 * *rhs,
|
||||
span,
|
||||
}),
|
||||
(Value::Float { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Float {
|
||||
val: *lhs * *rhs as f64,
|
||||
span,
|
||||
}),
|
||||
(Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
|
||||
val: lhs * rhs,
|
||||
span,
|
||||
}),
|
||||
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
op_span: op,
|
||||
lhs_ty: self.get_type(),
|
||||
lhs_span: self.span(),
|
||||
rhs_ty: rhs.get_type(),
|
||||
rhs_span: rhs.span(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
pub fn div(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
|
||||
let span = nu_parser::span(&[self.span(), rhs.span()]);
|
||||
|
||||
match (self, rhs) {
|
||||
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => {
|
||||
if *rhs != 0 {
|
||||
Ok(Value::Int {
|
||||
val: lhs / rhs,
|
||||
span,
|
||||
})
|
||||
} else {
|
||||
Err(ShellError::DivisionByZero(op))
|
||||
}
|
||||
}
|
||||
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => {
|
||||
if *rhs != 0.0 {
|
||||
Ok(Value::Float {
|
||||
val: *lhs as f64 / *rhs,
|
||||
span,
|
||||
})
|
||||
} else {
|
||||
Err(ShellError::DivisionByZero(op))
|
||||
}
|
||||
}
|
||||
(Value::Float { val: lhs, .. }, Value::Int { val: rhs, .. }) => {
|
||||
if *rhs != 0 {
|
||||
Ok(Value::Float {
|
||||
val: *lhs / *rhs as f64,
|
||||
span,
|
||||
})
|
||||
} else {
|
||||
Err(ShellError::DivisionByZero(op))
|
||||
}
|
||||
}
|
||||
(Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => {
|
||||
if *rhs != 0.0 {
|
||||
Ok(Value::Float {
|
||||
val: lhs / rhs,
|
||||
span,
|
||||
})
|
||||
} else {
|
||||
Err(ShellError::DivisionByZero(op))
|
||||
}
|
||||
}
|
||||
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
op_span: op,
|
||||
lhs_ty: self.get_type(),
|
||||
lhs_span: self.span(),
|
||||
rhs_ty: rhs.get_type(),
|
||||
rhs_span: rhs.span(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
pub fn lt(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
|
||||
let span = nu_parser::span(&[self.span(), rhs.span()]);
|
||||
|
||||
match (self, rhs) {
|
||||
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: lhs < rhs,
|
||||
span,
|
||||
}),
|
||||
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: (*lhs as f64) < *rhs,
|
||||
span,
|
||||
}),
|
||||
(Value::Float { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: *lhs < *rhs as f64,
|
||||
span,
|
||||
}),
|
||||
(Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: lhs < rhs,
|
||||
span,
|
||||
}),
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
op_span: op,
|
||||
lhs_ty: self.get_type(),
|
||||
lhs_span: self.span(),
|
||||
rhs_ty: rhs.get_type(),
|
||||
rhs_span: rhs.span(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
pub fn lte(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
|
||||
let span = nu_parser::span(&[self.span(), rhs.span()]);
|
||||
|
||||
match (self, rhs) {
|
||||
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: lhs <= rhs,
|
||||
span,
|
||||
}),
|
||||
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: (*lhs as f64) <= *rhs,
|
||||
span,
|
||||
}),
|
||||
(Value::Float { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: *lhs <= *rhs as f64,
|
||||
span,
|
||||
}),
|
||||
(Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: lhs <= rhs,
|
||||
span,
|
||||
}),
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
op_span: op,
|
||||
lhs_ty: self.get_type(),
|
||||
lhs_span: self.span(),
|
||||
rhs_ty: rhs.get_type(),
|
||||
rhs_span: rhs.span(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
pub fn gt(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
|
||||
let span = nu_parser::span(&[self.span(), rhs.span()]);
|
||||
|
||||
match (self, rhs) {
|
||||
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: lhs > rhs,
|
||||
span,
|
||||
}),
|
||||
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: (*lhs as f64) > *rhs,
|
||||
span,
|
||||
}),
|
||||
(Value::Float { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: *lhs > *rhs as f64,
|
||||
span,
|
||||
}),
|
||||
(Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: lhs > rhs,
|
||||
span,
|
||||
}),
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
op_span: op,
|
||||
lhs_ty: self.get_type(),
|
||||
lhs_span: self.span(),
|
||||
rhs_ty: rhs.get_type(),
|
||||
rhs_span: rhs.span(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
pub fn gte(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
|
||||
let span = nu_parser::span(&[self.span(), rhs.span()]);
|
||||
|
||||
match (self, rhs) {
|
||||
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: lhs >= rhs,
|
||||
span,
|
||||
}),
|
||||
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: (*lhs as f64) >= *rhs,
|
||||
span,
|
||||
}),
|
||||
(Value::Float { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: *lhs >= *rhs as f64,
|
||||
span,
|
||||
}),
|
||||
(Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: lhs >= rhs,
|
||||
span,
|
||||
}),
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
op_span: op,
|
||||
lhs_ty: self.get_type(),
|
||||
lhs_span: self.span(),
|
||||
rhs_ty: rhs.get_type(),
|
||||
rhs_span: rhs.span(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
pub fn eq(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
|
||||
let span = nu_parser::span(&[self.span(), rhs.span()]);
|
||||
|
||||
match (self, rhs) {
|
||||
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: lhs == rhs,
|
||||
span,
|
||||
}),
|
||||
(Value::String { val: lhs, .. }, Value::String { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: lhs == rhs,
|
||||
span,
|
||||
}),
|
||||
// FIXME: these should consider machine epsilon
|
||||
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: (*lhs as f64) == *rhs,
|
||||
span,
|
||||
}),
|
||||
// FIXME: these should consider machine epsilon
|
||||
(Value::Float { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: *lhs == *rhs as f64,
|
||||
span,
|
||||
}),
|
||||
// FIXME: these should consider machine epsilon
|
||||
(Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: lhs == rhs,
|
||||
span,
|
||||
}),
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
op_span: op,
|
||||
lhs_ty: self.get_type(),
|
||||
lhs_span: self.span(),
|
||||
rhs_ty: rhs.get_type(),
|
||||
rhs_span: rhs.span(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
pub fn ne(&self, op: Span, rhs: &Value) -> Result<Value, ShellError> {
|
||||
let span = nu_parser::span(&[self.span(), rhs.span()]);
|
||||
|
||||
match (self, rhs) {
|
||||
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: lhs != rhs,
|
||||
span,
|
||||
}),
|
||||
(Value::String { val: lhs, .. }, Value::String { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: lhs != rhs,
|
||||
span,
|
||||
}),
|
||||
// FIXME: these should consider machine epsilon
|
||||
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: (*lhs as f64) != *rhs,
|
||||
span,
|
||||
}),
|
||||
// FIXME: these should consider machine epsilon
|
||||
(Value::Float { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: *lhs != *rhs as f64,
|
||||
span,
|
||||
}),
|
||||
// FIXME: these should consider machine epsilon
|
||||
(Value::Float { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Bool {
|
||||
val: lhs != rhs,
|
||||
span,
|
||||
}),
|
||||
_ => Err(ShellError::OperatorMismatch {
|
||||
op_span: op,
|
||||
lhs_ty: self.get_type(),
|
||||
lhs_span: self.span(),
|
||||
rhs_ty: rhs.get_type(),
|
||||
rhs_span: rhs.span(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ use crate::{
|
|||
parser_state::{Type, VarId},
|
||||
signature::{Flag, PositionalArg},
|
||||
BlockId, DeclId, Declaration, LiteBlock, ParseError, ParserWorkingSet, Signature, Span, Token,
|
||||
TokenContents,
|
||||
};
|
||||
|
||||
/// The syntactic shapes that values must match to be passed into a command. You can think of this as the type-checking that occurs when you call a function.
|
||||
|
@ -1028,7 +1029,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||
Expression {
|
||||
expr: Expr::Float(x),
|
||||
span,
|
||||
ty: Type::Int,
|
||||
ty: Type::Float,
|
||||
},
|
||||
None,
|
||||
)
|
||||
|
@ -1450,6 +1451,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||
error = error.or(err);
|
||||
|
||||
let mut args: Vec<Arg> = vec![];
|
||||
let mut rest: Option<Arg> = None;
|
||||
let mut parse_mode = ParseMode::ArgMode;
|
||||
|
||||
for token in &output {
|
||||
|
@ -1947,6 +1949,32 @@ impl<'a> ParserWorkingSet<'a> {
|
|||
let (output, err) = lex(source, start, &[], &[]);
|
||||
error = error.or(err);
|
||||
|
||||
// Check to see if we have parameters
|
||||
let params = if matches!(
|
||||
output.first(),
|
||||
Some(Token {
|
||||
contents: TokenContents::Pipe,
|
||||
..
|
||||
})
|
||||
) {
|
||||
// We've found a parameter list
|
||||
let mut param_tokens = vec![];
|
||||
let mut token_iter = output.iter().skip(1);
|
||||
for token in &mut token_iter {
|
||||
if matches!(
|
||||
token,
|
||||
Token {
|
||||
contents: TokenContents::Pipe,
|
||||
..
|
||||
}
|
||||
) {
|
||||
break;
|
||||
} else {
|
||||
param_tokens.push(token);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let (output, err) = lite_parse(&output);
|
||||
error = error.or(err);
|
||||
|
||||
|
|
|
@ -18,27 +18,11 @@ impl<'a> ParserWorkingSet<'a> {
|
|||
) -> (Type, Option<ParseError>) {
|
||||
match &op.expr {
|
||||
Expr::Operator(operator) => match operator {
|
||||
Operator::Equal => (Type::Bool, None),
|
||||
Operator::Multiply => match (&lhs.ty, &rhs.ty) {
|
||||
(Type::Int, Type::Int) => (Type::Int, None),
|
||||
(Type::Unknown, _) => (Type::Unknown, None),
|
||||
(_, Type::Unknown) => (Type::Unknown, None),
|
||||
_ => {
|
||||
*op = Expression::garbage(op.span);
|
||||
(
|
||||
Type::Unknown,
|
||||
Some(ParseError::UnsupportedOperation(
|
||||
op.span,
|
||||
lhs.span,
|
||||
lhs.ty.clone(),
|
||||
rhs.span,
|
||||
rhs.ty.clone(),
|
||||
)),
|
||||
)
|
||||
}
|
||||
},
|
||||
Operator::Plus => match (&lhs.ty, &rhs.ty) {
|
||||
(Type::Int, Type::Int) => (Type::Int, None),
|
||||
(Type::Float, Type::Int) => (Type::Float, None),
|
||||
(Type::Int, Type::Float) => (Type::Float, None),
|
||||
(Type::Float, Type::Float) => (Type::Float, None),
|
||||
(Type::String, Type::String) => (Type::String, None),
|
||||
(Type::Unknown, _) => (Type::Unknown, None),
|
||||
(_, Type::Unknown) => (Type::Unknown, None),
|
||||
|
@ -69,6 +53,195 @@ impl<'a> ParserWorkingSet<'a> {
|
|||
)
|
||||
}
|
||||
},
|
||||
Operator::Minus => match (&lhs.ty, &rhs.ty) {
|
||||
(Type::Int, Type::Int) => (Type::Int, None),
|
||||
(Type::Float, Type::Int) => (Type::Float, None),
|
||||
(Type::Int, Type::Float) => (Type::Float, None),
|
||||
(Type::Float, Type::Float) => (Type::Float, None),
|
||||
(Type::Unknown, _) => (Type::Unknown, None),
|
||||
(_, Type::Unknown) => (Type::Unknown, None),
|
||||
_ => {
|
||||
*op = Expression::garbage(op.span);
|
||||
(
|
||||
Type::Unknown,
|
||||
Some(ParseError::UnsupportedOperation(
|
||||
op.span,
|
||||
lhs.span,
|
||||
lhs.ty.clone(),
|
||||
rhs.span,
|
||||
rhs.ty.clone(),
|
||||
)),
|
||||
)
|
||||
}
|
||||
},
|
||||
Operator::Multiply => match (&lhs.ty, &rhs.ty) {
|
||||
(Type::Int, Type::Int) => (Type::Int, None),
|
||||
(Type::Float, Type::Int) => (Type::Float, None),
|
||||
(Type::Int, Type::Float) => (Type::Float, None),
|
||||
(Type::Float, Type::Float) => (Type::Float, None),
|
||||
(Type::Unknown, _) => (Type::Unknown, None),
|
||||
(_, Type::Unknown) => (Type::Unknown, None),
|
||||
_ => {
|
||||
*op = Expression::garbage(op.span);
|
||||
(
|
||||
Type::Unknown,
|
||||
Some(ParseError::UnsupportedOperation(
|
||||
op.span,
|
||||
lhs.span,
|
||||
lhs.ty.clone(),
|
||||
rhs.span,
|
||||
rhs.ty.clone(),
|
||||
)),
|
||||
)
|
||||
}
|
||||
},
|
||||
Operator::Divide => match (&lhs.ty, &rhs.ty) {
|
||||
(Type::Int, Type::Int) => (Type::Int, None),
|
||||
(Type::Float, Type::Int) => (Type::Float, None),
|
||||
(Type::Int, Type::Float) => (Type::Float, None),
|
||||
(Type::Float, Type::Float) => (Type::Float, None),
|
||||
(Type::Unknown, _) => (Type::Unknown, None),
|
||||
(_, Type::Unknown) => (Type::Unknown, None),
|
||||
_ => {
|
||||
*op = Expression::garbage(op.span);
|
||||
(
|
||||
Type::Unknown,
|
||||
Some(ParseError::UnsupportedOperation(
|
||||
op.span,
|
||||
lhs.span,
|
||||
lhs.ty.clone(),
|
||||
rhs.span,
|
||||
rhs.ty.clone(),
|
||||
)),
|
||||
)
|
||||
}
|
||||
},
|
||||
Operator::LessThan => match (&lhs.ty, &rhs.ty) {
|
||||
(Type::Int, Type::Int) => (Type::Bool, None),
|
||||
(Type::Float, Type::Int) => (Type::Bool, None),
|
||||
(Type::Int, Type::Float) => (Type::Bool, None),
|
||||
(Type::Float, Type::Float) => (Type::Bool, None),
|
||||
(Type::Unknown, _) => (Type::Bool, None),
|
||||
(_, Type::Unknown) => (Type::Bool, None),
|
||||
_ => {
|
||||
*op = Expression::garbage(op.span);
|
||||
(
|
||||
Type::Unknown,
|
||||
Some(ParseError::UnsupportedOperation(
|
||||
op.span,
|
||||
lhs.span,
|
||||
lhs.ty.clone(),
|
||||
rhs.span,
|
||||
rhs.ty.clone(),
|
||||
)),
|
||||
)
|
||||
}
|
||||
},
|
||||
Operator::LessThanOrEqual => match (&lhs.ty, &rhs.ty) {
|
||||
(Type::Int, Type::Int) => (Type::Bool, None),
|
||||
(Type::Float, Type::Int) => (Type::Bool, None),
|
||||
(Type::Int, Type::Float) => (Type::Bool, None),
|
||||
(Type::Float, Type::Float) => (Type::Bool, None),
|
||||
(Type::Unknown, _) => (Type::Bool, None),
|
||||
(_, Type::Unknown) => (Type::Bool, None),
|
||||
_ => {
|
||||
*op = Expression::garbage(op.span);
|
||||
(
|
||||
Type::Unknown,
|
||||
Some(ParseError::UnsupportedOperation(
|
||||
op.span,
|
||||
lhs.span,
|
||||
lhs.ty.clone(),
|
||||
rhs.span,
|
||||
rhs.ty.clone(),
|
||||
)),
|
||||
)
|
||||
}
|
||||
},
|
||||
Operator::GreaterThan => match (&lhs.ty, &rhs.ty) {
|
||||
(Type::Int, Type::Int) => (Type::Bool, None),
|
||||
(Type::Float, Type::Int) => (Type::Bool, None),
|
||||
(Type::Int, Type::Float) => (Type::Bool, None),
|
||||
(Type::Float, Type::Float) => (Type::Bool, None),
|
||||
(Type::Unknown, _) => (Type::Bool, None),
|
||||
(_, Type::Unknown) => (Type::Bool, None),
|
||||
_ => {
|
||||
*op = Expression::garbage(op.span);
|
||||
(
|
||||
Type::Unknown,
|
||||
Some(ParseError::UnsupportedOperation(
|
||||
op.span,
|
||||
lhs.span,
|
||||
lhs.ty.clone(),
|
||||
rhs.span,
|
||||
rhs.ty.clone(),
|
||||
)),
|
||||
)
|
||||
}
|
||||
},
|
||||
Operator::GreaterThanOrEqual => match (&lhs.ty, &rhs.ty) {
|
||||
(Type::Int, Type::Int) => (Type::Bool, None),
|
||||
(Type::Float, Type::Int) => (Type::Bool, None),
|
||||
(Type::Int, Type::Float) => (Type::Bool, None),
|
||||
(Type::Float, Type::Float) => (Type::Bool, None),
|
||||
(Type::Unknown, _) => (Type::Bool, None),
|
||||
(_, Type::Unknown) => (Type::Bool, None),
|
||||
_ => {
|
||||
*op = Expression::garbage(op.span);
|
||||
(
|
||||
Type::Unknown,
|
||||
Some(ParseError::UnsupportedOperation(
|
||||
op.span,
|
||||
lhs.span,
|
||||
lhs.ty.clone(),
|
||||
rhs.span,
|
||||
rhs.ty.clone(),
|
||||
)),
|
||||
)
|
||||
}
|
||||
},
|
||||
Operator::Equal => match (&lhs.ty, &rhs.ty) {
|
||||
(Type::Float, Type::Int) => (Type::Bool, None),
|
||||
(Type::Int, Type::Float) => (Type::Bool, None),
|
||||
(x, y) if x == y => (Type::Bool, None),
|
||||
(Type::Unknown, _) => (Type::Bool, None),
|
||||
(_, Type::Unknown) => (Type::Bool, None),
|
||||
_ => {
|
||||
*op = Expression::garbage(op.span);
|
||||
(
|
||||
Type::Unknown,
|
||||
Some(ParseError::UnsupportedOperation(
|
||||
op.span,
|
||||
lhs.span,
|
||||
lhs.ty.clone(),
|
||||
rhs.span,
|
||||
rhs.ty.clone(),
|
||||
)),
|
||||
)
|
||||
}
|
||||
},
|
||||
Operator::NotEqual => match (&lhs.ty, &rhs.ty) {
|
||||
(Type::Int, Type::Int) => (Type::Bool, None),
|
||||
(Type::Float, Type::Int) => (Type::Bool, None),
|
||||
(Type::Int, Type::Float) => (Type::Bool, None),
|
||||
(Type::Float, Type::Float) => (Type::Bool, None),
|
||||
(Type::Unknown, _) => (Type::Bool, None),
|
||||
(_, Type::Unknown) => (Type::Bool, None),
|
||||
_ => {
|
||||
*op = Expression::garbage(op.span);
|
||||
(
|
||||
Type::Unknown,
|
||||
Some(ParseError::UnsupportedOperation(
|
||||
op.span,
|
||||
lhs.span,
|
||||
lhs.ty.clone(),
|
||||
rhs.span,
|
||||
rhs.ty.clone(),
|
||||
)),
|
||||
)
|
||||
}
|
||||
},
|
||||
|
||||
_ => {
|
||||
*op = Expression::garbage(op.span);
|
||||
|
||||
|
|
Loading…
Reference in a new issue