Skip to content

Commit

Permalink
给重复块添加无限重复, 增加一些内建函数
Browse files Browse the repository at this point in the history
  • Loading branch information
A4-Tacks committed Jan 31, 2025
1 parent 9471c51 commit 198221b
Show file tree
Hide file tree
Showing 15 changed files with 176 additions and 52 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.17.24"
version = "0.18.0"
edition = "2021"

authors = ["A4-Tacks <[email protected]>"]
Expand Down
3 changes: 3 additions & 0 deletions examples/builtin_functions.mdtlbl
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
* * `MetaDebug[]`: 以调试形式输出编译时元数据
* * `MaxExpandDepth[]`: 获取最大展开层数限制
* * `SetMaxExpandDepth[depth]`: 设置最大展开层数限制
* * `RepeatLimit[]`: 获取最大重复块重复次数限制
* * `SetRepeatLimit[limit]`: 设置最大重复块重复次数限制
* * `StopRepeat[]`: 最里层的重复块在本次重复结束后将停止
* * `ExpandStack[]`: 调试输出当前展开栈情况
* * `EvalNum[num]`: 尝试常量计算一个值, 失败则返回`__`
* * `IsString[str]`: 返回给定量是否是一个字符串
Expand Down
4 changes: 4 additions & 0 deletions examples/learn.md
Original file line number Diff line number Diff line change
Expand Up @@ -1262,6 +1262,10 @@ print 1
从编译结果可以看出它的工作原理, `@`符号前面写数量, 数量不足时**依旧会运行**,
如果数量省略不写则默认为`1`

> [!WARNING]
> 重复块的重复次数可以为 0, 那么它将无限的重复,
> 此时需要使用内建函数 StopRepeat 来终止下一轮重复
通常重复块也配合着 match 一起使用, 来取出参数内容, 或者仅关心参数足够时的情况

> [!TIP]
Expand Down
21 changes: 21 additions & 0 deletions examples/match.mdtlbl
Original file line number Diff line number Diff line change
Expand Up @@ -411,3 +411,24 @@ inline*C@ {
foo a b
foo c
*#


# 在0.18.0版本的重复块添加了可以无限重复的功能, 只要在重复次数写0(以前会报错)
# 终止的方式则是使用内建函数 StopRepeat, 调用了它后将不会再次运行当前重复块
# 同时增加了重复次数上限, 防止卡死, 也可以使用内建函数调整上限
take*I = 0;
inline 0@ {
# 考虑到 StopRepeat 不是立即跳出, 而是执行完当前重复不再重复
# 所以match一下, 省得多执行一次
match I { [5] { Builtin.StopRepeat!; } _ {
print I;
take*I = I + 1;
} }
}
#* >>>
print 0
print 1
print 2
print 3
print 4
*#
9 changes: 9 additions & 0 deletions syntax/vim/UltiSnips/mdtlbl.snippets
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ endsnippet
snippet _MaxExpandDepth "Builtin.MaxExpandDepth[]" w
Builtin.MaxExpandDepth[]
endsnippet
snippet _RepeatLimit "Builtin.RepeatLimit[]" w
Builtin.RepeatLimit[]
endsnippet
snippet _EvalNum "Builtin.EvalNum[$1]" w
Builtin.EvalNum[$1]
endsnippet
Expand Down Expand Up @@ -196,6 +199,9 @@ endsnippet
snippet _SetMaxExpandDepth "Builtin.SetMaxExpandDepth! $1;" w
Builtin.SetMaxExpandDepth! $1;
endsnippet
snippet _SetRepeatLimit "Builtin.SetRepeatLimit! $1;" w
Builtin.SetRepeatLimit! $1;
endsnippet
snippet _ExpandStack "Builtin.ExpandStack!;" w
Builtin.ExpandStack!;
endsnippet
Expand All @@ -211,6 +217,9 @@ endsnippet
snippet _SetNoOp "Builtin.SetNoOp! $1;" w
Builtin.SetNoOp! $1;
endsnippet
snippet _StopRepeat "Builtin.StopRepeat! $1;" w
Builtin.StopRepeat!;
endsnippet

# logic
snippet read "read result cell1 0;" w
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.27"
version = "0.3.28"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
2 changes: 1 addition & 1 deletion tools/display_source/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ impl DisplaySource for Args {
impl DisplaySource for ArgsRepeat {
fn display_source(&self, meta: &mut DisplaySourceMeta) {
meta.push("inline");
match self.count() {
match &**self.count() {
Left(n) => {
meta.add_space();
meta.push_fmt(n);
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.28"
version = "0.3.29"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
25 changes: 10 additions & 15 deletions tools/parser/src/parser.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ OOCArgs<T, S>: Vec<T> = {
OpenArgs<T, S>,
CloseArgs<T, S>,
}
Span<T> = @L T @R;
#[inline]
Opt<T>: bool = T? => <>.is_some();
#[inline]
Expand Down Expand Up @@ -519,28 +518,24 @@ ParamArgs: Args = {
},
}
ArgsRepeatBlock: ArgsRepeat = {
<l:@L><chunk:LiteralUInt?><r:@R>
"@" <block:NoPrefixInlineBlock> =>? {
if chunk == Some(0) {
return Err(Error::from((l, Errors::ArgsRepeatChunkByZero, r)).into())
}
Ok(ArgsRepeat::new(chunk.unwrap_or(1), block))
<chunk:Loc<LiteralUInt?>> "@" <block:NoPrefixInlineBlock> =>? {
Ok(ArgsRepeat::new(chunk.map(|n| n.unwrap_or(1)), block))
},
"*" <value:Loc<NonConstRangeValue>> "@" <block:NoPrefixInlineBlock> => {
ArgsRepeat::new_valued(value, block)
},
<l:Loc<"@">> <pats:ConstMatchPatAtom+> <block:NoPrefixInlineBlock> => {
let glob = l.new_value(Args::GLOB_ONLY);
ArgsRepeat::new(pats.len(), vec![
<l:Loc<"@">> <pats:Loc<ConstMatchPatAtom+>> <block:NoPrefixInlineBlock> => {
let glob = pats.new_value(Args::GLOB_ONLY);
ArgsRepeat::new(l.new_value(pats.len()), vec![
ConstMatch::new(glob, vec![
(pats.into(), block),
(pats.value.into(), block),
]).into()
].into())
},
}

Print: LogicLine = "print" <Args?> LEnd => {
let Some(args) = <> else {
Print: LogicLine = <l:Loc<"print">> <args:Args?> LEnd => {
let Some(args) = args else {
// 无参数, 啥也不做
return LogicLine::Ignore
};
Expand All @@ -563,7 +558,7 @@ Print: LogicLine = "print" <Args?> LEnd => {
).into()
},
Args::Expanded(p, s) if p.len() == 0 && s.len() == 0 => {
ArgsRepeat::new(1, vec![
ArgsRepeat::new(l.new_value(1), vec![
LogicLine::Other(Args::Expanded(
vec![ReprVar("print".into())],
vec![],
Expand All @@ -578,7 +573,7 @@ Print: LogicLine = "print" <Args?> LEnd => {
res.push(one(arg))
}

res.push(ArgsRepeat::new(1, vec![
res.push(ArgsRepeat::new(l.new_value(1), vec![
LogicLine::Other(Args::Expanded(vec![
ReprVar("print".into()),
], vec![]))
Expand Down
2 changes: 1 addition & 1 deletion tools/parser/tests/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "parser-tests"
version = "0.1.49"
version = "0.1.50"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
45 changes: 43 additions & 2 deletions tools/parser/tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4807,6 +4807,26 @@ fn match_test() {
],
);

assert_eq!(
CompileMeta::new().compile(parse!(parser, r#"
const C = 1;
match a b c { @{} }
inline*C@{
foo @;
Builtin.StopRepeat!;
}
print end;
print @;
"#).unwrap()).compile().unwrap(),
vec![
"foo a",
"print end",
"print a",
"print b",
"print c",
],
);

assert_eq!(
CompileMeta::new().compile(parse!(parser, r#"
const C = 2;
Expand Down Expand Up @@ -5319,8 +5339,9 @@ fn match_test() {

assert_eq!(
parse!(parser, r#"
# align.............
inline@ A B *C {
inline@ # align .....
A B *C
{
print A B C;
}
"#).unwrap(),
Expand Down Expand Up @@ -6088,6 +6109,26 @@ fn const_match_test() {
"print _0",
],
);

// 无限重复块
assert_eq!(
CompileMeta::new().compile(parse!(parser, r#"
take*I = 0;
inline 0@ {
match I { [5] { Builtin.StopRepeat!; } _ {
print I;
take*I = I + 1;
} }
}
"#).unwrap()).compile().unwrap(),
vec![
"print 0",
"print 1",
"print 2",
"print 3",
"print 4",
],
);
}

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

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
26 changes: 25 additions & 1 deletion tools/syntax/src/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,31 @@ pub fn build_builtins() -> Vec<BuiltinFunc> {
})
}

fn stop_repeat:StopRepeat(meta) [] {
let Some(flag) = meta.args_repeat_flags.last_mut() else {
return Err((2, format!("Not in repeat block")))
};
*flag = false;
Ok("__".into())
}

fn repeat_limit:RepeatLimit(meta) [] {
Ok(meta.args_repeat_limit().to_string().into())
}

fn set_repeat_limit:SetRepeatLimit(meta) [d:limit] {
check_type!("var" Value::Var(limit) = limit.value() => {
let limit: usize = match limit.parse() {
Ok(n) => n,
Err(e) => {
return Err((2, e.to_string()))
},
};
meta.set_args_repeat_limit(limit);
Ok("__".into())
})
}

fn expand_stack:ExpandStack(meta) [] {
meta.log_expand_stack::<false>();
Ok("__".into())
Expand Down Expand Up @@ -427,7 +452,6 @@ pub fn build_builtins() -> Vec<BuiltinFunc> {
Ok("__".into())
})
}

fn bind_sep:BindSep(meta) [v:sep] {
check_type!("var" Value::Var(sep) = sep.value() => {
match sep.as_var_type().as_string() {
Expand Down
Loading

0 comments on commit 198221b

Please sign in to comment.