Skip to content

Commit

Permalink
使op-expr也可以像sets一样多对多赋值
Browse files Browse the repository at this point in the history
  • Loading branch information
A4-Tacks committed Aug 25, 2023
1 parent c11694d commit 4b61ec2
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 17 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.11.1"
version = "0.11.2"
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 @@ -56,3 +56,20 @@ op 'z' min (op $ 'a' + 'b';) (op $ 'c' - 'd';);
# 虽然运算成员是Value, 但依旧不推荐使用`$`符号(返回句柄替换符)
# 因为这并没有什么意义, 且如果在最外层, 那么因为最顶层op与set的合并,
# 这个句柄将会指向set的更外层的DExp.


# 在0.11.2版本起, 我们可以像sets一样, 同时进行多个
a, b, c = x, -y, z+2*3;
#* A >>>
{
`'set'` 'a' 'x';
op 'b' `'0'` - 'y';
op 'c' 'z' + (op $ '2' * '3';);
}
*#
# 可以看到, 就像sets一样, 只不过使用逗号分隔了.
# 对于多个简易运算, 我们不用写在多行或者使用额外一个set来换取写在一行中了
# 当然, 运算之外的例如sensor还是不能这么做,
# 因为op-expr的内联set目前仅为它自己的op服务
#
# 起码我们在数学运算方面的舒适度上来了不是吗
55 changes: 55 additions & 0 deletions src/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,48 @@ impl Meta {
value,
])
}

/// 单纯的构建一个OpExpr
pub fn build_op_expr(var: Value, (do_inline, mut value): OpExprInfo)
-> LogicLine {
if do_inline {
// 将Op内联过来, 而不是构建一个set
let dexp = value
.as_dexp_mut().unwrap();
assert_eq!(dexp.len(), 1);
assert!(dexp[0].is_op());
assert_eq!(dexp[0].as_op().unwrap().get_result(), &Value::ResultHandle);
let mut op_line = dexp.pop().unwrap();
*op_line.as_op_mut().unwrap().get_result_mut() = var;
op_line
} else {
Meta::build_set(var, value)
}
}

/// 构建可能同时有多对的OpExpr
pub fn build_op_exprs(mut vars: Vec<Value>, mut values: Vec<OpExprInfo>) -> LogicLine {
assert_eq!(vars.len(), values.len());
assert!(! vars.is_empty());
let len = vars.len();
if len == 1 {
Self::build_op_expr(vars.pop().unwrap(), values.pop().unwrap())
} else {
Expand(
vars.into_iter()
.zip(values)
.map(|(var, value)|
Self::build_op_expr(var, value)
)
.fold(
Vec::with_capacity(len),
|mut lines, line| {
lines.push(line);
lines
})
).into()
}
}
}

pub trait FromMdtArgs
Expand Down Expand Up @@ -4481,6 +4523,19 @@ mod tests {
"#).unwrap(),
);

assert_eq!(
parse!(parser, r#"
a, b, c = x, -y, z+2*3;
"#).unwrap(),
parse!(parser, r#"
{
a = x;
b = -y;
c = z+2*3;
}
"#).unwrap(),
);

}

#[test]
Expand Down
30 changes: 15 additions & 15 deletions src/syntax_def.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -285,23 +285,23 @@ Args2: Vec<Value> = {
Value Value Value Value Value Value Value Value Value Value Value Value Value Value Value => vec![<>],
}

OpExpr: LogicLine = <var:Value> "=" <value:OpExprBody> LEnd => {
let (do_inline, mut value) = value;
if do_inline {
// 将Op内联过来, 而不是构建一个set
assert_eq!(value.as_dexp().unwrap().len(), 1);
assert!(value.as_dexp().unwrap()[0].is_op());
assert_eq!(value.as_dexp().unwrap()[0].as_op().unwrap().get_result(), &ResultHandle);
let mut op_line = value
.as_dexp_mut().unwrap()
.pop().unwrap();
*op_line.as_op_mut().unwrap().get_result_mut() = var;
op_line
} else {
Meta::build_set(var, value)
}
OpExpr: LogicLine = <OpExprDoMultiple> LEnd => {
let (mut vars, values) = <>;
vars.reverse();
Meta::build_op_exprs(vars, values)
};

// 例如`a, b = 1, 2`返回`([b, a], [1, 2])`
OpExprDoMultiple: (Vec<Value>, Vec<OpExprInfo>) = {
<var:Value> "=" <value:OpExprBody> => (vec![var], vec![value]),
<var:Value> "," <mut mid:OpExprDoMultiple> "," <value:OpExprBody> => {
let (ref mut vars, ref mut values) = mid;
vars.push(var);
values.push(value);
mid
},
}

OpExprBody: OpExprInfo = OpExprBody11;

OpExprBody11: OpExprInfo = {
Expand Down

0 comments on commit 4b61ec2

Please sign in to comment.