From cfe03cdfa56e9d79e83c2d654136b283ee4cc70c Mon Sep 17 00:00:00 2001 From: A4-Tacks Date: Wed, 17 Jan 2024 01:21:35 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=87=A0=E5=A4=84=E4=B8=8D?= =?UTF-8?q?=E5=BA=94=E6=9C=89=E7=9A=84const=E8=BF=BD=E6=BA=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ArgsRepeat 的二次追溯 --- Cargo.lock | 6 +-- Cargo.toml | 2 +- tools/parser/tests/Cargo.toml | 2 +- tools/parser/tests/src/lib.rs | 62 +++++++++++++++++++++++ tools/syntax/Cargo.toml | 2 +- tools/syntax/src/lib.rs | 93 ++++++++++++++++++----------------- 6 files changed, 115 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 72913ab..9d575b0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -292,7 +292,7 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "mindustry_logic_bang_lang" -version = "0.14.10" +version = "0.14.11" dependencies = [ "display_source", "parser", @@ -348,7 +348,7 @@ dependencies = [ [[package]] name = "parser-tests" -version = "0.1.6" +version = "0.1.7" dependencies = [ "parser", "syntax", @@ -525,7 +525,7 @@ dependencies = [ [[package]] name = "syntax" -version = "0.2.7" +version = "0.2.8" dependencies = [ "tag_code", "utils", diff --git a/Cargo.toml b/Cargo.toml index 5f1dc3c..ec94b16 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mindustry_logic_bang_lang" -version = "0.14.10" +version = "0.14.11" edition = "2021" authors = ["A4-Tacks "] diff --git a/tools/parser/tests/Cargo.toml b/tools/parser/tests/Cargo.toml index 09d0b8a..1fb1579 100644 --- a/tools/parser/tests/Cargo.toml +++ b/tools/parser/tests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "parser-tests" -version = "0.1.6" +version = "0.1.7" 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 101d1db..d1f0883 100644 --- a/tools/parser/tests/src/lib.rs +++ b/tools/parser/tests/src/lib.rs @@ -4411,6 +4411,68 @@ fn match_test() { "print 4", ], ); + + assert_eq!( + CompileMeta::new().compile(parse!(parser, r#" + # 关于二次追溯 + { + const X = 2; + const Y = `X`; + const F = ( + print _0 @; + ); + take F[Y]; + } + { + const X = 2; + const F = ( + const Y = `X`; + print _0 @; + ); + take F[Y]; + } + "#).unwrap()).compile().unwrap(), + vec![ + "print X", + "print X", + "print Y", + "print Y", + ], + ); + + assert_eq!( + CompileMeta::new().compile(parse!(parser, r#" + # 关于二次追溯 + { + const X = 2; + const Y = `X`; + const F = ( + print _0; + match @ { + V { print V; } + } + ); + take F[Y]; + } + { + const X = 2; + const F = ( + const Y = `X`; + print _0; + match @ { + V { print V; } + } + ); + take F[Y]; + } + "#).unwrap()).compile().unwrap(), + vec![ + "print X", + "print X", + "print Y", + "print Y", + ], + ); } #[test] diff --git a/tools/syntax/Cargo.toml b/tools/syntax/Cargo.toml index 1c538ed..2beb5b4 100644 --- a/tools/syntax/Cargo.toml +++ b/tools/syntax/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "syntax" -version = "0.2.7" +version = "0.2.8" 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 d1ab167..205d5a2 100644 --- a/tools/syntax/src/lib.rs +++ b/tools/syntax/src/lib.rs @@ -127,9 +127,13 @@ pub const FALSE_VAR: &str = "false"; pub const ZERO_VAR: &str = "0"; pub const UNUSED_VAR: &str = "0"; -pub trait TakeHandle { +pub trait TakeHandle: Sized { /// 编译依赖并返回句柄 fn take_handle(self, meta: &mut CompileMeta) -> Var; + /// 编译并拿取句柄, 但是是在被const的值的情况下 + fn take_handle_with_consted(self, meta: &mut CompileMeta) -> Var { + self.take_handle(meta) + } } impl TakeHandle for Var { @@ -143,6 +147,9 @@ impl TakeHandle for Var { self } } + fn take_handle_with_consted(self, _meta: &mut CompileMeta) -> Var { + self + } } #[derive(Debug, PartialEq, Clone)] @@ -178,17 +185,6 @@ impl Value { None } } - - /// 编译并拿取句柄, 但是是在被const的值的情况下 - pub fn take_handle_with_consted(self, meta: &mut CompileMeta) -> Var { - if let Some(var) = self.try_eval_const_num_to_var(meta) { - return var; - } - match self { - Self::Var(var) => var, - other => other.take_handle(meta), - } - } } impl TakeHandle for Value { fn take_handle(self, meta: &mut CompileMeta) -> Var { @@ -218,6 +214,18 @@ impl TakeHandle for Value { Self::BuiltinFunc(func) => func.call(meta), } } + fn take_handle_with_consted(self, meta: &mut CompileMeta) -> Var { + if let Some(var) = self.try_eval_const_num_to_var(meta) { + return var; + } + match self { + Self::Var(var) => var, + Self::ReprVar(var) => { + panic!("Fail const reprvar {}, meta: {:#?}", var, meta); + }, + other => other.take_handle(meta), + } + } } impl Default for Value { /// 默认的占位值, 它是无副作用的, 不会被常量展开 @@ -2079,33 +2087,13 @@ pub enum Args { Expanded(Vec, Vec), } impl Args { - /// 获取参数引用 - pub fn get_value_args<'a>(&'a self, meta: &'a CompileMeta) -> Vec<&'a Value> { - match self { - Self::Normal(args) => args.iter().collect(), - Self::Expanded(left, right) => { - left.iter() - .chain(meta.get_env_args().iter() - .map(|var| meta.get_const_value(var) - .unwrap() - .value())) - .chain(right) - .collect() - }, - } - } - /// 获取值 pub fn into_value_args(self, meta: &CompileMeta) -> Vec { match self { Self::Normal(args) => args, Self::Expanded(left, right) => { left.into_iter() - .chain(meta.get_env_args().iter() - .map(|var| meta.get_const_value(var) - .unwrap() - .value() - .clone())) + .chain(meta.get_env_args().iter().cloned().map(Into::into)) .chain(right) .collect() }, @@ -2115,7 +2103,7 @@ impl Args { /// 获取句柄, 但是假定环境中的args已经const过了 /// /// 这不包括左部分和右部分 - pub fn into_args_handle(self, meta: &mut CompileMeta) -> Vec { + pub fn into_taked_args_handle(self, meta: &mut CompileMeta) -> Vec { match self { Args::Normal(args) => { args.into_iter() @@ -2166,7 +2154,7 @@ impl Args { } } - pub fn into_normal(self) -> Result, Self> { + pub fn try_into_normal(self) -> Result, Self> { match self { Self::Normal(args) => Ok(args), this => Err(this), @@ -2219,12 +2207,12 @@ impl ArgsRepeat { } impl Compile for ArgsRepeat { fn compile(self, meta: &mut CompileMeta) { - let chunks: Vec> = meta.get_env_args().chunks(self.count) + let chunks: Vec> = meta.get_env_args() + .chunks(self.count) .map(|chunks| chunks.iter() - .map(|var| meta.get_const_value(var) - .unwrap() - .value()) - .cloned().collect()) + .cloned() + .map(Into::into) + .collect()) .collect(); for args in chunks { let args = Vec::from_iter(args.iter().cloned()); @@ -2243,7 +2231,7 @@ pub struct Match { } impl Compile for Match { fn compile(self, meta: &mut CompileMeta) { - let args = self.args.into_args_handle(meta); + let args = self.args.into_taked_args_handle(meta); let mut iter = self.cases.into_iter(); loop { let Some(case) = iter.next() else { break }; @@ -2405,7 +2393,7 @@ impl Compile for LogicLine { meta.push(data) }, Self::Other(args) => { - let handles: Vec = args.into_args_handle(meta); + let handles: Vec = args.into_taked_args_handle(meta); meta.push(TagLine::Line(handles.join(" ").into())); }, Self::SetResultHandle(value) => { @@ -2413,13 +2401,24 @@ impl Compile for LogicLine { meta.set_dexp_handle(new_dexp_handle); }, Self::SetArgs(args) => { + fn iarg(i: usize) -> Var { + format!("_{i}") + } let expand_args = args.into_value_args(meta); - meta.set_env_args(expand_args.clone()); + let len = expand_args.len(); let mut f = |r#const: Const| r#const.compile(meta); - for (i, value) in expand_args.into_iter().enumerate() { - let name = format!("_{}", i); - f(Const(name.into(), value, Vec::with_capacity(0)).into()); + let iter = expand_args.into_iter().enumerate(); + for (i, value) in iter { + f(Const( + iarg(i).into(), + value.into(), + Vec::with_capacity(0), + ).into()); } + meta.set_env_args((0..len) + .map(iarg) + .map(Into::into) + .collect()); }, Self::Select(select) => select.compile(meta), Self::Expand(expand) => expand.compile(meta), @@ -3141,6 +3140,8 @@ impl CompileMeta { } /// 设置最内层args, 返回旧值 + /// + /// 这将进行const的追溯 pub fn set_env_args(&mut self, expand_args: Vec) -> Option> { let vars: Vec = expand_args.into_iter() .map(|value| {