diff --git a/Cargo.lock b/Cargo.lock index 2612f8e..2712178 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -100,7 +100,7 @@ dependencies = [ [[package]] name = "display_source" -version = "0.3.14" +version = "0.3.15" dependencies = [ "parser", "syntax", @@ -301,7 +301,7 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "mindustry_logic_bang_lang" -version = "0.16.4" +version = "0.16.5" dependencies = [ "display_source", "logic_lint", @@ -535,7 +535,7 @@ dependencies = [ [[package]] name = "syntax" -version = "0.2.23" +version = "0.2.24" dependencies = [ "either", "tag_code", diff --git a/Cargo.toml b/Cargo.toml index 71f78e1..a87a150 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mindustry_logic_bang_lang" -version = "0.16.4" +version = "0.16.5" edition = "2021" authors = ["A4-Tacks "] diff --git a/src/main.rs b/src/main.rs index d2ec745..fe565d3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,17 +7,23 @@ use std::{ process::exit, str::FromStr, collections::HashMap, - ops::Deref, fmt::Display, + ops::Deref, + fmt::Display, + cell::RefCell, + borrow::Cow, }; -use display_source::DisplaySource; +use display_source::{ + DisplaySource, + DisplaySourceMeta, +}; use syntax::{ CompileMeta, Error, Errors, Expand, Meta, - line_first_add, + line_first_add, CompileMetaExtends, }; use parser::{ TopLevelParser, @@ -120,7 +126,7 @@ impl CompileMode { match *self { Self::BangToMdtLogic => { let ast = build_ast(&src); - let mut meta = compile_ast(ast); + let mut meta = compile_ast(ast, src); build_tag_down(&mut meta); let logic_lines = meta.tag_codes_mut().compile().unwrap(); logic_lines.join("\n") @@ -135,7 +141,7 @@ impl CompileMode { }, Self::BangToMdtTagCode { tag_down } => { let ast = build_ast(&src); - let mut meta = compile_ast(ast); + let mut meta = compile_ast(ast, src); if tag_down { build_tag_down(&mut meta); } meta.tag_codes().to_string() }, @@ -422,8 +428,36 @@ fn unwrap_parse_err(result: ParseResult<'_>, src: &str) -> Expand { } } -fn compile_ast(ast: Expand) -> CompileMeta { - CompileMeta::new().compile_res_self(ast) +struct CompileMetaExtender { + source: String, + display_meta: RefCell, +} +impl CompileMetaExtender { + fn new(source: String, display_meta: RefCell) -> Self { + Self { + source, + display_meta, + } + } +} +impl CompileMetaExtends for CompileMetaExtender { + fn source_location(&self, index: usize) -> [syntax::Location; 2] { + get_locations(&self.source, [index])[0] + } + fn display_value(&self, value: &syntax::Value) -> Cow<'_, str> { + let meta = &mut *self.display_meta.borrow_mut(); + meta.to_default(); + value.display_source_and_get(meta).to_owned().into() + } +} + +fn compile_ast(ast: Expand, src: String) -> CompileMeta { + let mut meta = CompileMeta::new(); + meta.set_extender(Box::new(CompileMetaExtender::new( + src, + DisplaySourceMeta::new().into(), + ))); + meta.compile_res_self(ast) } fn get_token_name(s: &str) -> Option<&'static str> { diff --git a/tools/display_source/Cargo.toml b/tools/display_source/Cargo.toml index 8ede4df..65a5e7e 100644 --- a/tools/display_source/Cargo.toml +++ b/tools/display_source/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "display_source" -version = "0.3.14" +version = "0.3.15" 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/lib.rs b/tools/display_source/src/lib.rs index ab1b057..f1f25f2 100644 --- a/tools/display_source/src/lib.rs +++ b/tools/display_source/src/lib.rs @@ -51,6 +51,13 @@ impl DisplaySourceMeta { Self::default() } + /// 已显示内容恢复至初始状态, + /// 这个方法的存在是为了保留可能已经堆分配的缓冲区和配置等 + pub fn to_default(&mut self) { + self.buffer.clear(); + self.do_indent_flag = true; + } + /// 执行传入的函数 /// 在执行前会先将缩进增加一层 /// 在执行完毕后会将缩进减回 diff --git a/tools/syntax/Cargo.toml b/tools/syntax/Cargo.toml index f2031cc..081bd3b 100644 --- a/tools/syntax/Cargo.toml +++ b/tools/syntax/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "syntax" -version = "0.2.23" +version = "0.2.24" 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 138d328..053b810 100644 --- a/tools/syntax/src/builtins.rs +++ b/tools/syntax/src/builtins.rs @@ -269,7 +269,22 @@ pub fn build_builtins() -> Vec { /// 以Debug形式显示一个值 fn debug:Debug(meta) [v:value] { - meta.log_info(format!("Value Debug:\n{:#?}", value)); + if let Some(ref ext) = meta.extender { + meta.log_info(format!( + "Value Debug:\n\ + binder: ..{}\n\ + labels: {}\n\ + value: {}\ + ", + value.binder.as_ref().map(|s| s.as_str()).unwrap_or(""), + value.labels().iter() + .flat_map(|s| [s.as_str(), ", "]) + .into_iter_fmtter(), + ext.display_value(value.value()), + )); + } else { + meta.log_info(format!("Value Debug:\n{:#?}", value)); + } Ok("__".into()) } diff --git a/tools/syntax/src/lib.rs b/tools/syntax/src/lib.rs index 17c7910..62dd1ab 100644 --- a/tools/syntax/src/lib.rs +++ b/tools/syntax/src/lib.rs @@ -158,6 +158,13 @@ impl Var { pub fn new() -> Self { Self::default() } + + pub fn display_src<'a>(&'a self, meta: &'a CompileMeta) -> Cow<'a, str> { + meta.extender.as_ref() + .map(|ext| ext + .display_value(&Value::Var(self.clone()))) + .unwrap_or(self.as_str().into()) + } } impl FromIterator for Var { fn from_iter>(iter: T) -> Self { @@ -347,6 +354,17 @@ impl Value { None } } + + /// 尝试借助扩展直接显示源码, 如果不成的话走普通的debug + pub fn display_src<'a>( + &self, + meta: &'a CompileMeta, + ) -> Cow<'a, str> { + meta.extender + .as_ref() + .map(|ext| ext.display_value(&self)) + .unwrap_or_else(|| format!("{self:#?}").into()) + } } impl TakeHandle for Value { fn take_handle(self, meta: &mut CompileMeta) -> Var { @@ -366,11 +384,11 @@ impl TakeHandle for Value { meta.get_dexp_expand_binder().cloned() .unwrap_or_else(|| "__".into()) }, - Self::Cmper(cmp) => { + cmp @ Self::Cmper(_) => { err!( - "{}\n最终未被展开的cmper, {:#?}", + "{}\n最终未被展开的cmper:\n{}", meta.err_info().join("\n"), - cmp, + cmp.display_src(meta), ); exit(6); }, @@ -893,11 +911,11 @@ impl TakeHandle for DExp { concat!( "{}\n尝试在`DExp`的返回句柄处使用值不为Var的const, ", "此处仅允许使用`Var`\n", - "值: {:#?}\n", + "值: {}\n", "名称: {:?}", ), meta.err_info().join("\n"), - value, + value.display_src(meta), result ); exit(5); @@ -2764,6 +2782,9 @@ impl Compile for Match { } } if meta.enable_misses_match_log_info { + let args = args.into_iter() + .map(|v| v.display_src(meta).into_owned()) + .collect::>(); meta.log_info(format_args!("Misses match, [{}]", args.join(" "))); meta.log_expand_stack::(); } @@ -2928,10 +2949,10 @@ impl Compile for ConstMatch { } } if meta.enable_misses_match_log_info { - meta.log_info(format_args!( - "Misses const match, [{}]", - args.join(" "), - )); + let args = args.into_iter() + .map(|v| v.display_src(meta).into_owned()) + .collect::>(); + meta.log_info(format_args!("Misses match, [{}]", args.join(" "))); meta.log_expand_stack::(); } } @@ -3720,7 +3741,15 @@ impl ExpandEnv { } } +pub trait CompileMetaExtends { + #[must_use] + fn source_location(&self, index: usize) -> [Location; 2]; + #[must_use] + fn display_value(&self, value: &Value) -> Cow<'_, str>; +} + pub struct CompileMeta { + extender: Option>, /// 标记与`id`的映射关系表 tags_map: HashMap, tag_count: usize, @@ -3787,6 +3816,7 @@ impl CompileMeta { pub fn with_tag_codes(tag_codes: TagCodes) -> Self { let mut meta = Self { + extender: None, tags_map: HashMap::new(), tag_count: 0, tag_codes, @@ -3866,7 +3896,10 @@ impl CompileMeta { self.tmp_var_count.get() }).clone(); if let Some((true, bind)) = warn_builtin { - self.log_info(format_args!("Missed Builtin Call: {bind}")); + self.log_info(format!( + "Missed Builtin Call: {}", + bind.display_src(self), + )); } binded } @@ -4306,7 +4339,7 @@ impl CompileMeta { pub fn log_expand_stack(&mut self) { let names = self.debug_expand_stack() .flat_map(|var| [ - var.to_string().into(), + var.display_src(&self).into_owned().into(), Cow::Borrowed("\n"), ]) .into_iter_fmtter(); @@ -4338,6 +4371,14 @@ impl CompileMeta { pub fn set_const_expand_max_depth(&mut self, const_expand_max_depth: usize) { self.const_expand_max_depth = const_expand_max_depth; } + + pub fn set_extender(&mut self, extender: Box) { + self.extender = extender.into(); + } + + pub fn extender(&self) -> Option<&dyn CompileMetaExtends> { + self.extender.as_deref() + } } pub fn line_first_add(lines: &mut Vec, insert: &str) {