Skip to content

Commit

Permalink
添加gswitch语法, 可以很好的和常量系统交互, 并且拥有匹配守卫
Browse files Browse the repository at this point in the history
  • Loading branch information
A4-Tacks committed May 7, 2024
1 parent 80f4b48 commit 26a72f0
Show file tree
Hide file tree
Showing 15 changed files with 971 additions and 24 deletions.
10 changes: 5 additions & 5 deletions 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.16.2"
version = "0.16.3"
edition = "2021"

authors = ["A4-Tacks <[email protected]>"]
Expand Down
1 change: 1 addition & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
> [`switch_append.mdtlbl`](./switch_append.mdtlbl)<br/>
> [`switch_catch.mdtlbl`](./switch_catch.mdtlbl)<br/>
> [`take2.mdtlbl`](./take2.mdtlbl)<br/>
> [`gswitch.mdtlbl`](./gswitch.mdtlbl)<br/>
> [`mul_takes_and_consts.mdtlbl`](./mul_takes_and_consts.mdtlbl)<br/>
> [`cmper.mdtlbl`](./cmper.mdtlbl)<br/>
> [`setres.mdtlbl`](./setres.mdtlbl)<br/>
Expand Down
167 changes: 167 additions & 0 deletions examples/gswitch.mdtlbl
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
#**
* 这是0.16.3版本新增的语法, 主要是解决switch无法和常量还有参数系统交互的问题
* 并且更加强大, 拥有匹配守卫, 并且对于不同的值到同一块代码并不会有过多的代码重复
*
* 它的结构始终是jump跳转到代码的表.
* 由于它始终采用跳转表式, 所以它的穿透也将与case声明顺序相同.
* 它的跳转表是使用select原语构建的, 方便且偷懒
*
* 需要注意的是, 它对于为指定失配时的行为和普通switch不同,
* 它会直接跳过整个gswitch, 而不是采用append
*
* 它的catchs和switch的很像, 但是其代码体和其它case的在一起,
* 这可以很符合直觉的穿透
*
* 没有设计同时匹配catch和普通case的语法, 这或许是一个遗憾, 但是真的不想实现它
* 当然, 你可以舍弃常用的简单的向append中编写break的语法, 直接穿透到它那里.
*
* 它还拥有匹配守卫, 可以在普通的匹配后面增加一个if加上比较条件,
* 将仅在成立时执行这个case.
* 当然不设计为为同一个case中每个匹配使用不同的守卫支持, 也是类似上面的原因.
* 实在要使用也可以使用类似上面的解决方法
*#

# 一个例子
const Foo = 0;
const Bar = 2;
x = Bar;
y = 2;
gswitch x {
break;
case Foo if y < 1:
print "Foo && y<1";
case Foo:
print "Foo";
case Bar:
print "Bar";
}

#* >>>
set x 2
set y 2
op mul __1 x 2
op add @counter @counter __1
jump 10 lessThan y 1
jump 12 always 0 0
jump 0 always 0 0
jump 14 always 0 0
jump 14 always 0 0
jump 10 always 0 0
print "Foo && y<1"
jump 0 always 0 0
print "Foo"
jump 0 always 0 0
print "Bar"
jump 0 always 0 0
*#


# 使用catch的例子
gswitch x {
break;
case 0: print "0";
case ! X: print X": missed";
case 1: print "1";
}
end;
#* >>>
op add @counter @counter x
jump 3 always 0 0
jump 8 always 0 0
print "0"
jump 10 always 0 0
print x
print ": missed"
jump 10 always 0 0
print "1"
jump 10 always 0 0
end
*#


# 这种只有一个分支的, 会触发select的优化, 所以看着怪怪的
gswitch x {
break;
case 0: print "0";
case ! X: print X": missed";
}
#* >>>
jump 1 always 0 0
print "0"
jump 1 always 0 0
print x
print ": missed"
jump 1 always 0 0
*#


# 同时使用多个匹配的情况
gswitch x {
break;
case 1 2 3 4: print "1 or 2 or 3 or 4"a","b","c;
case ! X: print X": missed";
}
#* >>>
op add @counter @counter x
jump 13 always 0 0
jump 6 always 0 0
jump 6 always 0 0
jump 6 always 0 0
jump 6 always 0 0
print "1 or 2 or 3 or 4"
print a
print ","
print b
print ","
print c
jump 0 always 0 0
print x
print ": missed"
jump 0 always 0 0
*#
# 我们和switch比对一下
switch x {
break;
case !: print ": missed";
case 1 2 3 4: print "1 or 2 or 3 or 4"a","b","c;
}
#* >>>
jump 2 always 0 0
print ": missed"
op add @counter @counter x
jump 1 always 0 0
jump 9 always 0 0
jump 16 always 0 0
jump 23 always 0 0
jump 30 always 0 0
jump 1 always 0 0
print "1 or 2 or 3 or 4"
print a
print ","
print b
print ","
print c
jump 2 always 0 0
print "1 or 2 or 3 or 4"
print a
print ","
print b
print ","
print c
jump 2 always 0 0
print "1 or 2 or 3 or 4"
print a
print ","
print b
print ","
print c
jump 2 always 0 0
print "1 or 2 or 3 or 4"
print a
print ","
print b
print ","
print c
jump 2 always 0 0
*#
# 显然, gswitch很好的解决了这个问题
7 changes: 6 additions & 1 deletion syntax/vim/mdtlbl.snippets
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,13 @@ switch $1 {
$0
}
endsnippet
snippet gswitch "gswitch" w
gswitch $1 {
$0
}
endsnippet
snippet case "switch-case" w
case ${1:0}:$0
case ${1}:$0
endsnippet
snippet op "op result a + b;" w
op ${1:result} ${2:a} ${3:+} ${4:b};$0
Expand Down
6 changes: 5 additions & 1 deletion syntax/vim/mdtlbl.vim
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ syn case match

" 一些关键字 {{{1
syn keyword mdtlblKeyword
\ while gwhile do skip goto if elif else switch case break continue
\ while gwhile do skip goto if elif else switch gswitch case break continue
\ const take setres select match
\ inline
\ op set noop print
Expand Down Expand Up @@ -72,6 +72,10 @@ syn match mdtlblQuickDExpTakeIdent /\I\i*\%(\[\)\@=/
syn match mdtlblQuickDExpTakeIdent /'[^' \t]\+'\%(\[\)\@=/
syn match mdtlblQuickDExpTakeIdent /->/
syn match mdtlblIdentLabel /:\I\i*/
syn match mdtlblIdentLabel /:@\I\i*\%(-\i*\)*/
syn match mdtlblIdentLabel /:'[^' \t]\+'/
syn match mdtlblIdentLabel /:\v0%(x-=%(_)@![0-9a-fA-F_]+|x-=%(_)@![01_]+)/
syn match mdtlblIdentLabel /:\v-=%(_)@![0-9_]+/

" Fold {{{1
setlocal foldmethod=syntax
Expand Down
2 changes: 1 addition & 1 deletion tools/display_source/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "display_source"
version = "0.3.12"
version = "0.3.13"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
64 changes: 64 additions & 0 deletions tools/display_source/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ impl DisplaySource for LogicLine {
Self::Goto(goto) => goto.display_source(meta),
Self::Op(op) => op.display_source(meta),
Self::Select(select) => select.display_source(meta),
Self::GSwitch(gswitch) => gswitch.display_source(meta),
Self::Take(take) => take.display_source(meta),
Self::Const(r#const) => r#const.display_source(meta),
Self::ConstLeak(var) => {
Expand Down Expand Up @@ -632,6 +633,69 @@ impl DisplaySource for ConstMatch {
meta.push("}");
}
}
impl DisplaySource for GSwitchCase {
fn display_source(&self, meta: &mut DisplaySourceMeta) {
match self {
&Self::Catch {
underflow,
missed,
overflow,
ref to,
} => {
meta.add_space();
if underflow {
meta.push("<");
}
if missed {
meta.push("!")
}
if overflow {
meta.push(">")
}
if let Some(key) = to {
meta.add_space();
key.display_source(meta);
}
},
Self::Normal { ids, guard } => {
if !ids.as_normal().map(Vec::is_empty).unwrap_or_default() {
meta.add_space();
ids.display_source(meta);
}
if let Some(guard) = guard {
meta.add_space();
meta.push("if");
meta.add_space();
guard.display_source(meta);
}
},
}
}
}
impl DisplaySource for GSwitch {
fn display_source(&self, meta: &mut DisplaySourceMeta) {
meta.push("gswitch");
meta.add_space();
self.value.display_source(meta);
meta.add_space();
meta.push("{");
meta.add_lf();
meta.do_block(|meta| {
self.extra.display_source(meta);
meta.add_lf();
});
for (case, expand) in &self.cases {
meta.push("case");
case.display_source(meta);
meta.push(":");
meta.add_lf();
meta.do_block(|meta| {
expand.display_source(meta);
})
}
meta.push("}");
}
}

#[cfg(test)]
#[test]
Expand Down
2 changes: 1 addition & 1 deletion tools/parser/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "parser"
version = "0.3.9"
version = "0.3.10"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
Loading

0 comments on commit 26a72f0

Please sign in to comment.