mirror of
https://github.com/nushell/nushell.git
synced 2024-11-22 00:13:21 +01:00
Change append operator to concat operator
This commit is contained in:
parent
30f98f7e64
commit
e987ccab56
@ -60,10 +60,6 @@ impl Completer for OperatorCompletion {
|
|||||||
("bit-shr", "Bitwise shift right"),
|
("bit-shr", "Bitwise shift right"),
|
||||||
("in", "Is a member of (doesn't use regex)"),
|
("in", "Is a member of (doesn't use regex)"),
|
||||||
("not-in", "Is not a member of (doesn't use regex)"),
|
("not-in", "Is not a member of (doesn't use regex)"),
|
||||||
(
|
|
||||||
"++",
|
|
||||||
"Appends two lists, a list and a value, two strings, or two binary values",
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
Expr::String(_) => vec![
|
Expr::String(_) => vec![
|
||||||
("=~", "Contains regex match"),
|
("=~", "Contains regex match"),
|
||||||
@ -72,7 +68,7 @@ impl Completer for OperatorCompletion {
|
|||||||
("not-like", "Does not contain regex match"),
|
("not-like", "Does not contain regex match"),
|
||||||
(
|
(
|
||||||
"++",
|
"++",
|
||||||
"Appends two lists, a list and a value, two strings, or two binary values",
|
"Concatenates two lists, two strings, or two binary values",
|
||||||
),
|
),
|
||||||
("in", "Is a member of (doesn't use regex)"),
|
("in", "Is a member of (doesn't use regex)"),
|
||||||
("not-in", "Is not a member of (doesn't use regex)"),
|
("not-in", "Is not a member of (doesn't use regex)"),
|
||||||
@ -95,10 +91,6 @@ impl Completer for OperatorCompletion {
|
|||||||
("**", "Power of"),
|
("**", "Power of"),
|
||||||
("in", "Is a member of (doesn't use regex)"),
|
("in", "Is a member of (doesn't use regex)"),
|
||||||
("not-in", "Is not a member of (doesn't use regex)"),
|
("not-in", "Is not a member of (doesn't use regex)"),
|
||||||
(
|
|
||||||
"++",
|
|
||||||
"Appends two lists, a list and a value, two strings, or two binary values",
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
Expr::Bool(_) => vec![
|
Expr::Bool(_) => vec![
|
||||||
(
|
(
|
||||||
@ -113,15 +105,11 @@ impl Completer for OperatorCompletion {
|
|||||||
("not", "Negates a value or expression"),
|
("not", "Negates a value or expression"),
|
||||||
("in", "Is a member of (doesn't use regex)"),
|
("in", "Is a member of (doesn't use regex)"),
|
||||||
("not-in", "Is not a member of (doesn't use regex)"),
|
("not-in", "Is not a member of (doesn't use regex)"),
|
||||||
(
|
|
||||||
"++",
|
|
||||||
"Appends two lists, a list and a value, two strings, or two binary values",
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
Expr::FullCellPath(path) => match path.head.expr {
|
Expr::FullCellPath(path) => match path.head.expr {
|
||||||
Expr::List(_) => vec![(
|
Expr::List(_) => vec![(
|
||||||
"++",
|
"++",
|
||||||
"Appends two lists, a list and a value, two strings, or two binary values",
|
"Concatenates two lists, two strings, or two binary values",
|
||||||
)],
|
)],
|
||||||
Expr::Var(id) => get_variable_completions(id, working_set),
|
Expr::Var(id) => get_variable_completions(id, working_set),
|
||||||
_ => vec![],
|
_ => vec![],
|
||||||
@ -165,7 +153,7 @@ pub fn get_variable_completions<'a>(
|
|||||||
Type::List(_) | Type::String | Type::Binary => vec![
|
Type::List(_) | Type::String | Type::Binary => vec![
|
||||||
(
|
(
|
||||||
"++=",
|
"++=",
|
||||||
"Appends a list, a value, a string, or a binary value to a variable.",
|
"Concatenates two lists, two strings, or two binary values",
|
||||||
),
|
),
|
||||||
("=", "Assigns a value to a variable."),
|
("=", "Assigns a value to a variable."),
|
||||||
],
|
],
|
||||||
|
@ -31,7 +31,7 @@ impl Command for HelpOperators {
|
|||||||
let mut operators = [
|
let mut operators = [
|
||||||
Operator::Assignment(Assignment::Assign),
|
Operator::Assignment(Assignment::Assign),
|
||||||
Operator::Assignment(Assignment::PlusAssign),
|
Operator::Assignment(Assignment::PlusAssign),
|
||||||
Operator::Assignment(Assignment::AppendAssign),
|
Operator::Assignment(Assignment::ConcatAssign),
|
||||||
Operator::Assignment(Assignment::MinusAssign),
|
Operator::Assignment(Assignment::MinusAssign),
|
||||||
Operator::Assignment(Assignment::MultiplyAssign),
|
Operator::Assignment(Assignment::MultiplyAssign),
|
||||||
Operator::Assignment(Assignment::DivideAssign),
|
Operator::Assignment(Assignment::DivideAssign),
|
||||||
@ -48,7 +48,7 @@ impl Command for HelpOperators {
|
|||||||
Operator::Comparison(Comparison::StartsWith),
|
Operator::Comparison(Comparison::StartsWith),
|
||||||
Operator::Comparison(Comparison::EndsWith),
|
Operator::Comparison(Comparison::EndsWith),
|
||||||
Operator::Math(Math::Plus),
|
Operator::Math(Math::Plus),
|
||||||
Operator::Math(Math::Append),
|
Operator::Math(Math::Concat),
|
||||||
Operator::Math(Math::Minus),
|
Operator::Math(Math::Minus),
|
||||||
Operator::Math(Math::Multiply),
|
Operator::Math(Math::Multiply),
|
||||||
Operator::Math(Math::Divide),
|
Operator::Math(Math::Divide),
|
||||||
@ -144,7 +144,7 @@ fn description(operator: &Operator) -> &'static str {
|
|||||||
Operator::Comparison(Comparison::StartsWith) => "Checks if a string starts with another.",
|
Operator::Comparison(Comparison::StartsWith) => "Checks if a string starts with another.",
|
||||||
Operator::Comparison(Comparison::EndsWith) => "Checks if a string ends with another.",
|
Operator::Comparison(Comparison::EndsWith) => "Checks if a string ends with another.",
|
||||||
Operator::Math(Math::Plus) => "Adds two values.",
|
Operator::Math(Math::Plus) => "Adds two values.",
|
||||||
Operator::Math(Math::Append) => {
|
Operator::Math(Math::Concat) => {
|
||||||
"Appends two lists, a list and a value, two strings, or two binary values."
|
"Appends two lists, a list and a value, two strings, or two binary values."
|
||||||
}
|
}
|
||||||
Operator::Math(Math::Minus) => "Subtracts two values.",
|
Operator::Math(Math::Minus) => "Subtracts two values.",
|
||||||
@ -163,7 +163,7 @@ fn description(operator: &Operator) -> &'static str {
|
|||||||
Operator::Bits(Bits::ShiftRight) => "Bitwise shifts a value right by another.",
|
Operator::Bits(Bits::ShiftRight) => "Bitwise shifts a value right by another.",
|
||||||
Operator::Assignment(Assignment::Assign) => "Assigns a value to a variable.",
|
Operator::Assignment(Assignment::Assign) => "Assigns a value to a variable.",
|
||||||
Operator::Assignment(Assignment::PlusAssign) => "Adds a value to a variable.",
|
Operator::Assignment(Assignment::PlusAssign) => "Adds a value to a variable.",
|
||||||
Operator::Assignment(Assignment::AppendAssign) => {
|
Operator::Assignment(Assignment::ConcatAssign) => {
|
||||||
"Appends a list, a value, a string, or a binary value to a variable."
|
"Appends a list, a value, a string, or a binary value to a variable."
|
||||||
}
|
}
|
||||||
Operator::Assignment(Assignment::MinusAssign) => "Subtracts a value from a variable.",
|
Operator::Assignment(Assignment::MinusAssign) => "Subtracts a value from a variable.",
|
||||||
|
@ -1,88 +0,0 @@
|
|||||||
use nu_test_support::nu;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn append_assign_int() {
|
|
||||||
let actual = nu!(r#"
|
|
||||||
mut a = [1 2];
|
|
||||||
$a ++= [3 4];
|
|
||||||
$a == [1 2 3 4]
|
|
||||||
"#);
|
|
||||||
|
|
||||||
assert_eq!(actual.out, "true")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn append_assign_string() {
|
|
||||||
let actual = nu!(r#"
|
|
||||||
mut a = [a b];
|
|
||||||
$a ++= [c d];
|
|
||||||
$a == [a b c d]
|
|
||||||
"#);
|
|
||||||
|
|
||||||
assert_eq!(actual.out, "true")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn append_assign_any() {
|
|
||||||
let actual = nu!(r#"
|
|
||||||
mut a = [1 2 a];
|
|
||||||
$a ++= [b 3];
|
|
||||||
$a == [1 2 a b 3]
|
|
||||||
"#);
|
|
||||||
|
|
||||||
assert_eq!(actual.out, "true")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn append_assign_both_empty() {
|
|
||||||
let actual = nu!(r#"
|
|
||||||
mut a = [];
|
|
||||||
$a ++= [];
|
|
||||||
$a == []
|
|
||||||
"#);
|
|
||||||
|
|
||||||
assert_eq!(actual.out, "true")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn append_assign_type_mismatch() {
|
|
||||||
let actual = nu!(r#"
|
|
||||||
mut a = [1 2];
|
|
||||||
$a ++= [a];
|
|
||||||
$a == [1 2 "a"]
|
|
||||||
"#);
|
|
||||||
|
|
||||||
assert_eq!(actual.out, "true")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn append_assign_single_element() {
|
|
||||||
let actual = nu!(r#"
|
|
||||||
mut a = ["list" "and"];
|
|
||||||
$a ++= "a single element";
|
|
||||||
$a == ["list" "and" "a single element"]
|
|
||||||
"#);
|
|
||||||
|
|
||||||
assert_eq!(actual.out, "true")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn append_assign_to_single_element() {
|
|
||||||
let actual = nu!(r#"
|
|
||||||
mut a = "string";
|
|
||||||
$a ++= ["and" "the" "list"];
|
|
||||||
$a == ["string" "and" "the" "list"]
|
|
||||||
"#);
|
|
||||||
|
|
||||||
assert_eq!(actual.out, "true")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn append_assign_single_to_single() {
|
|
||||||
let actual = nu!(r#"
|
|
||||||
mut a = 1;
|
|
||||||
$a ++= "and a single element";
|
|
||||||
"#);
|
|
||||||
|
|
||||||
assert!(actual.err.contains("nu::parser::unsupported_operation"));
|
|
||||||
}
|
|
76
crates/nu-command/tests/commands/assignment/concat.rs
Normal file
76
crates/nu-command/tests/commands/assignment/concat.rs
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
use nu_test_support::nu;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn concat_assign_list_int() {
|
||||||
|
let actual = nu!(r#"
|
||||||
|
mut a = [1 2];
|
||||||
|
$a ++= [3 4];
|
||||||
|
$a == [1 2 3 4]
|
||||||
|
"#);
|
||||||
|
|
||||||
|
assert_eq!(actual.out, "true")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn concat_assign_list_string() {
|
||||||
|
let actual = nu!(r#"
|
||||||
|
mut a = [a b];
|
||||||
|
$a ++= [c d];
|
||||||
|
$a == [a b c d]
|
||||||
|
"#);
|
||||||
|
|
||||||
|
assert_eq!(actual.out, "true")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn concat_assign_any() {
|
||||||
|
let actual = nu!(r#"
|
||||||
|
mut a = [1 2 a];
|
||||||
|
$a ++= [b 3];
|
||||||
|
$a == [1 2 a b 3]
|
||||||
|
"#);
|
||||||
|
|
||||||
|
assert_eq!(actual.out, "true")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn concat_assign_both_empty() {
|
||||||
|
let actual = nu!(r#"
|
||||||
|
mut a = [];
|
||||||
|
$a ++= [];
|
||||||
|
$a == []
|
||||||
|
"#);
|
||||||
|
|
||||||
|
assert_eq!(actual.out, "true")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn concat_assign_string() {
|
||||||
|
let actual = nu!(r#"
|
||||||
|
mut a = 'hello';
|
||||||
|
$a ++= ' world';
|
||||||
|
$a == 'hello world'
|
||||||
|
"#);
|
||||||
|
|
||||||
|
assert_eq!(actual.out, "true")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn concat_assign_type_mismatch() {
|
||||||
|
let actual = nu!(r#"
|
||||||
|
mut a = [];
|
||||||
|
$a ++= 'str'
|
||||||
|
"#);
|
||||||
|
|
||||||
|
assert!(actual.err.contains("nu::parser::unsupported_operation"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn concat_assign_runtime_type_mismatch() {
|
||||||
|
let actual = nu!(r#"
|
||||||
|
mut a = [];
|
||||||
|
$a ++= if true { 'str' }
|
||||||
|
"#);
|
||||||
|
|
||||||
|
assert!(actual.err.contains("nu::shell::type_mismatch"));
|
||||||
|
}
|
@ -1 +1 @@
|
|||||||
mod append_assign;
|
mod concat;
|
||||||
|
@ -483,7 +483,7 @@ fn compound_where_paren() {
|
|||||||
// TODO: these ++ tests are not really testing *math* functionality, maybe find another place for them
|
// TODO: these ++ tests are not really testing *math* functionality, maybe find another place for them
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn adding_lists() {
|
fn concat_lists() {
|
||||||
let actual = nu!(pipeline(
|
let actual = nu!(pipeline(
|
||||||
r#"
|
r#"
|
||||||
[1 3] ++ [5 6] | to nuon
|
[1 3] ++ [5 6] | to nuon
|
||||||
@ -494,29 +494,7 @@ fn adding_lists() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn adding_list_and_value() {
|
fn concat_tables() {
|
||||||
let actual = nu!(pipeline(
|
|
||||||
r#"
|
|
||||||
[1 3] ++ 5 | to nuon
|
|
||||||
"#
|
|
||||||
));
|
|
||||||
|
|
||||||
assert_eq!(actual.out, "[1, 3, 5]");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn adding_value_and_list() {
|
|
||||||
let actual = nu!(pipeline(
|
|
||||||
r#"
|
|
||||||
1 ++ [3 5] | to nuon
|
|
||||||
"#
|
|
||||||
));
|
|
||||||
|
|
||||||
assert_eq!(actual.out, "[1, 3, 5]");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn adding_tables() {
|
|
||||||
let actual = nu!(pipeline(
|
let actual = nu!(pipeline(
|
||||||
r#"
|
r#"
|
||||||
[[a b]; [1 2]] ++ [[c d]; [10 11]] | to nuon
|
[[a b]; [1 2]] ++ [[c d]; [10 11]] | to nuon
|
||||||
@ -526,7 +504,7 @@ fn adding_tables() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn append_strings() {
|
fn concat_strings() {
|
||||||
let actual = nu!(pipeline(
|
let actual = nu!(pipeline(
|
||||||
r#"
|
r#"
|
||||||
"foo" ++ "bar"
|
"foo" ++ "bar"
|
||||||
@ -536,7 +514,7 @@ fn append_strings() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn append_binary_values() {
|
fn concat_binary_values() {
|
||||||
let actual = nu!(pipeline(
|
let actual = nu!(pipeline(
|
||||||
r#"
|
r#"
|
||||||
0x[01 02] ++ 0x[03 04] | to nuon
|
0x[01 02] ++ 0x[03 04] | to nuon
|
||||||
|
@ -27,7 +27,7 @@ fn url_join_with_only_user() {
|
|||||||
"password": "",
|
"password": "",
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"port": "",
|
"port": "",
|
||||||
} | url join
|
} | url join
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ fn url_join_with_only_pwd() {
|
|||||||
"password": "pwd",
|
"password": "pwd",
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"port": "",
|
"port": "",
|
||||||
} | url join
|
} | url join
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ fn url_join_with_user_and_pwd() {
|
|||||||
"password": "pwd",
|
"password": "pwd",
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"port": "",
|
"port": "",
|
||||||
} | url join
|
} | url join
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ fn url_join_with_query() {
|
|||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"query": "par_1=aaa&par_2=bbb"
|
"query": "par_1=aaa&par_2=bbb"
|
||||||
"port": "",
|
"port": "",
|
||||||
} | url join
|
} | url join
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -411,12 +411,9 @@ fn url_join_with_params_invalid_table() {
|
|||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"params": (
|
"params": (
|
||||||
[
|
[
|
||||||
["key", "value"];
|
{ key: foo, value: bar }
|
||||||
["par_1", "aaa"],
|
"not a record"
|
||||||
["par_2", "bbb"],
|
]
|
||||||
["par_1", "ccc"],
|
|
||||||
["par_2", "ddd"],
|
|
||||||
] ++ ["not a record"]
|
|
||||||
),
|
),
|
||||||
"port": "1234",
|
"port": "1234",
|
||||||
} | url join
|
} | url join
|
||||||
|
@ -155,7 +155,7 @@ pub(crate) fn decompose_assignment(assignment: Assignment) -> Option<Operator> {
|
|||||||
match assignment {
|
match assignment {
|
||||||
Assignment::Assign => None,
|
Assignment::Assign => None,
|
||||||
Assignment::PlusAssign => Some(Operator::Math(Math::Plus)),
|
Assignment::PlusAssign => Some(Operator::Math(Math::Plus)),
|
||||||
Assignment::AppendAssign => Some(Operator::Math(Math::Append)),
|
Assignment::ConcatAssign => Some(Operator::Math(Math::Concat)),
|
||||||
Assignment::MinusAssign => Some(Operator::Math(Math::Minus)),
|
Assignment::MinusAssign => Some(Operator::Math(Math::Minus)),
|
||||||
Assignment::MultiplyAssign => Some(Operator::Math(Math::Multiply)),
|
Assignment::MultiplyAssign => Some(Operator::Math(Math::Multiply)),
|
||||||
Assignment::DivideAssign => Some(Operator::Math(Math::Divide)),
|
Assignment::DivideAssign => Some(Operator::Math(Math::Divide)),
|
||||||
|
@ -794,9 +794,9 @@ impl Eval for EvalRuntime {
|
|||||||
let lhs = eval_expression::<D>(engine_state, stack, lhs)?;
|
let lhs = eval_expression::<D>(engine_state, stack, lhs)?;
|
||||||
lhs.div(op_span, &rhs, op_span)?
|
lhs.div(op_span, &rhs, op_span)?
|
||||||
}
|
}
|
||||||
Assignment::AppendAssign => {
|
Assignment::ConcatAssign => {
|
||||||
let lhs = eval_expression::<D>(engine_state, stack, lhs)?;
|
let lhs = eval_expression::<D>(engine_state, stack, lhs)?;
|
||||||
lhs.append(op_span, &rhs, op_span)?
|
lhs.concat(op_span, &rhs, op_span)?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -956,7 +956,7 @@ fn binary_op(
|
|||||||
},
|
},
|
||||||
Operator::Math(mat) => match mat {
|
Operator::Math(mat) => match mat {
|
||||||
Math::Plus => lhs_val.add(op_span, &rhs_val, span)?,
|
Math::Plus => lhs_val.add(op_span, &rhs_val, span)?,
|
||||||
Math::Append => lhs_val.append(op_span, &rhs_val, span)?,
|
Math::Concat => lhs_val.concat(op_span, &rhs_val, span)?,
|
||||||
Math::Minus => lhs_val.sub(op_span, &rhs_val, span)?,
|
Math::Minus => lhs_val.sub(op_span, &rhs_val, span)?,
|
||||||
Math::Multiply => lhs_val.mul(op_span, &rhs_val, span)?,
|
Math::Multiply => lhs_val.mul(op_span, &rhs_val, span)?,
|
||||||
Math::Divide => lhs_val.div(op_span, &rhs_val, span)?,
|
Math::Divide => lhs_val.div(op_span, &rhs_val, span)?,
|
||||||
|
@ -4895,7 +4895,7 @@ pub fn parse_assignment_operator(working_set: &mut StateWorkingSet, span: Span)
|
|||||||
let operator = match contents {
|
let operator = match contents {
|
||||||
b"=" => Operator::Assignment(Assignment::Assign),
|
b"=" => Operator::Assignment(Assignment::Assign),
|
||||||
b"+=" => Operator::Assignment(Assignment::PlusAssign),
|
b"+=" => Operator::Assignment(Assignment::PlusAssign),
|
||||||
b"++=" => Operator::Assignment(Assignment::AppendAssign),
|
b"++=" => Operator::Assignment(Assignment::ConcatAssign),
|
||||||
b"-=" => Operator::Assignment(Assignment::MinusAssign),
|
b"-=" => Operator::Assignment(Assignment::MinusAssign),
|
||||||
b"*=" => Operator::Assignment(Assignment::MultiplyAssign),
|
b"*=" => Operator::Assignment(Assignment::MultiplyAssign),
|
||||||
b"/=" => Operator::Assignment(Assignment::DivideAssign),
|
b"/=" => Operator::Assignment(Assignment::DivideAssign),
|
||||||
@ -5021,7 +5021,7 @@ pub fn parse_operator(working_set: &mut StateWorkingSet, span: Span) -> Expressi
|
|||||||
b"=~" | b"like" => Operator::Comparison(Comparison::RegexMatch),
|
b"=~" | b"like" => Operator::Comparison(Comparison::RegexMatch),
|
||||||
b"!~" | b"not-like" => Operator::Comparison(Comparison::NotRegexMatch),
|
b"!~" | b"not-like" => Operator::Comparison(Comparison::NotRegexMatch),
|
||||||
b"+" => Operator::Math(Math::Plus),
|
b"+" => Operator::Math(Math::Plus),
|
||||||
b"++" => Operator::Math(Math::Append),
|
b"++" => Operator::Math(Math::Concat),
|
||||||
b"-" => Operator::Math(Math::Minus),
|
b"-" => Operator::Math(Math::Minus),
|
||||||
b"*" => Operator::Math(Math::Multiply),
|
b"*" => Operator::Math(Math::Multiply),
|
||||||
b"/" => Operator::Math(Math::Divide),
|
b"/" => Operator::Math(Math::Divide),
|
||||||
|
@ -131,7 +131,7 @@ pub fn math_result_type(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Operator::Math(Math::Append) => check_append(working_set, lhs, rhs, op),
|
Operator::Math(Math::Concat) => check_concat(working_set, lhs, rhs, op),
|
||||||
Operator::Math(Math::Minus) => match (&lhs.ty, &rhs.ty) {
|
Operator::Math(Math::Minus) => 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::Float, Type::Int) => (Type::Float, None),
|
||||||
@ -934,8 +934,8 @@ pub fn math_result_type(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Operator::Assignment(Assignment::AppendAssign) => {
|
Operator::Assignment(Assignment::ConcatAssign) => {
|
||||||
check_append(working_set, lhs, rhs, op)
|
check_concat(working_set, lhs, rhs, op)
|
||||||
}
|
}
|
||||||
Operator::Assignment(_) => match (&lhs.ty, &rhs.ty) {
|
Operator::Assignment(_) => match (&lhs.ty, &rhs.ty) {
|
||||||
(x, y) if x == y => (Type::Nothing, None),
|
(x, y) if x == y => (Type::Nothing, None),
|
||||||
@ -1084,7 +1084,7 @@ pub fn check_block_input_output(working_set: &StateWorkingSet, block: &Block) ->
|
|||||||
output_errors
|
output_errors
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_append(
|
fn check_concat(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
lhs: &Expression,
|
lhs: &Expression,
|
||||||
rhs: &Expression,
|
rhs: &Expression,
|
||||||
@ -1098,13 +1098,6 @@ fn check_append(
|
|||||||
(Type::List(Box::new(Type::Any)), None)
|
(Type::List(Box::new(Type::Any)), None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Type::List(a), b) | (b, Type::List(a)) => {
|
|
||||||
if a == &Box::new(b.clone()) {
|
|
||||||
(Type::List(a.clone()), None)
|
|
||||||
} else {
|
|
||||||
(Type::List(Box::new(Type::Any)), None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(Type::Table(a), Type::Table(_)) => (Type::Table(a.clone()), None),
|
(Type::Table(a), Type::Table(_)) => (Type::Table(a.clone()), None),
|
||||||
(Type::String, Type::String) => (Type::String, None),
|
(Type::String, Type::String) => (Type::String, None),
|
||||||
(Type::Binary, Type::Binary) => (Type::Binary, None),
|
(Type::Binary, Type::Binary) => (Type::Binary, None),
|
||||||
@ -1114,7 +1107,7 @@ fn check_append(
|
|||||||
(
|
(
|
||||||
Type::Any,
|
Type::Any,
|
||||||
Some(ParseError::UnsupportedOperationRHS(
|
Some(ParseError::UnsupportedOperationRHS(
|
||||||
"append".into(),
|
"concat".into(),
|
||||||
op.span,
|
op.span,
|
||||||
lhs.span,
|
lhs.span,
|
||||||
lhs.ty.clone(),
|
lhs.ty.clone(),
|
||||||
@ -1128,7 +1121,7 @@ fn check_append(
|
|||||||
(
|
(
|
||||||
Type::Any,
|
Type::Any,
|
||||||
Some(ParseError::UnsupportedOperationLHS(
|
Some(ParseError::UnsupportedOperationLHS(
|
||||||
"append".into(),
|
"concat".into(),
|
||||||
op.span,
|
op.span,
|
||||||
lhs.span,
|
lhs.span,
|
||||||
lhs.ty.clone(),
|
lhs.ty.clone(),
|
||||||
|
@ -1485,7 +1485,7 @@ fn prepare_plugin_call_custom_value_op() {
|
|||||||
span,
|
span,
|
||||||
},
|
},
|
||||||
CustomValueOp::Operation(
|
CustomValueOp::Operation(
|
||||||
Operator::Math(Math::Append).into_spanned(span),
|
Operator::Math(Math::Concat).into_spanned(span),
|
||||||
cv_ok_val.clone(),
|
cv_ok_val.clone(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1498,7 +1498,7 @@ fn prepare_plugin_call_custom_value_op() {
|
|||||||
span,
|
span,
|
||||||
},
|
},
|
||||||
CustomValueOp::Operation(
|
CustomValueOp::Operation(
|
||||||
Operator::Math(Math::Append).into_spanned(span),
|
Operator::Math(Math::Concat).into_spanned(span),
|
||||||
cv_bad_val.clone(),
|
cv_bad_val.clone(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -24,7 +24,7 @@ pub enum Comparison {
|
|||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub enum Math {
|
pub enum Math {
|
||||||
Plus,
|
Plus,
|
||||||
Append,
|
Concat,
|
||||||
Minus,
|
Minus,
|
||||||
Multiply,
|
Multiply,
|
||||||
Divide,
|
Divide,
|
||||||
@ -53,7 +53,7 @@ pub enum Bits {
|
|||||||
pub enum Assignment {
|
pub enum Assignment {
|
||||||
Assign,
|
Assign,
|
||||||
PlusAssign,
|
PlusAssign,
|
||||||
AppendAssign,
|
ConcatAssign,
|
||||||
MinusAssign,
|
MinusAssign,
|
||||||
MultiplyAssign,
|
MultiplyAssign,
|
||||||
DivideAssign,
|
DivideAssign,
|
||||||
@ -90,7 +90,7 @@ impl Operator {
|
|||||||
| Self::Comparison(Comparison::NotEqual)
|
| Self::Comparison(Comparison::NotEqual)
|
||||||
| Self::Comparison(Comparison::In)
|
| Self::Comparison(Comparison::In)
|
||||||
| Self::Comparison(Comparison::NotIn)
|
| Self::Comparison(Comparison::NotIn)
|
||||||
| Self::Math(Math::Append) => 80,
|
| Self::Math(Math::Concat) => 80,
|
||||||
Self::Bits(Bits::BitAnd) => 75,
|
Self::Bits(Bits::BitAnd) => 75,
|
||||||
Self::Bits(Bits::BitXor) => 70,
|
Self::Bits(Bits::BitXor) => 70,
|
||||||
Self::Bits(Bits::BitOr) => 60,
|
Self::Bits(Bits::BitOr) => 60,
|
||||||
@ -107,7 +107,7 @@ impl Display for Operator {
|
|||||||
match self {
|
match self {
|
||||||
Operator::Assignment(Assignment::Assign) => write!(f, "="),
|
Operator::Assignment(Assignment::Assign) => write!(f, "="),
|
||||||
Operator::Assignment(Assignment::PlusAssign) => write!(f, "+="),
|
Operator::Assignment(Assignment::PlusAssign) => write!(f, "+="),
|
||||||
Operator::Assignment(Assignment::AppendAssign) => write!(f, "++="),
|
Operator::Assignment(Assignment::ConcatAssign) => write!(f, "++="),
|
||||||
Operator::Assignment(Assignment::MinusAssign) => write!(f, "-="),
|
Operator::Assignment(Assignment::MinusAssign) => write!(f, "-="),
|
||||||
Operator::Assignment(Assignment::MultiplyAssign) => write!(f, "*="),
|
Operator::Assignment(Assignment::MultiplyAssign) => write!(f, "*="),
|
||||||
Operator::Assignment(Assignment::DivideAssign) => write!(f, "/="),
|
Operator::Assignment(Assignment::DivideAssign) => write!(f, "/="),
|
||||||
@ -124,7 +124,7 @@ impl Display for Operator {
|
|||||||
Operator::Comparison(Comparison::In) => write!(f, "in"),
|
Operator::Comparison(Comparison::In) => write!(f, "in"),
|
||||||
Operator::Comparison(Comparison::NotIn) => write!(f, "not-in"),
|
Operator::Comparison(Comparison::NotIn) => write!(f, "not-in"),
|
||||||
Operator::Math(Math::Plus) => write!(f, "+"),
|
Operator::Math(Math::Plus) => write!(f, "+"),
|
||||||
Operator::Math(Math::Append) => write!(f, "++"),
|
Operator::Math(Math::Concat) => write!(f, "++"),
|
||||||
Operator::Math(Math::Minus) => write!(f, "-"),
|
Operator::Math(Math::Minus) => write!(f, "-"),
|
||||||
Operator::Math(Math::Multiply) => write!(f, "*"),
|
Operator::Math(Math::Multiply) => write!(f, "*"),
|
||||||
Operator::Math(Math::Divide) => write!(f, "/"),
|
Operator::Math(Math::Divide) => write!(f, "/"),
|
||||||
|
@ -238,7 +238,7 @@ pub trait Eval {
|
|||||||
Math::Minus => lhs.sub(op_span, &rhs, expr_span),
|
Math::Minus => lhs.sub(op_span, &rhs, expr_span),
|
||||||
Math::Multiply => lhs.mul(op_span, &rhs, expr_span),
|
Math::Multiply => lhs.mul(op_span, &rhs, expr_span),
|
||||||
Math::Divide => lhs.div(op_span, &rhs, expr_span),
|
Math::Divide => lhs.div(op_span, &rhs, expr_span),
|
||||||
Math::Append => lhs.append(op_span, &rhs, expr_span),
|
Math::Concat => lhs.concat(op_span, &rhs, expr_span),
|
||||||
Math::Modulo => lhs.modulo(op_span, &rhs, expr_span),
|
Math::Modulo => lhs.modulo(op_span, &rhs, expr_span),
|
||||||
Math::FloorDivision => lhs.floor_div(op_span, &rhs, expr_span),
|
Math::FloorDivision => lhs.floor_div(op_span, &rhs, expr_span),
|
||||||
Math::Pow => lhs.pow(op_span, &rhs, expr_span),
|
Math::Pow => lhs.pow(op_span, &rhs, expr_span),
|
||||||
|
@ -2492,34 +2492,20 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn append(&self, op: Span, rhs: &Value, span: Span) -> Result<Value, ShellError> {
|
pub fn concat(&self, op: Span, rhs: &Value, span: Span) -> Result<Value, ShellError> {
|
||||||
match (self, rhs) {
|
match (self, rhs) {
|
||||||
(Value::List { vals: lhs, .. }, Value::List { vals: rhs, .. }) => {
|
(Value::List { vals: lhs, .. }, Value::List { vals: rhs, .. }) => {
|
||||||
let mut lhs = lhs.clone();
|
Ok(Value::list([lhs.as_slice(), rhs.as_slice()].concat(), span))
|
||||||
let mut rhs = rhs.clone();
|
|
||||||
lhs.append(&mut rhs);
|
|
||||||
Ok(Value::list(lhs, span))
|
|
||||||
}
|
|
||||||
(Value::List { vals: lhs, .. }, val) => {
|
|
||||||
let mut lhs = lhs.clone();
|
|
||||||
lhs.push(val.clone());
|
|
||||||
Ok(Value::list(lhs, span))
|
|
||||||
}
|
|
||||||
(val, Value::List { vals: rhs, .. }) => {
|
|
||||||
let mut rhs = rhs.clone();
|
|
||||||
rhs.insert(0, val.clone());
|
|
||||||
Ok(Value::list(rhs, span))
|
|
||||||
}
|
}
|
||||||
(Value::String { val: lhs, .. }, Value::String { val: rhs, .. }) => {
|
(Value::String { val: lhs, .. }, Value::String { val: rhs, .. }) => {
|
||||||
Ok(Value::string(lhs.to_string() + rhs, span))
|
Ok(Value::string([lhs.as_str(), rhs.as_str()].join(""), span))
|
||||||
}
|
|
||||||
(Value::Binary { val: lhs, .. }, Value::Binary { val: rhs, .. }) => {
|
|
||||||
let mut val = lhs.clone();
|
|
||||||
val.extend(rhs);
|
|
||||||
Ok(Value::binary(val, span))
|
|
||||||
}
|
}
|
||||||
|
(Value::Binary { val: lhs, .. }, Value::Binary { val: rhs, .. }) => Ok(Value::binary(
|
||||||
|
[lhs.as_slice(), rhs.as_slice()].concat(),
|
||||||
|
span,
|
||||||
|
)),
|
||||||
(Value::Custom { val: lhs, .. }, rhs) => {
|
(Value::Custom { val: lhs, .. }, rhs) => {
|
||||||
lhs.operation(self.span(), Operator::Math(Math::Append), op, rhs)
|
lhs.operation(self.span(), Operator::Math(Math::Concat), op, rhs)
|
||||||
}
|
}
|
||||||
_ => Err(ShellError::OperatorMismatch {
|
_ => Err(ShellError::OperatorMismatch {
|
||||||
op_span: op,
|
op_span: op,
|
||||||
|
@ -37,7 +37,7 @@ def get-all-operators [] { return [
|
|||||||
|
|
||||||
[Assignment, =, Assign, "Assigns a value to a variable.", 10]
|
[Assignment, =, Assign, "Assigns a value to a variable.", 10]
|
||||||
[Assignment, +=, PlusAssign, "Adds a value to a variable.", 10]
|
[Assignment, +=, PlusAssign, "Adds a value to a variable.", 10]
|
||||||
[Assignment, ++=, AppendAssign, "Appends a list or a value to a variable.", 10]
|
[Assignment, ++=, ConcatAssign, "Concatenate two lists, two strings, or two binary values.", 10]
|
||||||
[Assignment, -=, MinusAssign, "Subtracts a value from a variable.", 10]
|
[Assignment, -=, MinusAssign, "Subtracts a value from a variable.", 10]
|
||||||
[Assignment, *=, MultiplyAssign, "Multiplies a variable by a value.", 10]
|
[Assignment, *=, MultiplyAssign, "Multiplies a variable by a value.", 10]
|
||||||
[Assignment, /=, DivideAssign, "Divides a variable by a value.", 10]
|
[Assignment, /=, DivideAssign, "Divides a variable by a value.", 10]
|
||||||
@ -55,7 +55,7 @@ def get-all-operators [] { return [
|
|||||||
[Comparison, ends-with, EndsWith, "Checks if a string ends with another.", 80]
|
[Comparison, ends-with, EndsWith, "Checks if a string ends with another.", 80]
|
||||||
[Comparison, not, UnaryNot, "Negates a value or expression.", 0]
|
[Comparison, not, UnaryNot, "Negates a value or expression.", 0]
|
||||||
[Math, +, Plus, "Adds two values.", 90]
|
[Math, +, Plus, "Adds two values.", 90]
|
||||||
[Math, ++, Append, "Appends two lists or a list and a value.", 80]
|
[Math, ++, Concat, "Concatenate two lists, two strings, or two binary values.", 80]
|
||||||
[Math, -, Minus, "Subtracts two values.", 90]
|
[Math, -, Minus, "Subtracts two values.", 90]
|
||||||
[Math, *, Multiply, "Multiplies two values.", 95]
|
[Math, *, Multiply, "Multiplies two values.", 95]
|
||||||
[Math, /, Divide, "Divides two values.", 95]
|
[Math, /, Divide, "Divides two values.", 95]
|
||||||
|
@ -112,7 +112,7 @@ impl CustomValue for CoolCustomValue {
|
|||||||
) -> Result<Value, ShellError> {
|
) -> Result<Value, ShellError> {
|
||||||
match operator {
|
match operator {
|
||||||
// Append the string inside `cool`
|
// Append the string inside `cool`
|
||||||
ast::Operator::Math(ast::Math::Append) => {
|
ast::Operator::Math(ast::Math::Concat) => {
|
||||||
if let Some(right) = right
|
if let Some(right) = right
|
||||||
.as_custom_value()
|
.as_custom_value()
|
||||||
.ok()
|
.ok()
|
||||||
|
@ -154,7 +154,6 @@ fn const_unary_operator(#[case] inp: &[&str], #[case] expect: &str) {
|
|||||||
#[case(&[r#"const x = "a" ++ "b" "#, "$x"], "ab")]
|
#[case(&[r#"const x = "a" ++ "b" "#, "$x"], "ab")]
|
||||||
#[case(&[r#"const x = [1,2] ++ [3]"#, "$x | describe"], "list<int>")]
|
#[case(&[r#"const x = [1,2] ++ [3]"#, "$x | describe"], "list<int>")]
|
||||||
#[case(&[r#"const x = 0x[1,2] ++ 0x[3]"#, "$x | describe"], "binary")]
|
#[case(&[r#"const x = 0x[1,2] ++ 0x[3]"#, "$x | describe"], "binary")]
|
||||||
#[case(&[r#"const x = 0x[1,2] ++ [3]"#, "$x | describe"], "list<any>")]
|
|
||||||
#[case(&["const x = 1 < 2", "$x"], "true")]
|
#[case(&["const x = 1 < 2", "$x"], "true")]
|
||||||
#[case(&["const x = (3 * 200) > (2 * 100)", "$x"], "true")]
|
#[case(&["const x = (3 * 200) > (2 * 100)", "$x"], "true")]
|
||||||
#[case(&["const x = (3 * 200) < (2 * 100)", "$x"], "false")]
|
#[case(&["const x = (3 * 200) < (2 * 100)", "$x"], "false")]
|
||||||
|
@ -187,7 +187,7 @@ fn record_spread() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn binary_op_example() {
|
fn binary_op_example() {
|
||||||
test_eval(
|
test_eval(
|
||||||
"(([1 2] ++ [3 4]) == [1 2 3 4]) and (([1 2 3] ++ 4) == ([1] ++ [2 3 4]))",
|
"(([1 2] ++ [3 4]) == [1 2 3 4]) and (([1] ++ [2 3 4]) == [1 2 3 4])",
|
||||||
Eq("true"),
|
Eq("true"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user