Skip to content

Commit

Permalink
强化OpExpr, 使得一个值可以一次赋给多个接收者
Browse files Browse the repository at this point in the history
  • Loading branch information
A4-Tacks committed Oct 19, 2023
1 parent 6fd7afd commit ac8dda4
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 24 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mindustry_logic_bang_lang"
version = "0.12.6"
version = "0.12.7"
edition = "2021"

authors = ["A4-Tacks <[email protected]>"]
Expand Down
17 changes: 17 additions & 0 deletions examples/op_expr.mdtlbl
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,20 @@ op 'x' '1' + (
);
*#
# 由于前面解释过的原因, 你需要添加括号


# 这是0.12.7版本添加的语法, 可以将一个值一次赋给多个接收者
# 方法是使用首次赋值的值来为接下来赋值
#
# 需要注意的是, 求值顺序是:
# 第一个接收者 -> 值 -> 第二个接收者 -> ... -> 第N个接收者

a, b, c = 1 + 2 * 3;
#* A >>>
{
take ___0 = a;
op ___0 1 + (op $ 2 * 3;);
`'set'` b ___0;
`'set'` c ___0;
}
*#
50 changes: 28 additions & 22 deletions src/syntax/def.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use crate::syntax::{
DExp,
ValueBind,
op_expr_build_op,
op_expr_build_results,
OpExprInfo,
JumpCmp,
CmpTree,
Expand Down Expand Up @@ -58,12 +59,12 @@ MTuple<T> = Wrap<"(", T, ")">;
MList<T> = Wrap<"[", T, "]">;
MBlock<T> = Wrap<"{", T, "}">;
OpenArgs<T, S> = (<T> S)*; // 零至多个有分隔后缀值
CloseArgs<T, S> = (<T> S)* T => { // 一至多个有分隔无后缀值
CloseArgs<T, S>: Vec<T> = OpenArgs<T, S> T => { // 一至多个有分隔无后缀值
let (mut args, tail) = <>;
args.push(tail);
args
};
OOCArgs<T, S> = {
OOCArgs<T, S>: Vec<T> = {
OpenArgs<T, S>,
CloseArgs<T, S>,
}
Expand Down Expand Up @@ -319,30 +320,35 @@ Args2: Vec<Value> = {
Value Value Value Value Value Value Value Value Value Value Value Value Value Value Value => vec![<>],
}

OpExpr: LogicLine = <OpExprDoMultiple> LEnd => {
let (mut results, values) = <>;
results.reverse();
assert_eq!(results.len(), values.len());

let mut lines = Vec::with_capacity(results.len());

let ziped = results.into_iter().zip(values);
for (result, value) in ziped {
let line = value.into_logic_line(meta, result);
lines.push(line)
}
OpExpr: LogicLine = {
<OpExprMultipleResult> LEnd => {
let (mut results, value) = <>;
results.reverse();
op_expr_build_results(meta, results, vec![value])
},
<OpExprDoMultiple> LEnd => {
let (mut results, values) = <>;
results.reverse();
op_expr_build_results(meta, results, values)
},
}

assert!(! lines.is_empty());
if lines.len() == 1 {
lines.pop().unwrap()
} else {
Expand(lines).into()
}
};
// 多个接收者的OpExpr, 例如`a, b, c = 1;`
OpExprMultipleResult: (Vec<Value>, OpExprInfo) = {
<result:Value> "=" <value:OpExprBody> => {
(vec![result], value)
},
<result:Value> "," <body:OpExprMultipleResult> => {
let (mut results, value) = body;
results.push(result);
(results, value)
},
}

// 例如`a, b = 1, 2`返回`([b, a], [1, 2])`
OpExprDoMultiple: (Vec<Value>, Vec<OpExprInfo>) = {
<result:Value> "=" <value:OpExprBody> => (vec![result], vec![value]),
<res1:Value> "," <res2:Value> "=" <val1:OpExprBody> "," <val2:OpExprBody>
=> (vec![res2, res1], vec![val1, val2]),
<result:Value> "," <mut mid:OpExprDoMultiple> "," <value:OpExprBody> => {
let (results, values) = &mut mid;
results.push(result);
Expand Down
49 changes: 49 additions & 0 deletions src/syntax/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2583,6 +2583,55 @@ where F: FnOnce() -> Op
{
f().into()
}
pub fn op_expr_build_results(
meta: &mut Meta,
mut results: Vec<Value>,
mut values: Vec<OpExprInfo>,
) -> LogicLine {
match (results.len(), values.len()) {
e @ ((0, _) | (_, 0)) => unreachable!("len by zero, {e:?}"),
(1, 1) => {
let (result, value) = (
results.pop().unwrap(),
values.pop().unwrap(),
);
value.into_logic_line(meta, result)
},
(len, 1) => {
let mut lines = Vec::with_capacity(len + 1);
let value = values.pop().unwrap();
let mut results = results.into_iter();
let first_result_handle = meta.get_tmp_var();
lines.push(Take(
first_result_handle.clone(), results.next().unwrap()
).into());
lines.push(value.into_logic_line(
meta,
first_result_handle.clone().into()
));
for result in results {
let value
= OpExprInfo::Value(first_result_handle.clone().into());
lines.push(value.into_logic_line(meta, result.clone()))
}
assert_eq!(lines.len(), len + 1);
Expand(lines).into()
},
(res_len, val_len) => {
assert_eq!(res_len, val_len);

let mut lines = Vec::with_capacity(res_len);
let ziped
= results.into_iter().zip(values);

for (result, value) in ziped {
let line = value.into_logic_line(meta, result);
lines.push(line)
}
Expand(lines).into()
},
}
}

#[cfg(test)]
mod tests;
14 changes: 14 additions & 0 deletions src/syntax/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2221,6 +2221,20 @@ fn op_expr_test() {
"#).unwrap(),
);

assert_eq!(
parse!(parser, r#"
a, b, c = 1;
"#).unwrap(),
parse!(parser, r#"
{
take ___0 = a;
___0 = 1;
b = ___0;
c = ___0;
}
"#).unwrap(),
);

}

#[test]
Expand Down

0 comments on commit ac8dda4

Please sign in to comment.