Skip to content

Commit

Permalink
将const和take的目标扩展到ValueBind, 并将其值加入至全局作用域
Browse files Browse the repository at this point in the history
- 注意: 此次更新缩减了ValueBind被绑定值的语法范围
  • Loading branch information
A4-Tacks committed Jan 1, 2024
1 parent 2242187 commit d3fb2f7
Show file tree
Hide file tree
Showing 11 changed files with 234 additions and 49 deletions.
10 changes: 5 additions & 5 deletions Cargo.lock

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

2 changes: 1 addition & 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.14.2"
version = "0.14.3"
edition = "2021"

authors = ["A4-Tacks <[email protected]>"]
Expand Down
40 changes: 39 additions & 1 deletion examples/value_bind.mdtlbl
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,19 @@
* 这是在0.10.0版本加入的语法
* 可以有效的把数据组织起来
* 作用是将一个Var按照特定格式绑定到一个Value的句柄
* 语法为 `Value "." NoStringVar`, 例如`$.data` `foo.bar`
* 语法为 `NonDExpValue "." NoStringVar`, 例如`$.data` `foo.bar`
* 这里需要注意的是, 其左值的句柄不能为字符串, 否则会报错
*
* 在0.14.3版本将其扩展, 使其可以出现在take和const目标中, 并且会添加至全局作用域
* 当局部作用域都没有命中时, 将会尝试命中全局作用域
*
* 需要注意的是, 最佳实践中最好被绑定的量仅为匿名量, 否则可能会造成一定的混乱.
* 因为那时候或许难以区分哪些是展开为同一个量的值, 而值绑定是绑定在其句柄,
* 也就是展开的量上的
*
* 这个功能扩展主要是配合match使用的,
* 对于主要关注其量为变量的情况, 这很可能导致生命周期的模糊边界,
* 可能为项目增加额外的复杂度, 谨慎使用
*#

const Human_new = (
Expand Down Expand Up @@ -56,3 +67,30 @@ print ","
print __5
*#
# 可以看到, 这可以使我们方便的组织数据


const Foo = (
take $.X = _0;
);
print Foo[2].X;
#* >>>
print 2
*#
# 全局作用域并不受局部作用域限制


const Foo = (
const $.F = (
print "foo";
);
print "bar";
);
take R = Foo;
print "---";
take R.F;
#* >>>
print "bar"
print "---"
print "foo"
*#
# 使用const直接将值传出而不take
2 changes: 1 addition & 1 deletion tools/display_source/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "display_source"
version = "0.3.4"
version = "0.3.5"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
10 changes: 9 additions & 1 deletion tools/display_source/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ impl DisplaySource for Take {
meta.push("take");
meta.add_space();

meta.push(&Value::replace_ident(&self.0));
self.0.display_source(meta);
meta.add_space();

meta.push("=");
Expand All @@ -276,6 +276,14 @@ impl DisplaySource for Take {
meta.push(";");
}
}
impl DisplaySource for ConstKey {
fn display_source(&self, meta: &mut DisplaySourceMeta) {
match self {
Self::Var(var) => var.display_source(meta),
Self::ValueBind(vbind) => vbind.display_source(meta),
}
}
}
impl DisplaySource for LogicLine {
fn display_source(&self, meta: &mut DisplaySourceMeta) {
match self {
Expand Down
2 changes: 1 addition & 1 deletion tools/parser/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "parser"
version = "0.1.1"
version = "0.2.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
51 changes: 32 additions & 19 deletions tools/parser/src/parser.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use ::syntax::{
Select,
Const,
Take,
ConstKey,
LogicLine,
Args,
ArgsRepeat,
Expand Down Expand Up @@ -117,9 +118,12 @@ pub Var: Var = {
NoStringVar,
}

pub Value: Value = {
Var => <>.into(),
DExp => <>.into(),
ValueBind: ValueBind = <value:NonDExpValue> "." <attr:NoStringVar> => {
ValueBind(value.into(), attr)
};

NonDExpValue: Value = {
<v:Var> => v.into(),
"`" <Var> "`" => ReprVar(<>), // 原始值
"$" => ResultHandle,
<name:Var> <args:MList<Args?>> => {
Expand All @@ -129,17 +133,22 @@ pub Value: Value = {
LogicLine::SetResultHandle(name.into()),
].into()).into()
},
<value:Value> "." <attr:NoStringVar> => ValueBind(value.into(), attr).into(),
ValueBind => <>.into(),
"goto" <MTuple<JumpCmpOnce>> => Value::Cmper(<>.into()),
}

pub Value: Value = {
NonDExpValue,
DExp => <>.into(),
// consted-dexp
"const" ConstStart <dexp:DExp> <labels:ConstStop> => {
let tmp_name = meta.get_tmp_var();
let dexp_const = Const(tmp_name.clone(), dexp.into(), labels);
let dexp_const = Const(tmp_name.clone().into(), dexp.into(), labels);
DExp::new("__".into(), vec![
dexp_const.into(),
LogicLine::SetResultHandle(tmp_name.into()),
].into()).into()
},
"goto" <MTuple<JumpCmpOnce>> => Value::Cmper(<>.into()),
}

pub LiteralUInt: usize = <l:@L> <num:Number> <r:@R> =>? {
Expand Down Expand Up @@ -647,12 +656,17 @@ OpExprAtom: OpExprInfo = {
OpExprCallOp,
}

ConstKey: ConstKey = {
ValueBind => <>.into(),
Var => <>.into(),
}

// 开始一个const, 开启了必须负责清理
ConstStart: () = () => meta.add_label_scope();
ConstStop: Vec<Var> = () => Vec::from_iter(meta.pop_label_scope());

pub BuiltinCommand: LogicLine = {
"const" <mut values:(<Var> "=" ConstStart <Value> <ConstStop>)+> LEnd
"const" <mut values:(<ConstKey> "=" ConstStart <Value> <ConstStop>)+> LEnd
=> {
if values.len() == 1 {
let (var, value, labels) = values.pop().unwrap();
Expand All @@ -667,28 +681,27 @@ pub BuiltinCommand: LogicLine = {
}
},

// 如果后方是一个Var则直接将常量映射到后方的值
// 如果后方是一个DExp则将其计算然后将常量映射到计算出的句柄
// 此处默认句柄使用Value
"take" <args:MList<Args?>?> <var:(<Var> "=")?> <value:Value> LEnd => {
"take" <args:MList<Args?>> <var:(<Var> "=")?> <value:Value> LEnd => {
let do_leak_res = var.is_some();

Take::new(
args.flatten().unwrap_or_default(),
args.unwrap_or_default(),
var.unwrap_or_else(|| String::from("__")),
do_leak_res,
value
)
},

// 两个以上take
"take"
<first:(<(<Var> "=")?> <Value>)>
<nexts:(<(<Var> "=")?> <Value>)+>
<mut takes:(<(<ConstKey> "=")?> <Value>)+>
LEnd => {
let mut lines = Vec::with_capacity(1 + nexts.len());
let iter = [first].into_iter().chain(nexts);
for (res, value) in iter {
if takes.len() == 1 {
let (res, value) = takes.pop().unwrap();
let res = res.unwrap_or_else(|| "__".into());
return Take(res, value).into();
}
let mut lines = Vec::with_capacity(takes.len());
for (res, value) in takes.into_iter() {
let res = res.unwrap_or_else(|| "__".into());
let take = Take(res, value);
lines.push(take.into())
Expand Down Expand Up @@ -912,7 +925,7 @@ pub Control: LogicLine = {
out_block.insert(
0,
Const::new(
name,
name.into(),
value_handle.as_str().into()
).into()
)
Expand Down
2 changes: 1 addition & 1 deletion tools/parser/tests/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "parser-tests"
version = "0.1.0"
version = "0.1.1"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
49 changes: 48 additions & 1 deletion tools/parser/tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -970,7 +970,7 @@ fn const_value_leak_test() {
}

#[test]
fn take_test2() {
fn take2_test() {
let parser = LogicLineParser::new();

let ast = parse!(parser, "take X;").unwrap();
Expand Down Expand Up @@ -4235,3 +4235,50 @@ fn match_test() {
],
);
}

#[test]
fn value_bind_of_constkey_test() {
let parser = TopLevelParser::new();

assert_eq!(
CompileMeta::new().compile(parse!(parser, r#"
take X = ();
take X.Y = 2;
print X.Y;
"#).unwrap()).compile().unwrap(),
vec![
"print 2",
],
);

assert_eq!(
CompileMeta::new().compile(parse!(parser, r#"
take X = ();
{
take X.Y = 2; # to global
}
print X.Y;
"#).unwrap()).compile().unwrap(),
vec![
"print 2",
],
);

assert_eq!(
CompileMeta::new().compile(parse!(parser, r#"
take X = ();
{
const X.Y = (
:x
goto :x;
);
}
take X.Y;
take X.Y;
"#).unwrap()).compile().unwrap(),
vec![
"jump 0 always 0 0",
"jump 1 always 0 0",
],
);
}
2 changes: 1 addition & 1 deletion tools/syntax/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "syntax"
version = "0.1.2"
version = "0.2.0"
edition = "2021"

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

0 comments on commit d3fb2f7

Please sign in to comment.