mirror of
https://github.com/nushell/nushell.git
synced 2024-12-22 15:13:01 +01:00
Add a few operators. Needs parser work
This commit is contained in:
parent
739425431a
commit
35c3622405
@ -5,6 +5,9 @@ edition = "2018"
|
|||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# 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]
|
[dependencies]
|
||||||
reedline = { git = "https://github.com/jntrnr/reedline", branch = "main" }
|
reedline = { git = "https://github.com/jntrnr/reedline", branch = "main" }
|
||||||
codespan-reporting = "0.11.1"
|
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_labels(vec![Label::primary(diag_file_id, diag_range)
|
||||||
.with_message(format!("can't convert to {}", s))])
|
.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");
|
// println!("DIAG");
|
||||||
|
@ -16,6 +16,7 @@ pub enum ShellError {
|
|||||||
InternalError(String),
|
InternalError(String),
|
||||||
VariableNotFound(Span),
|
VariableNotFound(Span),
|
||||||
CantConvert(String, Span),
|
CantConvert(String, Span),
|
||||||
|
DivisionByZero(Span),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eval_operator(op: &Expression) -> Result<Operator, ShellError> {
|
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 {
|
match op {
|
||||||
Operator::Plus => lhs.add(op_span, &rhs),
|
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},
|
parser_state::{Type, VarId},
|
||||||
signature::{Flag, PositionalArg},
|
signature::{Flag, PositionalArg},
|
||||||
BlockId, DeclId, Declaration, LiteBlock, ParseError, ParserWorkingSet, Signature, Span, Token,
|
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.
|
/// 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 {
|
Expression {
|
||||||
expr: Expr::Float(x),
|
expr: Expr::Float(x),
|
||||||
span,
|
span,
|
||||||
ty: Type::Int,
|
ty: Type::Float,
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
@ -1450,6 +1451,7 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
error = error.or(err);
|
error = error.or(err);
|
||||||
|
|
||||||
let mut args: Vec<Arg> = vec![];
|
let mut args: Vec<Arg> = vec![];
|
||||||
|
let mut rest: Option<Arg> = None;
|
||||||
let mut parse_mode = ParseMode::ArgMode;
|
let mut parse_mode = ParseMode::ArgMode;
|
||||||
|
|
||||||
for token in &output {
|
for token in &output {
|
||||||
@ -1947,6 +1949,32 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
let (output, err) = lex(source, start, &[], &[]);
|
let (output, err) = lex(source, start, &[], &[]);
|
||||||
error = error.or(err);
|
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);
|
let (output, err) = lite_parse(&output);
|
||||||
error = error.or(err);
|
error = error.or(err);
|
||||||
|
|
||||||
|
@ -18,27 +18,11 @@ impl<'a> ParserWorkingSet<'a> {
|
|||||||
) -> (Type, Option<ParseError>) {
|
) -> (Type, Option<ParseError>) {
|
||||||
match &op.expr {
|
match &op.expr {
|
||||||
Expr::Operator(operator) => match operator {
|
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) {
|
Operator::Plus => match (&lhs.ty, &rhs.ty) {
|
||||||
(Type::Int, Type::Int) => (Type::Int, None),
|
(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::String, Type::String) => (Type::String, None),
|
||||||
(Type::Unknown, _) => (Type::Unknown, None),
|
(Type::Unknown, _) => (Type::Unknown, 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);
|
*op = Expression::garbage(op.span);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user