diff --git a/Cargo.lock b/Cargo.lock index 1c0217d..2491b80 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -307,7 +307,7 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "mindustry_logic_bang_lang" -version = "0.17.1" +version = "0.17.2" dependencies = [ "display_source", "logic_lint", @@ -580,7 +580,7 @@ dependencies = [ [[package]] name = "tag_code" -version = "0.2.1" +version = "0.2.2" dependencies = [ "either", "peg", diff --git a/Cargo.toml b/Cargo.toml index 90add1a..1fc2915 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mindustry_logic_bang_lang" -version = "0.17.1" +version = "0.17.2" edition = "2021" authors = ["A4-Tacks "] diff --git a/src/main.rs b/src/main.rs index ae8540d..3ede930 100644 --- a/src/main.rs +++ b/src/main.rs @@ -100,6 +100,7 @@ enum CompileMode { MdtTagCodeToMdtLogic, LintLogic, IndentLogic, + RenameLabel, BangToMdtLabel, } impl CompileMode { @@ -163,6 +164,13 @@ impl CompileMode { logic_lines.index_label_popup(); format!("{logic_lines:#}") }, + Self::RenameLabel => { + let mut logic_lines = logic_parse(&src); + logic_lines.for_each_inner_label_mut(|mut lab| { + lab.to_mut().push_str("_RENAME"); + }); + format!("{logic_lines:#}") + }, Self::BangToMdtLabel => { let ast = build_ast(&src); let mut meta = compile_ast(ast, src.clone()); @@ -221,6 +229,7 @@ pub const HELP_MSG: &str = concat_lines! { "\t", "C: compile MdtTagCode to MdtLogicCode"; "\t", "l: lint MdtLogicCode"; "\t", "i: indent MdtLogicCode"; + "\t", "n: rename MdtLogicCode"; "\t", "L: compile MdtBangLang to MdtLabelCode"; ; "input from stdin"; @@ -243,6 +252,7 @@ impl TryFrom for CompileMode { 'C' => Self::MdtTagCodeToMdtLogic, 'l' => Self::LintLogic, 'i' => Self::IndentLogic, + 'n' => Self::RenameLabel, 'L' => Self::BangToMdtLabel, mode => return Err(mode), }) diff --git a/tools/tag_code/Cargo.toml b/tools/tag_code/Cargo.toml index 6fbc154..1532e38 100644 --- a/tools/tag_code/Cargo.toml +++ b/tools/tag_code/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tag_code" -version = "0.2.1" +version = "0.2.2" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tools/tag_code/src/lib.rs b/tools/tag_code/src/lib.rs index e8e5399..8edc3f8 100644 --- a/tools/tag_code/src/lib.rs +++ b/tools/tag_code/src/lib.rs @@ -488,11 +488,9 @@ impl<'a> TryFrom> for TagCodes { .try_for_each(|label| { if lab2idx.insert(*label, lab2idx.len()).is_some() { - return Err(label.as_ref().map(|_| { - ParseTagCodesError::RepeatLabel( - label.to_string() - ) - })); + return Err(label.new_value(ParseTagCodesError::RepeatLabel( + label.to_string() + ))); } Ok(()) })?; @@ -501,7 +499,7 @@ impl<'a> TryFrom> for TagCodes { lab2idx.get(*lab) .copied() .ok_or_else(|| { - lab.as_ref().map(|_| ParseTagCodesError::MissedLabel( + lab.new_value(ParseTagCodesError::MissedLabel( lab.to_string() )) }) @@ -510,11 +508,11 @@ impl<'a> TryFrom> for TagCodes { let lines = codes.iter().map(|line| { match *line.as_ref() { ParseLine::Label(lab) => { - let tag = get(line.as_ref().map(|_| lab.as_ref()))?; + let tag = get(line.new_value(lab.as_ref()))?; Ok(TagLine::TagDown(tag)) }, ParseLine::Jump(tgt, args) => { - let tag = get(line.as_ref().map(|_| tgt.as_ref()))?; + let tag = get(line.new_value(tgt.as_ref()))?; Ok(TagLine::Jump(Jump(tag, args.join(" ")).into())) }, ParseLine::Args(args) => { diff --git a/tools/tag_code/src/logic_parser.rs b/tools/tag_code/src/logic_parser.rs index eec0e75..ee04da2 100644 --- a/tools/tag_code/src/logic_parser.rs +++ b/tools/tag_code/src/logic_parser.rs @@ -275,6 +275,22 @@ impl<'a> ParseLine<'a> { None } } + + pub fn as_inner_label(&self) -> Option<&str> { + match self { + ParseLine::Label(lab) => Some(lab), + ParseLine::Jump(lab, _) => Some(lab), + ParseLine::Args(_) => None, + } + } + + pub fn as_inner_label_mut(&mut self) -> Option<&mut Cow<'a, str>> { + match self { + ParseLine::Label(lab) => Some(lab), + ParseLine::Jump(lab, _) => Some(lab), + ParseLine::Args(_) => None, + } + } } impl<'a> TryFrom> for ParseLine<'a> { type Error = as TryFrom>>::Error; @@ -414,6 +430,10 @@ impl IdxBox { let Self { index, value } = self; Some(IdxBox { index, value: f(value)? }) } + + pub fn new_value(&self, new_value: U) -> IdxBox { + self.as_ref().map(|&_| new_value) + } } impl Deref for IdxBox { type Target = T; @@ -489,37 +509,47 @@ impl<'a> ParseLines<'a> { &mut self.lines } -pub fn index_label_popup(&mut self) { - let mut lines = mem::take(self.lines_mut()); - let poped: HashSet = lines.iter() - .filter_map(|x| x.as_label()) - .filter_map(|x| x.parse().ok()) - .collect(); - let indexs: HashSet = lines.iter() - .filter_map(|x| x.as_jump_idx()) - .collect(); - let pop_idxs = &indexs - &poped; - while Some(true) == lines.last() - .map(|x| x.is_label()) // move last label to first + pub fn index_label_popup(&mut self) { + let mut lines = mem::take(self.lines_mut()); + let poped: HashSet = lines.iter() + .filter_map(|x| x.as_label()) + .filter_map(|x| x.parse().ok()) + .collect(); + let indexs: HashSet = lines.iter() + .filter_map(|x| x.as_jump_idx()) + .collect(); + let pop_idxs = &indexs - &poped; + while Some(true) == lines.last() + .map(|x| x.is_label()) // move last label to first + { + self.lines.push(lines.pop().unwrap()); + } + self.lines.extend(lines.into_iter() + .scan(0, |i, line| { + Some((line.is_solid().then(|| i!(*i++)), line)) + }) + .flat_map(|(i, line)| { + i.and_then(|i| { + pop_idxs.contains(&i).then(|| { + IdxBox::new( + line.index, + ParseLine::Label(i.to_string().into()), + ) + }) + }).into_iter().chain(once(line)) + }) + ); + } + + pub fn for_each_inner_label_mut<'b, F>(&'b mut self, f: F) + where F: FnMut(IdxBox<&'b mut Cow<'a, str>>), { - self.lines.push(lines.pop().unwrap()); - } - self.lines.extend(lines.into_iter() - .scan(0, |i, line| { - Some((line.is_solid().then(|| i!(*i++)), line)) - }) - .flat_map(|(i, line)| { - i.and_then(|i| { - pop_idxs.contains(&i).then(|| { - IdxBox::new( - line.index, - ParseLine::Label(i.to_string().into()), - ) - }) - }).into_iter().chain(once(line)) - }) - ); -} + self.iter_mut() + .filter_map(|line| { + line.as_mut().and_then(ParseLine::as_inner_label_mut) + }) + .for_each(f) + } } impl<'a> From>>> for ParseLines<'a> { fn from(lines: Vec>>) -> Self {