Skip to content

Commit

Permalink
为ValueBind的生成句柄由组合格改为匿名
Browse files Browse the repository at this point in the history
  • Loading branch information
A4-Tacks committed Oct 17, 2023
1 parent efa9c59 commit 2966a7b
Show file tree
Hide file tree
Showing 10 changed files with 137 additions and 34 deletions.
7 changes: 6 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mindustry_logic_bang_lang"
version = "0.12.4"
version = "0.12.5"
edition = "2021"

authors = ["A4-Tacks <[email protected]>"]
Expand All @@ -18,6 +18,7 @@ lalrpop = "0.20.0"
tag_code = { path = "./tools/tag_code", version = "*" }
display_source = { path = "./tools/display_source", version = "*" }
var_utils = { path = "./tools/var_utils", version = "*"}
utils = { path = "./tools/utils", version = "*" }

[dependencies.lalrpop-util]
version = "0.20.0"
Expand Down
18 changes: 9 additions & 9 deletions examples/value_bind.mdtlbl
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ take["jack" 18] Human = Human_new;
print Human Human.age;
#* >>>
set __0 "jack"
set ____0__bind__age 18
set __1 18
print __0
print ____0__bind__age
print __1
*#
# 可以看到, 我们将额外的age绑定到了我们的Human
# 这可以用来组织一些复杂结构
Expand All @@ -46,13 +46,13 @@ take[Num1 Num2] Num3 = Complex_add;
print Num3 "," Num3.i;
#* >>>
set __0 3
set ____0__bind__i 5
set __1 2
set ____1__bind__i 8
op add __2 __0 __1
op add ____2__bind__i ____0__bind__i ____1__bind__i
print __2
set __1 5
set __2 2
set __3 8
op add __4 __0 __2
op add __5 __1 __3
print __4
print ","
print ____2__bind__i
print __5
*#
# 可以看到, 这可以使我们方便的组织数据
54 changes: 34 additions & 20 deletions src/syntax/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use display_source::{
DisplaySourceMeta,
};
pub use crate::tag_code::mdt_logic_split;
use utils::counter::Counter;


macro_rules! impl_enum_froms {
Expand Down Expand Up @@ -430,16 +431,11 @@ impl TakeHandle for ValueBind {
// 以`__{}__bind__{}`的形式组合
let handle = self.0.take_handle(meta);
assert!(! Value::is_string(&self.1));
if Value::is_string(&handle) {
err!(
"{}\nValueBind过程中, 左值句柄为字符串, ({}.{})",
meta.err_info().join("\n"),
Value::replace_ident(&handle),
Value::replace_ident(&self.1),
);
exit(6)
}
format!("__{}__bind__{}", handle, self.1)
let binded
= meta.get_value_binded(handle, self.1).clone();
// 进行常量表查询, 虽然是匿名量但是还是要有这个行为嘛
// 虽然之前没有
binded.take_handle(meta)
}
}
impl DisplaySource for ValueBind {
Expand Down Expand Up @@ -2131,19 +2127,20 @@ pub struct CompileMeta {
tags_map: HashMap<String, usize>,
tag_count: usize,
tag_codes: TagCodes,
tmp_var_count: usize,
tmp_var_count: Counter<fn(&mut usize) -> Var>,
/// 块中常量, 且带有展开次数与内部标记
/// 并且存储了需要泄露的常量
///
/// `Vec<(leaks, HashMap<name, (Vec<Label>, Value)>)>`
const_var_namespace: Vec<(Vec<Var>, HashMap<Var, (Vec<Var>, Value)>)>,
/// 每层DExp所使用的句柄, 末尾为当前层
dexp_result_handles: Vec<Var>,
tmp_tag_count: usize,
tmp_tag_count: Counter<fn(&mut usize) -> Var>,
/// 每层const展开的标签
/// 一个标签从尾部上寻, 寻到就返回找到的, 没找到就返回原本的
/// 所以它支持在宏A内部展开的宏B跳转到宏A内部的标记
const_expand_tag_name_map: Vec<HashMap<Var, Var>>,
value_binds: HashMap<(Var, Var), Var>,
}
impl Default for CompileMeta {
fn default() -> Self {
Expand All @@ -2160,11 +2157,12 @@ impl CompileMeta {
tags_map: HashMap::new(),
tag_count: 0,
tag_codes,
tmp_var_count: 0,
tmp_var_count: Counter::new(Self::tmp_var_getter),
const_var_namespace: Vec::new(),
dexp_result_handles: Vec::new(),
tmp_tag_count: 0,
tmp_tag_count: Counter::new(Self::tmp_tag_getter),
const_expand_tag_name_map: Vec::new(),
value_binds: HashMap::new(),
}
}

Expand All @@ -2178,17 +2176,33 @@ impl CompileMeta {
})
}

fn tmp_tag_getter(id: &mut usize) -> Var {
let old = *id;
*id += 1;
format!("__{old}")
}

/// 获取一个临时的`tag`
pub fn get_tmp_tag(&mut self) -> Var {
let id = self.tmp_tag_count;
self.tmp_tag_count += 1;
format!("__{}", id)
self.tmp_tag_count.get()
}

fn tmp_var_getter(id: &mut usize) -> Var {
let old = *id;
*id += 1;
format!("__{old}")
}

pub fn get_tmp_var(&mut self) -> Var {
let id = self.tmp_var_count;
self.tmp_var_count += 1;
format!("__{}", id)
self.tmp_var_count.get()
}

pub fn get_value_binded(&mut self, value: Var, bind: Var) -> &Var {
let key = (value, bind);
self.value_binds.entry(key)
.or_insert_with(|| {
self.tmp_var_count.get()
})
}

/// 向已生成代码`push`
Expand Down
8 changes: 5 additions & 3 deletions src/syntax/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2069,16 +2069,18 @@ fn value_bind_test() {
"#).unwrap()).compile().unwrap();
assert_eq!(logic_lines, vec![
"set jack \"jack\"",
"set __jack__bind__age 18",
"set __0 18",
"print jack",
"print __jack__bind__age",
"print __0",
]);

let logic_lines = CompileMeta::new().compile(parse!(parser, r#"
print a.b.c;
print a.b;
"#).unwrap()).compile().unwrap();
assert_eq!(logic_lines, vec![
"print ____a__bind__b__bind__c",
"print __1",
"print __0",
]);

}
Expand Down
1 change: 1 addition & 0 deletions tools/utils/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/target
7 changes: 7 additions & 0 deletions tools/utils/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions tools/utils/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "utils"
version = "0.1.1"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
62 changes: 62 additions & 0 deletions tools/utils/src/counter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/// 一个负责获取结果并自增的结构
/// # Examples
/// ```
/// # use utils::counter::Counter;
/// let mut counter: Counter<_> = Counter::new(|n| {
/// let old = *n;
/// *n += 1;
/// format!("__{old}")
/// });
/// assert_eq!(counter.get(), "__0");
/// assert_eq!(counter.get(), "__1");
/// assert_eq!(counter.get(), "__2");
/// assert_eq!(counter.get(), "__3");
/// ```
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
pub struct Counter<F, T = usize>
{
counter: T,
getter: F,
}

impl<F, R, T> Counter<F, T>
where F: FnMut(&mut T) -> R
{
pub fn with_counter(f: F, counter: T) -> Self {
Self {
counter,
getter: f
}
}

pub fn get(&mut self) -> R {
(self.getter)(&mut self.counter)
}
}

impl<F, R, T> Counter<F, T>
where F: FnMut(&mut T) -> R,
T: Default
{
pub fn new(f: F) -> Self {
Self::with_counter(f, Default::default())
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test() {
let mut counter: Counter<_> = Counter::new(|n| {
let old = *n;
*n += 1;
format!("__{old}")
});
assert_eq!(counter.get(), "__0");
assert_eq!(counter.get(), "__1");
assert_eq!(counter.get(), "__2");
assert_eq!(counter.get(), "__3");
}
}
3 changes: 3 additions & 0 deletions tools/utils/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
//! 一系列通用工具
pub mod counter;

0 comments on commit 2966a7b

Please sign in to comment.