From 00f97832e57cd28c436dc3025bddd7da562c1d4c Mon Sep 17 00:00:00 2001 From: A4-Tacks Date: Sat, 18 May 2024 21:07:12 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=99cmper=E7=9A=84=E5=86=85=E8=81=94,=20?= =?UTF-8?q?=E5=9C=A8=E6=9E=84=E5=BB=BA=E6=97=B6=E8=BF=9B=E8=A1=8C=E5=B1=95?= =?UTF-8?q?=E5=BC=80=E7=9A=84=E5=BF=85=E8=A6=81=E6=93=8D=E4=BD=9C,=20?= =?UTF-8?q?=E7=BB=91=E5=AE=9A=E5=8F=A5=E6=9F=84=E7=AD=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 8 +-- Cargo.toml | 2 +- tools/display_source/Cargo.toml | 2 +- tools/display_source/src/impls.rs | 3 ++ tools/parser/tests/Cargo.toml | 2 +- tools/parser/tests/src/lib.rs | 83 +++++++++++++++++++++++++++++++ tools/syntax/Cargo.toml | 2 +- tools/syntax/src/lib.rs | 51 ++++++++++++++----- 8 files changed, 132 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 93984d6..5dfc1c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -100,7 +100,7 @@ dependencies = [ [[package]] name = "display_source" -version = "0.3.18" +version = "0.3.19" dependencies = [ "parser", "syntax", @@ -301,7 +301,7 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "mindustry_logic_bang_lang" -version = "0.16.11" +version = "0.16.12" dependencies = [ "display_source", "logic_lint", @@ -358,7 +358,7 @@ dependencies = [ [[package]] name = "parser-tests" -version = "0.1.26" +version = "0.1.27" dependencies = [ "parser", "syntax", @@ -535,7 +535,7 @@ dependencies = [ [[package]] name = "syntax" -version = "0.2.30" +version = "0.2.31" dependencies = [ "either", "tag_code", diff --git a/Cargo.toml b/Cargo.toml index a4e1168..1c0ad03 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mindustry_logic_bang_lang" -version = "0.16.11" +version = "0.16.12" edition = "2021" authors = ["A4-Tacks "] diff --git a/tools/display_source/Cargo.toml b/tools/display_source/Cargo.toml index c1abd81..110fb0f 100644 --- a/tools/display_source/Cargo.toml +++ b/tools/display_source/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "display_source" -version = "0.3.18" +version = "0.3.19" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tools/display_source/src/impls.rs b/tools/display_source/src/impls.rs index e6a85af..c183bd2 100644 --- a/tools/display_source/src/impls.rs +++ b/tools/display_source/src/impls.rs @@ -245,6 +245,9 @@ impl DisplaySource for CmpTree { cmp.display_source(meta); meta.push(")"); }, + Self::Expand(..) => { + unreachable!("应只在build处理过程中使用的变体, 所以不可能达到") + }, Self::Or(a, b) => { meta.push("("); a.display_source(meta); diff --git a/tools/parser/tests/Cargo.toml b/tools/parser/tests/Cargo.toml index 9021466..228f049 100644 --- a/tools/parser/tests/Cargo.toml +++ b/tools/parser/tests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "parser-tests" -version = "0.1.26" +version = "0.1.27" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tools/parser/tests/src/lib.rs b/tools/parser/tests/src/lib.rs index 1e1f583..a89aae7 100644 --- a/tools/parser/tests/src/lib.rs +++ b/tools/parser/tests/src/lib.rs @@ -3826,6 +3826,89 @@ fn cmper_test() { "#).unwrap()).compile().unwrap(), ); + assert_eq!( + CompileMeta::new().compile(parse!(parser, r#" + const x.Cmp = goto(.. < 2); + const Cmp = x->Cmp; + do {} while Cmp; + "#).unwrap()).compile().unwrap(), + CompileMeta::new().compile(parse!(parser, r#" + do {} while x < 2; + "#).unwrap()).compile().unwrap(), + ); + + assert_eq!( + CompileMeta::new().compile(parse!(parser, r#" + const x.New = ( + setres ..; + const $.Cmp = goto(.. < 2); + ); + const Cmp = x->New->Cmp; + do {} while Cmp; + "#).unwrap()).compile().unwrap(), + CompileMeta::new().compile(parse!(parser, r#" + do {} while x < 2; + "#).unwrap()).compile().unwrap(), + ); + + assert_eq!( + CompileMeta::new().compile(parse!(parser, r#" + const x.New = ( + setres ..; + const $.Cmp = goto({print ..;} => .. < 2); + ); + const Cmp = x->New->Cmp; + do {} while Cmp; + "#).unwrap()).compile().unwrap(), + CompileMeta::new().compile(parse!(parser, r#" + do {print x;} while x < 2; + "#).unwrap()).compile().unwrap(), + ); + + assert_eq!( + CompileMeta::new().compile(parse!(parser, r#" + const x.Cmp = goto(.. < 2); + const Cmp = x->Cmp; + do {} while Cmp; + do {} while Cmp; + "#).unwrap()).compile().unwrap(), + CompileMeta::new().compile(parse!(parser, r#" + do {} while x < 2; + do {} while x < 2; + "#).unwrap()).compile().unwrap(), + ); + + assert_eq!( + CompileMeta::new().compile(parse!(parser, r#" + const x.Cmp = goto({ + do {} while; + } => .. < 2); + const Cmp = x->Cmp; + do {} while Cmp; + do {} while Cmp; + "#).unwrap()).compile().unwrap(), + CompileMeta::new().compile(parse!(parser, r#" + do {do {} while;} while x < 2; + do {do {} while;} while x < 2; + "#).unwrap()).compile().unwrap(), + ); + + assert_eq!( + CompileMeta::new().compile(parse!(parser, r#" + const x.Cmp = goto({ + do {} while; + } => .. < 2); + const Cmp = x->Cmp; + do {} while Cmp; + do {} while Cmp; + print ..; + "#).unwrap()).compile().unwrap(), + CompileMeta::new().compile(parse!(parser, r#" + do {do {} while;} while x < 2; + do {do {} while;} while x < 2; + print __; + "#).unwrap()).compile().unwrap(), + ); } #[test] diff --git a/tools/syntax/Cargo.toml b/tools/syntax/Cargo.toml index 0a150dc..bc01d87 100644 --- a/tools/syntax/Cargo.toml +++ b/tools/syntax/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "syntax" -version = "0.2.30" +version = "0.2.31" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tools/syntax/src/lib.rs b/tools/syntax/src/lib.rs index 65df856..f7cb642 100644 --- a/tools/syntax/src/lib.rs +++ b/tools/syntax/src/lib.rs @@ -288,7 +288,7 @@ impl TakeHandle for Var { fn take_handle(self, meta: &mut CompileMeta) -> Var { if let Some(value) = meta.const_expand_enter(&self) { // 是一个常量 - let res = value.take_handle_with_consted(meta); + let res = value.clone().take_handle_with_consted(meta); meta.const_expand_exit(); res } else { @@ -613,6 +613,7 @@ impl_enum_froms!(impl From for Value { impl_enum_try_into!(impl TryInto for Value { Var => Var; DExp => DExp; + Cmper => Box; ValueBind => ValueBind; ValueBindRef => ValueBindRef; }); @@ -853,9 +854,10 @@ impl ClosuredValue { vars, }; } -} -impl TakeHandle for ClosuredValue { - fn take_handle(mut self, meta: &mut CompileMeta) -> Var { + + pub fn expand_with(mut self, meta: &mut CompileMeta, f: F) -> R + where F: FnOnce(Var, &mut CompileMeta) -> R, + { self.catch_env(meta); let Self::Inited { bind_handle, @@ -877,13 +879,23 @@ impl TakeHandle for ClosuredValue { meta.with_const_expand_tag_name_map_scope( rename_labels, |meta| { - result = Self::make_valkey(bind_handle) - .take_handle(meta) - .into(); + let binded = meta.get_value_binded( + bind_handle, + Self::BINDED_VALUE_NAME.into(), + ); + result = f(binded, meta).into(); }, ); }); result.unwrap() + + } +} +impl TakeHandle for ClosuredValue { + fn take_handle(self, meta: &mut CompileMeta) -> Var { + self.expand_with(meta, |v, meta| { + v.take_handle(meta) + }) } } @@ -1508,6 +1520,8 @@ impl_enum_froms!(impl From for LogicLineFromTagError { pub enum CmpTree { /// 整棵条件树的依赖 Deps(InlineBlock, Box), + /// 使用指定句柄的信息来进入const展开, 但使用的值是携带的那个 + Expand(Var, Box), And(Box, Box), Or(Box, Box), Atom(JumpCmp), @@ -1533,6 +1547,8 @@ impl CmpTree { => Self::Or(a.reverse().into(), b.reverse().into()), Self::Atom(cmp) => Self::Atom(cmp.reverse()), + Self::Expand(handle, cmp) + => Self::Expand(handle, cmp.reverse().into()), } } @@ -1640,7 +1656,6 @@ impl CmpTree { let info = op.into_info(); let cmp = cmper(info.arg1, info.arg2.unwrap()); *self = cmp_rev(cmp.into()) - } V::Var(name) => { match meta.get_const_value(name) { @@ -1653,7 +1668,10 @@ impl CmpTree { *self = cmp_rev(cmp.into()) } Some(ConstData { value: V::Cmper(cmper), .. }) => { - *self = cmp_rev((**cmper).clone()) + *self = cmp_rev(Self::Expand( + name.clone(), + cmper.clone(), + )) } Some(_) | None => return, } @@ -1690,6 +1708,11 @@ impl CmpTree { let tag_id = meta.get_tag(end); meta.push(TagLine::TagDown(tag_id)); }, + Expand(handle, cmp) => { + meta.const_expand_enter(&handle); + cmp.build(meta, do_tag_expanded); + meta.const_expand_exit(); + }, Atom(JumpCmp::Never) => (), // 构建不成立的条件没意义 Atom(cmp) => { // 构建为可以进行接下来的编译的形式 @@ -1739,11 +1762,14 @@ impl CmpTree { root.into() } + /// 静态的是否为始终成立的跳转判定, 不被常量什么的影响 pub fn is_always(&self) -> bool { match self { CmpTree::Deps(_, cond) => cond.is_always(), CmpTree::And(a, b) => a.is_always() && b.is_always(), + // NOTE: 这里使用`&&`而不是`||`是为了调用方可能借此确认条件的简单 CmpTree::Or(a, b) => a.is_always() && b.is_always(), + CmpTree::Expand(_, cond) => cond.is_always(), CmpTree::Atom(atom) => atom.is_always(), } } @@ -4213,7 +4239,7 @@ impl CompileMeta { /// 进入一层宏展开环境, 并且返回其值 /// 这个函数会直接调用获取函数将标记映射完毕, 然后返回其值 /// 如果不是一个宏则直接返回None, 也不会进入无需清理 - pub fn const_expand_enter(&mut self, name: &Var) -> Option { + pub fn const_expand_enter(&mut self, name: &Var) -> Option<&Value> { let label_count = self.get_const_value(name)?.labels().len(); if self.const_expand_names.len() >= self.const_expand_max_depth { self.log_expand_stack::(); @@ -4227,7 +4253,7 @@ impl CompileMeta { tmp_tags.extend(repeat_with(|| self.get_tmp_tag()) .take(label_count)); - let ConstData { value, labels, binder } + let ConstData { value: _, labels, binder } = self.get_const_value(name).unwrap(); let mut labels_map = HashMap::with_capacity(labels.len()); for (tmp_tag, label) in zip(tmp_tags, labels.iter().cloned()) { @@ -4241,11 +4267,10 @@ impl CompileMeta { ).into() }); } - let res = value.clone(); self.dexp_expand_binders.push(binder.clone()); self.const_expand_tag_name_map.push(labels_map); self.const_expand_names.push(name.clone()); - res.into() + Some(&self.get_const_value(name).unwrap().value) } pub fn const_expand_exit(&mut self) -> (