diff --git a/Cargo.lock b/Cargo.lock index 983d633..3537f8f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -100,7 +100,7 @@ dependencies = [ [[package]] name = "display_source" -version = "0.3.20" +version = "0.3.21" dependencies = [ "parser", "syntax", @@ -301,7 +301,7 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "mindustry_logic_bang_lang" -version = "0.16.13" +version = "0.16.14" dependencies = [ "display_source", "logic_lint", @@ -347,7 +347,7 @@ dependencies = [ [[package]] name = "parser" -version = "0.3.13" +version = "0.3.14" dependencies = [ "lalrpop", "lalrpop-util", @@ -358,7 +358,7 @@ dependencies = [ [[package]] name = "parser-tests" -version = "0.1.27" +version = "0.1.28" dependencies = [ "parser", "syntax", @@ -535,7 +535,7 @@ dependencies = [ [[package]] name = "syntax" -version = "0.2.32" +version = "0.2.33" dependencies = [ "either", "tag_code", @@ -605,7 +605,7 @@ version = "0.1.2" [[package]] name = "var_utils" -version = "0.5.2" +version = "0.5.3" dependencies = [ "lazy-regex", ] diff --git a/Cargo.toml b/Cargo.toml index ce45ddb..0060ea0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mindustry_logic_bang_lang" -version = "0.16.13" +version = "0.16.14" edition = "2021" authors = ["A4-Tacks "] diff --git a/examples/const.mdtlbl b/examples/const.mdtlbl index 9895ec3..d0991e7 100644 --- a/examples/const.mdtlbl +++ b/examples/const.mdtlbl @@ -5,6 +5,8 @@ * 内联常量的值是一个Value, 也就是说你可以往里面塞一个DExp, 这可以有效的提高代码复用 * Value有一个特殊的值 `$`, 这个值为包裹这个Value的DExp的返回句柄 * 例如 `(x: read $ cell1 0;)`, 其中的`$`代表了这个DExp的返回句柄`x` + * + * 需要注意, DExp定义返回句柄的位置是会尝试对定义的Var进行追溯的, 并且只允许Var *# const N = 2; diff --git a/examples/dexp.mdtlbl b/examples/dexp.mdtlbl index 0b1ab27..a0aa26a 100644 --- a/examples/dexp.mdtlbl +++ b/examples/dexp.mdtlbl @@ -22,7 +22,7 @@ * * 需要注意的是, 对于Var这些, 它们的句柄即为它们自己本身 * - * 语法方面的困惑可以查看源码中的`syntax_def.lalrpop`文件 + * 语法方面的困惑可以查看源码中的`parser.lalrpop`文件 * `...: ... = ... => ...;`这种就是一个类型定义, 而`=>`前面的就是语法定义, 后方的不用管那是逻辑处理 * 例如`pub Foo: FooStruct = "!" => { ... };` * pub是可见性, 不用管 diff --git a/examples/value_bind_ref.mdtlbl b/examples/value_bind_ref.mdtlbl index 3d7c0c0..206b7af 100644 --- a/examples/value_bind_ref.mdtlbl +++ b/examples/value_bind_ref.mdtlbl @@ -5,6 +5,7 @@ * 语法大致为`Value->Name`, 并且Name的位置还可以有两个特殊值 * 如果是`..`, 那么将返回其绑定者, 这只会对箭头左边的值进行常量追溯而不是take * 如果是`$`, 那么将其take并返回其句柄, 这在一些const时想要take很好用 +* 还有一个语法糖, `Value->[...]` 应等价 `Value[...]->$` * * 返回绑定者的值只会进行常量追溯而不是进行take *# diff --git a/syntax/vim/mdtlbl.vim b/syntax/vim/mdtlbl.vim index 63c1d26..d813d5d 100644 --- a/syntax/vim/mdtlbl.vim +++ b/syntax/vim/mdtlbl.vim @@ -1,11 +1,12 @@ " Vim syntax file " Language: mindustry_logic_bang_lang (mdtlbl) " Maintainer: A4-Tacks -" Last Change: 2023-12-24 -" URL: https://github.com/A4-Tacks/mindustry_logic_bang_lang +" Last Change: 2024-05-27 +" URL: https://github.com/A4-Tacks/mindustry_logic_bang_lang +scriptencoding utf-8 " 已加载高亮时就退出 -if exists("b:current_syntax") +if exists('b:current_syntax') finish endif @@ -28,7 +29,7 @@ syn keyword mdtlblKeyword \ while gwhile do skip if elif else switch gswitch break continue \ const take setres select match \ inline - \ op set noop print + \ op noop print syn keyword mdtlblKeyword goto nextgroup=mdtlblIdentLabelRest syn keyword mdtlblKeyword case nextgroup=mdtlblStar skipwhite syn match mdtlblStar /\*/ contained @@ -46,8 +47,8 @@ syn match mdtlblCmpTreeOper /&&\|||\|!\|=>/ syn match mdtlblArgsExpand /@/ " 注释 {{{1 -syn region mdtlblComment start=/#\%([^*]\|$\)/ end=/$/ oneline contains=mdtlblCommentMeta -syn region mdtlblLongComment start=/#\*/ end=/\*#/ contains=mdtlblCommentMeta fold +syn region mdtlblComment start=/#\%([^*]\|$\)/ end=/$/ contains=mdtlblCommentMeta oneline +syn region mdtlblLongComment start=/#\*/ end=/\*#/ contains=mdtlblCommentMeta fold syn keyword mdtlblCommentMeta Todo TODO Note NOTE Hint HINT setlocal comments=s:#*,mb:*,ex:*#,:# @@ -55,11 +56,11 @@ setlocal commentstring=#%s setlocal formatoptions+=rq " 值(Var) {{{1 -syn match mdtlblStringFailedEscape /\\\%("\@=\|.\)/ contained -syn match mdtlblStringColor /\[\v%(#\x{6,8}|%(c%(lear|yan|oral)|b%(l%(ack|ue)|r%(own|ick))|white|li%(ghtgray|me)|g%(r%(ay|een)|old%(enrod)?)|darkgray|navy|r%(oyal|ed)|s%(late|ky|carlet|almon)|t%(eal|an)|acid|forest|o%(live|range)|yellow|p%(ink|urple)|ma%(genta|roon)|violet))=\]/ contained -syn match mdtlblSpecialChar /^ *\\ \|\\\%([n\\[]\|$\)/ contained -syn cluster mdtlblStringContains add=mdtlblSpecialChar,mdtlblStringFailedEscape,mdtlblStringColor -syn region mdtlblString start=/"/ end=/"/ contains=@mdtlblStringContains +syn match mdtlblStringFailedEscape /\\\%("\@=\|.\)/ contained +syn match mdtlblStringColor contained /\[\v%(#\x{6,8}|%(c%(lear|yan|oral)|b%(l%(ack|ue)|r%(own|ick))|white|li%(ghtgray|me)|g%(r%(ay|een)|old%(enrod)?)|darkgray|navy|r%(oyal|ed)|s%(late|ky|carlet|almon)|t%(eal|an)|acid|forest|o%(live|range)|yellow|p%(ink|urple)|ma%(genta|roon)|violet))=\]/ +syn match mdtlblSpecialChar /^ *\\ \|\\\%([n\\[]\|$\)/ contained +syn cluster mdtlblStringContains contains=mdtlblSpecialChar,mdtlblStringFailedEscape,mdtlblStringColor +syn region mdtlblString start=/"/ end=/"/ contains=@mdtlblStringContains syn match mdtlblOIdent /@\I\i*\%(-\i*\)*/ syn match mdtlblOtherVar /'[^' \t]\+'/ @@ -75,27 +76,28 @@ syn match mdtlblDefineResultHandle /\v%(\([%?]=)@2<=0%(x-=_@![0-9a-fA-F_]+|b-=_@ syn match mdtlblDefineResultHandle /\v%(\([%?]=)@2<=%(\I\i*|\@\I\i*%(-\i*)*|'[^' \t]+'):/ syn match mdtlblDefineResultHandle /\v%(\([%?]=)@2<="[^"]*":/ contains=@mdtlblStringContains -syn match mdtlblQuickDExpTakeIdent /\I\i*\%(\[\)\@=/ -syn match mdtlblQuickDExpTakeIdent /'[^' \t]\+'\%(\[\)\@=/ +syn match mdtlblQuickDExpTakeIdent /\v\@\I\i*%(-\i*)*%(%(-\>)=\[)@=/ +syn match mdtlblQuickDExpTakeIdent /\v\I\i*%(%(-\>)=\[)@=/ +syn match mdtlblQuickDExpTakeIdent /\v'[^' \t]+'%(%(-\>)=\[)@=/ syn match mdtlblQuickDExpTakeIdent /->/ -syn match mdtlblIdentLabel /\v%(^|\W@1<=):%(\I\i*|\@\I\i*%(-\i*)*|'[^' \t]+')/ nextgroup=mdtlblIdentLabelRest -syn match mdtlblIdentLabel /\v%(^|\W@1<=):-=_@![0-9_]+%(\._@![0-9_]+|e[+-]=-=_@![0-9_]+)=>/ nextgroup=mdtlblIdentLabelRest -syn match mdtlblIdentLabel /\v%(^|\W@1<=):0%(x-=_@![0-9a-fA-F_]+|b-=_@![01_]+)>/ nextgroup=mdtlblIdentLabelRest -syn region mdtlblIdentLabel start=/\v%(^|\W@1<=):"/ end=/"/ contains=@mdtlblStringContains +syn match mdtlblIdentLabel /\v%(^|\W@1<=):%(\I\i*|\@\I\i*%(-\i*)*|'[^' \t]+')/ nextgroup=mdtlblIdentLabelRest +syn match mdtlblIdentLabel /\v%(^|\W@1<=):-=_@![0-9_]+%(\._@![0-9_]+|e[+-]=-=_@![0-9_]+)=>/ nextgroup=mdtlblIdentLabelRest +syn match mdtlblIdentLabel /\v%(^|\W@1<=):0%(x-=_@![0-9a-fA-F_]+|b-=_@![01_]+)>/ nextgroup=mdtlblIdentLabelRest +syn region mdtlblIdentLabel start=/\v%(^|\W@1<=):"/ end=/"/ contains=@mdtlblStringContains -syn match mdtlblIdentLabelRest /\v:%(\I\i*|\@\I\i*%(-\i*)*|'[^' \t]+')/ nextgroup=mdtlblIdentLabelRest contained -syn match mdtlblIdentLabelRest /\v:-=_@![0-9_]+%(\._@![0-9_]+|e[+-]=-=_@![0-9_]+)=>/ nextgroup=mdtlblIdentLabelRest contained -syn match mdtlblIdentLabelRest /\v:0%(x-=_@![0-9a-fA-F_]+|b-=_@![01_]+)>/ nextgroup=mdtlblIdentLabelRest contained -syn region mdtlblIdentLabelRest start=/:"/ end=/"/ contains=@mdtlblStringContains contained +syn match mdtlblIdentLabelRest /\v:%(\I\i*|\@\I\i*%(-\i*)*|'[^' \t]+')/ nextgroup=mdtlblIdentLabelRest contained +syn match mdtlblIdentLabelRest /\v:-=_@![0-9_]+%(\._@![0-9_]+|e[+-]=-=_@![0-9_]+)=>/ nextgroup=mdtlblIdentLabelRest contained +syn match mdtlblIdentLabelRest /\v:0%(x-=_@![0-9a-fA-F_]+|b-=_@![01_]+)>/ nextgroup=mdtlblIdentLabelRest contained +syn region mdtlblIdentLabelRest start=/:"/ end=/"/ contains=@mdtlblStringContains contained " Fold {{{1 setlocal foldmethod=syntax -syn region mdtlblBlock start=/{/ end=/}/ transparent fold -syn region mdtlblDExp start=/(\[\@=/ end=/)/ transparent -syn region mdtlblDExp start=/(\[\@!/ end=/)/ transparent fold -syn region mdtlblArgs matchgroup=mdtlblArgsBracket start=/(\@lineFilter(line) @@ -153,27 +155,28 @@ setlocal indentkeys+==. setlocal indentkeys+=0-> " END And Color Links {{{1 -hi def link mdtlblKeyword Keyword -hi def link mdtlblStar Keyword -hi def link mdtlblOpFunKeyword Operator -hi def link mdtlblCmpTreeOper Operator -hi def link mdtlblComment Comment -hi def link mdtlblLongComment Comment -hi def link mdtlblCommentMeta Todo -hi def link mdtlblStringFailedEscape Error -hi def link mdtlblStringColor Include -hi def link mdtlblSpecialChar SpecialChar -hi def link mdtlblString String -hi def link mdtlblOIdent Identifier -hi def link mdtlblOtherVar Identifier -hi def link mdtlblNumber Number -hi def link mdtlblBoolean Boolean -hi def link mdtlblNull Boolean -hi def link mdtlblResultHandle Identifier -hi def link mdtlblDefineResultHandle Identifier -hi def link mdtlblIdentLabel Label -hi def link mdtlblIdentLabelRest mdtlblIdentLabel -hi def link mdtlblArgsBracket Macro -hi def link mdtlblQuickDExpTakeIdent Macro -hi def link mdtlblArgsExpand Structure +hi def link mdtlblKeyword Keyword +hi def link mdtlblStar Keyword +hi def link mdtlblOpFunKeyword Operator +hi def link mdtlblCmpTreeOper Operator +hi def link mdtlblComment Comment +hi def link mdtlblLongComment Comment +hi def link mdtlblCommentMeta Todo +hi def link mdtlblStringFailedEscape Error +hi def link mdtlblStringColor Include +hi def link mdtlblSpecialChar SpecialChar +hi def link mdtlblString String +hi def link mdtlblOIdent Identifier +hi def link mdtlblOtherVar Identifier +hi def link mdtlblNumber Number +hi def link mdtlblBoolean Boolean +hi def link mdtlblNull Boolean +hi def link mdtlblResultHandle Identifier +hi def link mdtlblDefineResultHandle Identifier +hi def link mdtlblIdentLabel Label +hi def link mdtlblIdentLabelRest mdtlblIdentLabel +hi def link mdtlblArgsBracket Macro +hi def link mdtlblQuickDExpTakeIdent Macro +hi def link mdtlblArgsExpand Structure " }}}1 +" vim:nowrap ts=8 sts=8 noet diff --git a/tools/display_source/Cargo.toml b/tools/display_source/Cargo.toml index 39a6c82..b67c849 100644 --- a/tools/display_source/Cargo.toml +++ b/tools/display_source/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "display_source" -version = "0.3.20" +version = "0.3.21" 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/impls.rs b/tools/display_source/src/impls.rs index d76b74e..4161211 100644 --- a/tools/display_source/src/impls.rs +++ b/tools/display_source/src/impls.rs @@ -868,25 +868,25 @@ fn display_source_test() { parse!(line_parser, "print ($ = x;);") .unwrap() .display_source_and_get(&mut meta), - "`'print'` (`'set'` $ x;);" + "`'print'` (`set` $ x;);" ); assert_eq!( parse!(line_parser, "print (res: $ = x;);") .unwrap() .display_source_and_get(&mut meta), - "`'print'` (res: `'set'` $ x;);" + "`'print'` (res: `set` $ x;);" ); assert_eq!( parse!(line_parser, "print (noop;$ = x;);") .unwrap() .display_source_and_get(&mut meta), - "`'print'` (\n noop;\n `'set'` $ x;\n);" + "`'print'` (\n noop;\n `set` $ x;\n);" ); assert_eq!( parse!(line_parser, "print (res: noop;$ = x;);") .unwrap() .display_source_and_get(&mut meta), - "`'print'` (res:\n noop;\n `'set'` $ x;\n);" + "`'print'` (res:\n noop;\n `set` $ x;\n);" ); assert_eq!( parse!(line_parser, "print a.b.c;") @@ -922,7 +922,7 @@ fn display_source_test() { parse!(line_parser, "'take' 'set' 'print' 'const' 'take' 'op';") .unwrap() .display_source_and_get(&mut meta), - "'take' 'set' 'print' 'const' 'take' 'op';" + "'take' set 'print' 'const' 'take' 'op';" ); assert_eq!( parse!(jumpcmp_parser, "({take X = N;} => X > 10 && X < 50)") @@ -958,7 +958,7 @@ fn display_source_test() { parse!(line_parser, r#"set a "\n\\\[hi]\\n";"#) .unwrap() .display_source_and_get(&mut meta), - r#"`'set'` a "\n\\[[hi]\\n";"# + r#"set a "\n\\[[hi]\\n";"# ); assert_eq!( parse!(line_parser, r#"foo bar baz;"#) diff --git a/tools/parser/Cargo.toml b/tools/parser/Cargo.toml index 9a26712..55642a3 100644 --- a/tools/parser/Cargo.toml +++ b/tools/parser/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "parser" -version = "0.3.13" +version = "0.3.14" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tools/parser/src/parser.lalrpop b/tools/parser/src/parser.lalrpop index c5bd7dd..544cf04 100644 --- a/tools/parser/src/parser.lalrpop +++ b/tools/parser/src/parser.lalrpop @@ -90,6 +90,13 @@ OOCArgs: Vec = { Span = @L T @R; #[inline] Opt: bool = T? => <>.is_some(); +#[inline] +MakeDExpBody: DExp = { + ":")?> + => DExp::new_optional_res(var, value.into()), + "`" "`" ":" + => DExp::new_notake(var, value.into()), +} CtrlBreakStart: () = () => meta.add_control_break_level(None); CtrlContinueStart: () = () => meta.add_control_continue_level(None); @@ -148,11 +155,11 @@ NonConstRangeValue: Value = { ConstKey => <>.into(), "`" "`" => ReprVar(<>), // 原始值 "$" => ResultHandle, - > => { + > => { // QuickDExpTake DExp::new("__".into(), vec![ LogicLine::SetArgs(args.unwrap_or_default()), - LogicLine::SetResultHandle(name), + LogicLine::SetResultHandle(value), ].into()).into() }, "goto" > => Value::Cmper(<>.into()), @@ -171,6 +178,18 @@ NonConstRangeValue: Value = { "->" "$" => { ValueBindRef::new(<>.into(), ValueBindRefTarget::ResultHandle).into() }, + "->" > => { + // Refed QuickDExpTake + let value = DExp::new("__".into(), vec![ + LogicLine::SetArgs(args.unwrap_or_default()), + LogicLine::SetResultHandle(value), + ].into()).into(); + + ValueBindRef::new( + Box::new(value), + ValueBindRefTarget::ResultHandle, + ).into() + }, } pub Value: Value = { @@ -333,12 +352,10 @@ pub LogicLine: LogicLine = { Label => LogicLine::new_label(<>, meta), "op" LEnd => <>.into(), "noop" LEnd => LogicLine::NoOp, - "set" LEnd => Meta::build_set(<>), "=" LEnd =>? Meta::build_sets([l, r], vars, values).map_err(|e| e.into()), OpExpr, Print, - //ArgsRepeatBlock => <>.into(), LEnd => LogicLine::Other(<>), "inline" => <>.into(), Match => <>.into(), @@ -541,11 +558,12 @@ OpExpr: LogicLine = { }, LEnd => <>.into(), } -OpExprDExp: DExp = METuple<(( ":")? OpExprBody)> => { - let (res, body) = <>; - let line = op_expr_build_results(meta, vec![ResultHandle], vec![body]); - DExp::new_optional_res(res, vec![line].into()) +#[inline] +OpExprBodySetR: Expand = OpExprBody => { + let line = op_expr_build_results(meta, vec![ResultHandle], vec![<>]); + vec![line].into() }; +OpExprDExp: DExp = METuple>; IOpExpr: Expand = { "+=" => { let tmp = meta.get_tmp_var(); vec![Take(tmp.clone().into(), v).into(), Op::Add (tmp.clone().into(), tmp.into(), r.into_value(meta)).into()].into() }, @@ -844,10 +862,8 @@ pub BuiltinCommand: LogicLine = { BlockExpand: Expand = MBlock => <>; pub Block: LogicLine = BlockExpand => <>.into(); -pub DExp: DExp = MTuple<(<( ":")?> )> - => DExp::new_optional_res(<>.0, <>.1); -FEDExp: DExp = MFETuple<(<( ":")?> )> - => DExp::new_optional_res(<>.0, <>.1); +pub DExp: DExp = MTuple>; +FEDExp: DExp = MFETuple>; #[inline] ValueDExp: Value = DExp => <>.into(); diff --git a/tools/parser/tests/Cargo.toml b/tools/parser/tests/Cargo.toml index 228f049..5444d40 100644 --- a/tools/parser/tests/Cargo.toml +++ b/tools/parser/tests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "parser-tests" -version = "0.1.27" +version = "0.1.28" 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 a89aae7..cc4a30d 100644 --- a/tools/parser/tests/src/lib.rs +++ b/tools/parser/tests/src/lib.rs @@ -2174,6 +2174,15 @@ fn quick_dexp_take_test() { "print __3", ]); + assert_eq!( + parse!(parser, r#" + const V = F->[A B C @]->V; + "#).unwrap(), + parse!(parser, r#" + const V = F[A B C @]->$->V; + "#).unwrap(), + ); + } #[test] @@ -3365,7 +3374,7 @@ fn op_expr_if_else_test() { { take ___0 = a; goto :___0 b < c; - set ___0 c; + `set` ___0 c; goto :___1 _; :___0 op ___0 b + 2; @@ -3382,7 +3391,7 @@ fn op_expr_if_else_test() { { take ___0 = a; goto :___0 b < c; - set ___0 c; + `set` ___0 c; goto :___1 _; :___0 op ___0 b + 2; @@ -3405,7 +3414,7 @@ fn op_expr_if_else_test() { op ___0 c - 2; goto :___1 _; :___0 - set ___0 8; + `set` ___0 8; :___1 } goto :___3 _; @@ -3424,10 +3433,10 @@ fn op_expr_if_else_test() { op a 1 + ( take ___0 = $; goto :___0 b; - set ___0 d; + `set` ___0 d; goto :___1 _; :___0 - set ___0 c; + `set` ___0 c; :___1 ); "#).unwrap() @@ -4145,7 +4154,7 @@ fn const_expr_eval_test() { assert_eq!( CompileMeta::new().compile(parse!(parser, r#" - print ($ = (set $ ($ = 1 + 1;););); + print ($ = (`set` $ ($ = 1 + 1;););); "#).unwrap()).compile().unwrap(), CompileMeta::new().compile(parse!(parser, r#" print 2; @@ -6746,3 +6755,51 @@ fn closure_catch_label_test() { ], ); } + +#[test] +fn non_take_result_handle_dexp_test() { + let parser = TopLevelParser::new(); + + assert_eq!( + CompileMeta::new().compile(parse!(parser, r#" + const H = 2; + print (H: print pre;); + "#).unwrap()).compile().unwrap(), + vec![ + r#"print pre"#, + r#"print 2"#, + ], + ); + + assert_eq!( + CompileMeta::new().compile(parse!(parser, r#" + const H = 2; + print (`H`: print pre;); + "#).unwrap()).compile().unwrap(), + vec![ + r#"print pre"#, + r#"print H"#, + ], + ); + + assert_eq!( + CompileMeta::new().compile(parse!(parser, r#" + const H = (2:); + print (`H`: print pre;); + "#).unwrap()).compile().unwrap(), + vec![ + r#"print pre"#, + r#"print H"#, + ], + ); + + assert_eq!( + CompileMeta::new().compile(parse!(parser, r#" + print (?`n`: 2); + "#).unwrap()).compile().unwrap(), + vec![ + r#"set n 2"#, + r#"print n"#, + ], + ); +} diff --git a/tools/syntax/Cargo.toml b/tools/syntax/Cargo.toml index 203aad5..4a31c6f 100644 --- a/tools/syntax/Cargo.toml +++ b/tools/syntax/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "syntax" -version = "0.2.32" +version = "0.2.33" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tools/syntax/src/lib.rs b/tools/syntax/src/lib.rs index 048c370..3ea7e83 100644 --- a/tools/syntax/src/lib.rs +++ b/tools/syntax/src/lib.rs @@ -278,26 +278,33 @@ pub const UNUSED_VAR: &str = "0"; pub trait TakeHandle: Sized { /// 编译依赖并返回句柄 fn take_handle(self, meta: &mut CompileMeta) -> Var; - /// 编译并拿取句柄, 但是是在被const的值的情况下 - fn take_handle_with_consted(self, meta: &mut CompileMeta) -> Var { - self.take_handle(meta) - } } impl TakeHandle for Var { fn take_handle(self, meta: &mut CompileMeta) -> Var { if let Some(value) = meta.const_expand_enter(&self) { // 是一个常量 - let res = value.clone().take_handle_with_consted(meta); + let res = match value.clone() { + Value::Var(var) => var, + Value::ReprVar(var) => { + panic!("Fail const reprvar {}, meta: {:#?}", var, meta); + }, + Value::ClosuredValue(clos @ ClosuredValue::Uninit { .. }) => { + panic!("\ + 未捕获闭包不应以常量追溯目标被take, \ + 它应是直接take或者追溯时被替换成了其它值.\n\ + {:?}", + clos, + ) + }, + value => value.take_handle(meta), + }; meta.const_expand_exit(); res } else { self } } - fn take_handle_with_consted(self, _meta: &mut CompileMeta) -> Var { - self - } } #[derive(Debug, PartialEq, Clone)] @@ -403,18 +410,6 @@ impl TakeHandle for Value { Self::BuiltinFunc(func) => func.call(meta), } } - fn take_handle_with_consted(self, meta: &mut CompileMeta) -> Var { - if let Some(var) = self.try_eval_const_num_to_var(meta) { - return var; - } - match self { - Self::Var(var) => var, - Self::ReprVar(var) => { - panic!("Fail const reprvar {}, meta: {:#?}", var, meta); - }, - other => other.take_handle(meta), - } - } } impl Default for Value { /// 默认的占位值, 它是无副作用的, 不会被常量展开 @@ -669,6 +664,35 @@ where I: IntoIterator, } } +trait BoolOpsExtend: Sized { + fn and_then(self, f: F) -> Option + where F: FnOnce() -> Option; + + fn or_else(self, f: F) -> Option + where F: FnOnce() -> Option; +} +impl BoolOpsExtend for bool { + fn and_then(self, f: F) -> Option + where F: FnOnce() -> Option, + { + if self { + f() + } else { + None + } + } + + fn or_else(self, f: F) -> Option + where F: FnOnce() -> Option, + { + if self { + None + } else { + f() + } + } +} + /// 在常量追溯时就发生绑定追溯, 而不是take时 /// 不会take追溯到的值 /// @@ -733,11 +757,6 @@ impl TakeHandle for ValueBindRef { }, } } - fn take_handle_with_consted(self, _meta: &mut CompileMeta) -> Var { - panic!("它不应以常量追溯目标被take, \ - 它应是直接take或者追溯时被替换成了其它值.\n\ - {:?}", self) - } } #[derive(Debug, PartialEq, Clone)] pub enum ValueBindRefTarget { @@ -903,30 +922,42 @@ impl TakeHandle for ClosuredValue { /// 其依赖被计算完毕后, 句柄有效 #[derive(Debug, PartialEq, Clone)] pub struct DExp { + take_result: bool, result: Var, lines: Expand, } impl DExp { pub fn new(result: Var, lines: Expand) -> Self { - Self { result, lines } + Self::new_optional_res(result.into(), lines) + } + + pub fn new_notake(result: Var, lines: Expand) -> Self { + Self::new_optional_res_notake(result.into(), lines) } /// 新建一个可能指定返回值的DExp pub fn new_optional_res(result: Option, lines: Expand) -> Self { Self { + take_result: true, result: result.unwrap_or_default(), lines } } - /// 新建一个未指定返回值的DExp - pub fn new_nores(lines: Expand) -> Self { + /// 新建一个可能指定返回值的DExp, 但不take它 + pub fn new_optional_res_notake(result: Option, lines: Expand) -> Self { Self { - result: default(), + take_result: false, + result: result.unwrap_or_default(), lines } } + /// 新建一个未指定返回值的DExp + pub fn new_nores(lines: Expand) -> Self { + Self::new_optional_res(None, lines) + } + pub fn result(&self) -> &str { self.result.as_ref() } @@ -941,30 +972,34 @@ impl DExp { } impl TakeHandle for DExp { fn take_handle(self, meta: &mut CompileMeta) -> Var { - let DExp { mut result, lines } = self; + let DExp { take_result, mut result, lines } = self; let dexp_res_is_alloced = result.is_empty(); if dexp_res_is_alloced { result = meta.get_tmp_var(); /* init tmp_var */ - } else if let Some(ConstData { value, .. }) - = meta.get_const_value(&result) { - // 对返回句柄使用常量值的处理 - if !value.is_var() { - err!( - concat!( - "{}\n尝试在`DExp`的返回句柄处使用值不为Var的const, ", - "此处仅允许使用`Var`\n", - "值: {}\n", - "名称: {:?}", - ), - meta.err_info().join("\n"), - value.display_src(meta), - result - ); - exit(5); + } else if take_result { + if let Some(ConstData { value, .. }) + = meta.get_const_value(&result) + { + // 对返回句柄使用常量值的处理 + if !value.is_var() { + err!( + concat!( + "{}\n\ + 尝试在`DExp`的返回句柄处使用值不为Var的const, ", + "此处仅允许使用`Var`\n", + "值: {}\n", + "名称: {}", + ), + meta.err_info().join("\n"), + value.display_src(meta), + result.display_src(meta), + ); + exit(5); + } + assert!(value.is_var()); + result = value.as_var().unwrap().clone() } - assert!(value.is_var()); - result = value.as_var().unwrap().clone() } assert!(! result.is_empty()); meta.push_dexp_handle(result); @@ -1577,29 +1612,25 @@ impl CmpTree { // 二级展开 A=0; B=(A:); use B; | Some(ConstData { value: V::DExp(DExp { + take_result, result: s, lines }), .. - }) => { - if lines.is_empty() { - f(meta, s) - } else { - None - } - }, + }) => take_result.then_some(&***s) + .or_else(|| lines.is_empty() + .and_then(|| f(meta, s))), Some(_) => None, None => Some(&**s), } }, - | V::DExp(DExp { result: s, lines }) - => { - if lines.is_empty() { - f(meta, s) - } else { - None - } - }, + | V::DExp(DExp { + take_result, + result: s, + lines, + }) => take_result.then_some(&***s) + .or_else(|| lines.is_empty() + .and_then(|| f(meta, s))), | V::ReprVar(s) => Some(&**s), | V::ResultHandle diff --git a/tools/var_utils/Cargo.toml b/tools/var_utils/Cargo.toml index df2b6bf..65dde11 100644 --- a/tools/var_utils/Cargo.toml +++ b/tools/var_utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "var_utils" -version = "0.5.2" +version = "0.5.3" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tools/var_utils/src/lib.rs b/tools/var_utils/src/lib.rs index 1bbb8fd..325aee7 100644 --- a/tools/var_utils/src/lib.rs +++ b/tools/var_utils/src/lib.rs @@ -20,8 +20,8 @@ pub const VAR_KEYWORDS: &[&str] = {&[ "goto", "greaterThan", "greaterThanEq", "gwhile", "idiv", "if", "inline", "land", "len", "lessThan", "lessThanEq", "lnot", "log", "match", "max", "min", "mod", "mul", "noise", "noop", "not", "notEqual", - "op", "or", "pow", "print", "rand", "select", "set", - "setres", "shl", "shr", "sin", "skip", "sqrt", "strictEqual", + "op", "or", "pow", "print", "rand", "select", "setres", + "shl", "shr", "sin", "skip", "sqrt", "strictEqual", "strictNotEqual", "sub", "switch", "take", "tan", "while", "xor", ]};