From 03058891cc01abaf5c7173eb214ea218c179b467 Mon Sep 17 00:00:00 2001 From: A4-Tacks Date: Tue, 16 Jan 2024 11:09:29 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=B8=A4=E4=B8=AA=E5=80=BC?= =?UTF-8?q?=E7=BB=91=E5=AE=9A=E7=9B=B8=E5=85=B3=E5=86=85=E7=BD=AE=E5=87=BD?= =?UTF-8?q?=E6=95=B0,=20=E4=BF=AE=E6=94=B9=E5=B8=B8=E9=87=8F=E7=BB=91?= =?UTF-8?q?=E5=AE=9A=E8=80=85=E8=B7=9F=E8=B8=AA=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 还添加了编译时元数据调试输出内置函数 - 更新了编译时元数据的调试输出 --- Cargo.lock | 6 +-- Cargo.toml | 2 +- examples/builtin_functions.mdtlbl | 4 ++ tools/parser/tests/Cargo.toml | 2 +- tools/parser/tests/src/lib.rs | 48 ++++++++++++++++++++++- tools/syntax/Cargo.toml | 2 +- tools/syntax/src/builtins.rs | 23 +++++++++++ tools/syntax/src/lib.rs | 64 +++++++++++++++++++++++-------- 8 files changed, 128 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5359fb0..72913ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -292,7 +292,7 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "mindustry_logic_bang_lang" -version = "0.14.9" +version = "0.14.10" dependencies = [ "display_source", "parser", @@ -348,7 +348,7 @@ dependencies = [ [[package]] name = "parser-tests" -version = "0.1.5" +version = "0.1.6" dependencies = [ "parser", "syntax", @@ -525,7 +525,7 @@ dependencies = [ [[package]] name = "syntax" -version = "0.2.6" +version = "0.2.7" dependencies = [ "tag_code", "utils", diff --git a/Cargo.toml b/Cargo.toml index 7113017..5f1dc3c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mindustry_logic_bang_lang" -version = "0.14.9" +version = "0.14.10" edition = "2021" authors = ["A4-Tacks "] diff --git a/examples/builtin_functions.mdtlbl b/examples/builtin_functions.mdtlbl index 29d837d..d1ab999 100644 --- a/examples/builtin_functions.mdtlbl +++ b/examples/builtin_functions.mdtlbl @@ -12,12 +12,16 @@ * * `Unbind[var]`: 传入一个值绑定, 返回绑定者 * * `Const[name value]`: 动态目标的进行一个const, 并泄露到上层 * * `Binder[name value]`: 传入一个值绑定, 将其被绑定值const给给定名称 +* * `BindHandle[value]`: 直接获取值绑定的句柄, 但是不进行最后一层全局常量域追踪 +* * `BindHandle2[value name]`: 直接获取值绑定的句柄, 但是不进行最后一层全局常量域追踪. +* 与另一个不同的是它使用被绑定值和绑定量两个参数 * * `Debug[value]`: 以debug形式将传入值输出到日志 * * `Exit[code]`: 直接使编译器以给定的退出码值退出 * * `Status[]`: 获取上一个内置函数的退出代码, 通常情况下, 零代表正常, 非零即异常 * * `ArgsLen[]`: 获取上层有效参数表长度 * * `SliceArgs[start end]`: 将参数切分, 但不take * * `ArgsHandle[idx]`: 拿到指定下标的参数的const句柄, 配合Const内置函数转移其值 +* * `MetaDebug[]`: 以调试形式输出编译时元数据 *# print Builtin.Type[x]; diff --git a/tools/parser/tests/Cargo.toml b/tools/parser/tests/Cargo.toml index 18a5e4f..09d0b8a 100644 --- a/tools/parser/tests/Cargo.toml +++ b/tools/parser/tests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "parser-tests" -version = "0.1.5" +version = "0.1.6" 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 e4901e9..101d1db 100644 --- a/tools/parser/tests/src/lib.rs +++ b/tools/parser/tests/src/lib.rs @@ -4461,7 +4461,7 @@ fn value_bind_of_constkey_test() { } #[test] -fn dexp_expand_binder_test() { +fn const_value_expand_binder_test() { let parser = TopLevelParser::new(); assert_eq!( @@ -4629,6 +4629,52 @@ fn dexp_expand_binder_test() { "print 3", ], ); + + assert_eq!( + CompileMeta::new().compile(parse!(parser, r#" + const a.X = ( + print ..; + ); + const b.X = a.X; + take a.X; + take b.X; + "#).unwrap()).compile().unwrap(), + vec![ + "print a", + "print a", + ], + ); + + assert_eq!( + CompileMeta::new().compile(parse!(parser, r#" + const A = a; + const A.X = ( + print ..; + ); + take A.X; + "#).unwrap()).compile().unwrap(), + vec![ + "print a", + ], + ); + + assert_eq!( + CompileMeta::new().compile(parse!(parser, r#" + const a.X = ( + print ..; + ); + take Handle = Builtin.BindHandle2[`a` `X`]; + take Builtin.Const[`Handle` Handle]; + const b.X = Handle; + take a.X; + const a.X = 2; + take b.X; + "#).unwrap()).compile().unwrap(), + vec![ + "print a", + "print a", + ], + ); } #[test] diff --git a/tools/syntax/Cargo.toml b/tools/syntax/Cargo.toml index a958b8f..1c538ed 100644 --- a/tools/syntax/Cargo.toml +++ b/tools/syntax/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "syntax" -version = "0.2.6" +version = "0.2.7" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tools/syntax/src/builtins.rs b/tools/syntax/src/builtins.rs index f05c5a1..b759070 100644 --- a/tools/syntax/src/builtins.rs +++ b/tools/syntax/src/builtins.rs @@ -231,6 +231,23 @@ pub fn build_builtins() -> Vec { }) } + fn bind_handle:BindHandle(meta) [v:value] { + check_type!("valuebind" Value::ValueBind(bind) = value.value() => { + let handle = bind.clone().take_unfollow_handle(meta); + Ok(handle) + }) + } + + fn bind_handle2:BindHandle2(meta) [b:binder n:name] { + check_type!("var" Value::Var(name) = name.value() => { + let bind = ValueBind( + binder.value().clone().into(), + name.clone(), + ); + Ok(bind.take_unfollow_handle(meta)) + }) + } + fn exit:Exit(meta) [n:code] { check_type!("var" Value::Var(code) = code.value() => { let num_code = match code.parse() { @@ -282,5 +299,11 @@ pub fn build_builtins() -> Vec { .unwrap_or_else(|| "__".into())) }) } + + fn meta_dbg:MetaDebug(meta) [] { + let msg = format!("{:#?}", meta); + meta.log_info(msg); + Ok("__".into()) + } } } diff --git a/tools/syntax/src/lib.rs b/tools/syntax/src/lib.rs index 5af0d5a..d1ab167 100644 --- a/tools/syntax/src/lib.rs +++ b/tools/syntax/src/lib.rs @@ -488,14 +488,16 @@ impl_derefs!(impl for DExp => (self: self.lines): Expand); /// 可完成如属性调用的功能 #[derive(Debug, PartialEq, Clone)] pub struct ValueBind(pub Box, pub Var); +impl ValueBind { + pub fn take_unfollow_handle(self, meta: &mut CompileMeta) -> Var { + let handle = self.0.take_handle(meta); + meta.get_value_binded(handle, self.1).clone() + } +} impl TakeHandle for ValueBind { fn take_handle(self, meta: &mut CompileMeta) -> Var { - let handle = self.0.take_handle(meta); - assert!(! Value::is_string(&self.1)); - let binded - = meta.get_value_binded(handle, self.1).clone(); - // 进行常量表查询 - binded.take_handle(meta) + self.take_unfollow_handle(meta) + .take_handle(meta) // 进行通常是全局表的常量表查询 } } @@ -1987,8 +1989,8 @@ impl Const { Self(var, value, Default::default()) } - /// 在const编译前对右部分进行处理 - pub fn run_value(&mut self, meta: &mut CompileMeta) { + /// 在const编译前对右部分进行处理, 如果目标有的话, 返回绑定者 + pub fn run_value(&mut self, meta: &mut CompileMeta) -> Option { let value = &mut self.1; match value { Value::ReprVar(var) => { @@ -1997,21 +1999,27 @@ impl Const { }, Value::Var(var) => { if let Some(data) = meta.get_const_value(var) { - let ConstData { value, labels, .. } = data; + let ConstData { + value, + labels, + binder, + } = data; self.1 = value.clone(); self.2 = labels.clone(); + return binder.as_ref().cloned(); } }, _ => (), } + None } } impl Compile for Const { fn compile(mut self, meta: &mut CompileMeta) { // 对同作用域定义过的常量形成覆盖 // 如果要进行警告或者将信息传出则在此处理 - self.run_value(meta); - meta.add_const_value(self); + let extra_binder = self.run_value(meta); + meta.add_const_value_with_extra_binder(self, extra_binder); } } @@ -2712,11 +2720,15 @@ impl Debug for CompileMeta { .field("tag_count", &self.tag_count) .field("tag_codes", &self.tag_codes) .field("tmp_var_count", &self.tmp_var_count.counter()) - .field("const_var_namespace", &self.expand_env) + .field("expand_env", &self.expand_env) + .field("env_args", &self.env_args) .field("dexp_result_handles", &self.dexp_result_handles) + .field("dexp_expand_binders", &self.dexp_expand_binders) .field("tmp_tag_count", &self.tmp_tag_count.counter()) .field("const_expand_tag_name_map", &self.const_expand_tag_name_map) .field("value_binds", &self.value_binds) + .field("value_bind_global_consts", &self.value_bind_global_consts) + .field("last_builtin_exit_code", &self.last_builtin_exit_code) .field("..", &DotDot) .finish() } @@ -2924,23 +2936,43 @@ impl CompileMeta { } /// 新增一个常量到值的映射, 如果当前作用域已有此映射则返回旧的值并插入新值 - pub fn add_const_value(&mut self, Const(var, value, labels): Const) + pub fn add_const_value(&mut self, r#const: Const) -> Option { + self.add_const_value_with_extra_binder(r#const, None) + } + + /// 新增一个常量到值的映射, 如果当前作用域已有此映射则返回旧的值并插入新值 + /// + /// 如果扩展绑定者存在的话, 忽略键中的绑定者而采用扩展绑定者 + pub fn add_const_value_with_extra_binder( + &mut self, + Const(var, value, labels): Const, + extra_binder: Option, + ) -> Option { match var { ConstKey::Var(_) => { let var = var.take_handle(self); + let mut data = ConstData::new(value, labels); + if let Some(extra_binder) = extra_binder { + data = data.set_binder(extra_binder) + } self.expand_env .last_mut() .unwrap() .consts - .insert(var, ConstData::new(value, labels)) + .insert(var, data) }, ConstKey::ValueBind(ValueBind(binder, name)) => { - assert!(! Value::is_string(&name)); let binder_handle = binder.take_handle(self); + let binder + = if let Some(extra_binder) = extra_binder { + extra_binder + } else { + binder_handle.clone() + }; let data = ConstData::new(value, labels) - .set_binder(binder_handle.clone()); + .set_binder(binder); let binded = self.get_value_binded( binder_handle, name).clone(); self.value_bind_global_consts