Skip to content

Commit 1b567c1

Browse files
committed
增加op-expr, 这是我们更加熟悉的表达形式, 它使复杂计算也更加干练
1 parent 416acde commit 1b567c1

File tree

6 files changed

+379
-23
lines changed

6 files changed

+379
-23
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mindustry_logic_bang_lang"
3-
version = "0.10.6"
3+
version = "0.11.0"
44
edition = "2021"
55

66
authors = ["A4-Tacks <wdsjxhno1001@163.com>"]

examples/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
> [`print.mdtlbl`](./print.mdtlbl)<br/>
1010
> [`sets.mdtlbl`](./sets.mdtlbl)<br/>
1111
> [`op.mdtlbl`](./op.mdtlbl)<br/>
12+
> [`op_expr.mdtlbl`](./op_expr.mdtlbl)<br/>
1213
> [`control.mdtlbl`](./control.mdtlbl)<br/>
1314
> [`cmps.mdtlbl`](./cmps.mdtlbl)<br/>
1415
> [`insert_sort.mdtlbl`](./insert_sort.mdtlbl)<br/>

examples/op_expr.mdtlbl

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#**
2+
* 这是在0.11.0版本添加的表达式系统, 旨在更加干练的编写复杂运算
3+
* 可以有限的以我们比较常见的表达式形式使用op来进行运算
4+
* 这个语法可以看成在对sets左值为单个时的行为扩展
5+
* 在sets左值为单个Value时, 右值将成为一个op-expr
6+
*
7+
* 以下为各种运算符的优先级与结合性:
8+
* | 符号 | 实际运算(op) | 优先级 | 结合性 |
9+
* | --------- | ------------ | ------ | ------ |
10+
* | `a ** b` | `a ** b` | -1 | RL |
11+
* | `! x` | `x != false` | -2 | R |
12+
* | `- x` | `0 - x` | -2 | R |
13+
* | `~ x` | `~ x` | -2 | R |
14+
* | `a * b` | `a * b` | -3 | LR |
15+
* | `a / b` | `a / b` | -3 | LR |
16+
* | `a % b` | `a % b` | -3 | LR |
17+
* | `a // b` | `a // b` | -3 | LR |
18+
* | `a + b` | `a + b` | -4 | LR |
19+
* | `a - b` | `a - b` | -4 | LR |
20+
* | `a << b` | `a << b` | -5 | LR |
21+
* | `a >> b` | `a >> b` | -5 | LR |
22+
* | `a & b` | `a & b` | -6 | LR |
23+
* | `a ^ b` | `a ^ b` | -7 | LR |
24+
* | `a | b` | `a | b` | -8 | LR |
25+
* | `a == b` | `a == b` | -9 | LR |
26+
* | `a != b` | `a != b` | -9 | LR |
27+
* | `a < b` | `a < b` | -9 | LR |
28+
* | `a > b` | `a > b` | -9 | LR |
29+
* | `a <= b` | `a <= b` | -9 | LR |
30+
* | `a >= b` | `a >= b` | -9 | LR |
31+
* | `a === b` | `a === b` | -9 | LR |
32+
* | `a && b` | `a && b` | -10 | LR |
33+
* | `a || b` | `a + b` | -11 | LR |
34+
*
35+
* 以上表格外, 还有一元与二元函数(其实就是op)
36+
* 它们的优先级与括号平级,
37+
* 二元函数有: `max` `min` `angle` `len` `noise`,
38+
* 一元函数的部分列举有: `log` `rand` ...,
39+
*
40+
* 具体参考op中没有符号的运算
41+
*#
42+
43+
x = 1 + 2 * 3;
44+
y = (1 + 2) * 3;
45+
z = min(a+b, c-d);
46+
#* A >>>
47+
op 'x' '1' + (op $ '2' * '3';);
48+
op 'y' (op $ '1' + '2';) * '3';
49+
op 'z' min (op $ 'a' + 'b';) (op $ 'c' - 'd';);
50+
*#
51+
# 我们可以看出, 优先级生效了, 并且运算被正常解析为DExp树了
52+
# 并且我们并没有遇到最后要经历一遭set的问题, 因为解析时有一个安全标记
53+
# 这个标记将使我们可以正确的将op与set合并.
54+
#
55+
# 当然, 需要注意的是,
56+
# 虽然运算成员是Value, 但依旧不推荐使用`$`符号(返回句柄替换符)
57+
# 因为这并没有什么意义, 且如果在最外层, 那么因为最顶层op与set的合并,
58+
# 这个句柄将会指向set的更外层的DExp.

src/syntax.rs

Lines changed: 134 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,14 @@ impl DExp {
290290
lines
291291
}
292292
}
293+
294+
pub fn result(&self) -> &str {
295+
self.result.as_ref()
296+
}
297+
298+
pub fn lines(&self) -> &Expand {
299+
&self.lines
300+
}
293301
}
294302
impl TakeHandle for DExp {
295303
fn take_handle(self, meta: &mut CompileMeta) -> Var {
@@ -351,6 +359,7 @@ impl DisplaySource for DExp {
351359
meta.push(")");
352360
}
353361
}
362+
impl_derefs!(impl for DExp => (self: self.lines): Expand);
354363

355364
/// 将一个Value与一个Var以特定格式组合起来,
356365
/// 可完成如属性调用的功能
@@ -442,15 +451,9 @@ impl Meta {
442451
/// 如果只有一个值与被赋值则与之前行为一致
443452
/// 如果值与被赋值数量不匹配则返回错误
444453
/// 如果值与被赋值数量匹配且大于一对就返回Expand中多个set
445-
pub fn build_sets(&self, loc: [Location; 2], mut vars: Vec<Value>, mut values: Vec<Value>)
454+
pub fn build_sets(loc: [Location; 2], mut vars: Vec<Value>, mut values: Vec<Value>)
446455
-> Result<LogicLine, Error> {
447-
fn build_set(var: Value, value: Value) -> LogicLine {
448-
LogicLine::Other(vec![
449-
Value::ReprVar("set".into()),
450-
var,
451-
value,
452-
])
453-
}
456+
let build_set = Self::build_set;
454457
if vars.len() != values.len() {
455458
// 接受与值数量不匹配
456459
return Err((
@@ -475,6 +478,15 @@ impl Meta {
475478
Ok(Expand(expand).into())
476479
}
477480
}
481+
482+
/// 单纯的构建一个set语句
483+
pub fn build_set(var: Value, value: Value) -> LogicLine {
484+
LogicLine::Other(vec![
485+
Value::ReprVar("set".into()),
486+
var,
487+
value,
488+
])
489+
}
478490
}
479491

480492
pub trait FromMdtArgs
@@ -1018,6 +1030,50 @@ impl Op {
10181030
}
10191031
}
10201032

1033+
pub fn get_result(&self) -> &Value {
1034+
macro_rules! build_match {
1035+
{
1036+
$(
1037+
$variant:ident
1038+
),* $(,)?
1039+
} => {
1040+
match self {
1041+
$( Self::$variant(res, ..) => res ),*
1042+
}
1043+
};
1044+
}
1045+
build_match! {
1046+
Add, Sub, Mul, Div, Idiv, Mod, Pow,
1047+
Equal, NotEqual, Land, LessThan, LessThanEq, GreaterThan, GreaterThanEq,
1048+
StrictEqual, Shl, Shr, Or, And, Xor, Not,
1049+
Max, Min, Angle, Len, Noise, Abs, Log,
1050+
Log10, Floor, Ceil, Sqrt, Rand, Sin, Cos,
1051+
Tan, Asin, Acos, Atan,
1052+
}
1053+
}
1054+
1055+
pub fn get_result_mut(&mut self) -> &mut Value {
1056+
macro_rules! build_match {
1057+
{
1058+
$(
1059+
$variant:ident
1060+
),* $(,)?
1061+
} => {
1062+
match self {
1063+
$( Self::$variant(res, ..) => res ),*
1064+
}
1065+
};
1066+
}
1067+
build_match! {
1068+
Add, Sub, Mul, Div, Idiv, Mod, Pow,
1069+
Equal, NotEqual, Land, LessThan, LessThanEq, GreaterThan, GreaterThanEq,
1070+
StrictEqual, Shl, Shr, Or, And, Xor, Not,
1071+
Max, Min, Angle, Len, Noise, Abs, Log,
1072+
Log10, Floor, Ceil, Sqrt, Rand, Sin, Cos,
1073+
Tan, Asin, Acos, Atan,
1074+
}
1075+
}
1076+
10211077
pub fn oper_symbol_str(&self) -> &'static str {
10221078
macro_rules! build_match {
10231079
{
@@ -1651,6 +1707,14 @@ impl LogicLine {
16511707
}
16521708
}
16531709

1710+
pub fn as_op_mut(&mut self) -> Option<&mut Op> {
1711+
if let Self::Op(v) = self {
1712+
Some(v)
1713+
} else {
1714+
None
1715+
}
1716+
}
1717+
16541718
/// Returns `true` if the logic line is [`Label`].
16551719
///
16561720
/// [`Label`]: LogicLine::Label
@@ -2201,6 +2265,14 @@ pub fn mdt_logic_split(s: &str) -> Result<Vec<&str>, usize> {
22012265
Ok(res)
22022266
}
22032267

2268+
pub type OpExprInfo = (bool, Value);
2269+
2270+
pub fn op_expr_do<F>(f: F) -> OpExprInfo
2271+
where F: FnOnce() -> Op
2272+
{
2273+
(true, DExp::new_nores(vec![f().into()].into()).into())
2274+
}
2275+
22042276
#[cfg(test)]
22052277
mod tests {
22062278
use std::str::FromStr;
@@ -4322,4 +4394,58 @@ mod tests {
43224394
);
43234395
}
43244396
}
4397+
4398+
#[test]
4399+
fn op_expr_test() {
4400+
let parser = ExpandParser::new();
4401+
4402+
assert_eq!(
4403+
parse!(parser, r#"
4404+
x = max(1, 2);
4405+
y = max(max(1, 2), max(3, max(4, 5)));
4406+
"#).unwrap(),
4407+
parse!(parser, r#"
4408+
op x max 1 2;
4409+
op y max (op $ max 1 2;) (op $ max 3 (op $ max 4 5;););
4410+
"#).unwrap(),
4411+
);
4412+
4413+
assert_eq!(
4414+
parse!(parser, r#"
4415+
x = 1+2*3;
4416+
y = (1+2)*3;
4417+
z = 1+2+3;
4418+
"#).unwrap(),
4419+
parse!(parser, r#"
4420+
op x 1 + (op $ 2 * 3;);
4421+
op y (op $ 1 + 2;) * 3;
4422+
op z (op $ 1 + 2;) + 3;
4423+
"#).unwrap(),
4424+
);
4425+
4426+
assert_eq!(
4427+
parse!(parser, r#"
4428+
x = 1*max(2, 3);
4429+
y = a & b | c & d & e | f;
4430+
"#).unwrap(),
4431+
parse!(parser, r#"
4432+
op x 1 * (op $ max 2 3;);
4433+
op y (op $ (op $ a & b;) | (op $ (op $ c & d;) & e;);) | f;
4434+
"#).unwrap(),
4435+
);
4436+
4437+
assert_eq!(
4438+
parse!(parser, r#"
4439+
x = a**b**c; # pow的右结合
4440+
y = -x;
4441+
z = ~y;
4442+
"#).unwrap(),
4443+
parse!(parser, r#"
4444+
op x a ** (op $ b ** c;);
4445+
op y `0` - x;
4446+
op z ~y;
4447+
"#).unwrap(),
4448+
);
4449+
4450+
}
43254451
}

0 commit comments

Comments
 (0)