@@ -280,6 +280,14 @@ impl Meta {
280280 pub fn pop_label_scope ( & mut self ) -> Vec < Var > {
281281 self . defined_labels . pop ( ) . unwrap ( )
282282 }
283+
284+ /// 根据一系列构建一系列常量传参
285+ pub fn build_arg_consts ( & self , values : Vec < Value > , mut f : impl FnMut ( Const ) ) {
286+ for ( i, value) in values. into_iter ( ) . enumerate ( ) {
287+ let name = format ! ( "_{}" , i) ;
288+ f ( Const ( name, value, Vec :: with_capacity ( 0 ) ) )
289+ }
290+ }
283291}
284292
285293/// `jump`可用判断条件枚举
@@ -653,6 +661,7 @@ pub enum LogicLine {
653661 Ignore ,
654662 Const ( Const ) ,
655663 Take ( Take ) ,
664+ ConstLeak ( Var ) ,
656665}
657666impl Compile for LogicLine {
658667 fn compile ( self , meta : & mut CompileMeta ) {
@@ -678,6 +687,7 @@ impl Compile for LogicLine {
678687 Self :: Ignore => ( ) ,
679688 Self :: Const ( r#const) => r#const. compile ( meta) ,
680689 Self :: Take ( take) => take. compile ( meta) ,
690+ Self :: ConstLeak ( r#const) => meta. add_const_value_leak ( r#const) ,
681691 }
682692 }
683693}
@@ -807,9 +817,11 @@ pub struct CompileMeta {
807817 tag_count : usize ,
808818 tag_codes : TagCodes ,
809819 tmp_var_count : usize ,
810- /// # 块中宏, 且带有展开次数与内部标记
811- /// `Vec<HashMap<name, (count, Vec<Label>, Value)>>`
812- const_var_namespace : Vec < HashMap < Var , ( usize , Vec < Var > , Value ) > > ,
820+ /// 块中常量, 且带有展开次数与内部标记
821+ /// 并且存储了需要泄露的常量
822+ ///
823+ /// `Vec<(leaks, HashMap<name, (count, Vec<Label>, Value)>)>`
824+ const_var_namespace : Vec < ( Vec < Var > , HashMap < Var , ( usize , Vec < Var > , Value ) > ) > ,
813825 /// 每层DExp所使用的句柄, 末尾为当前层
814826 dexp_result_handles : Vec < Var > ,
815827 tmp_tag_count : usize ,
@@ -905,14 +917,39 @@ impl CompileMeta {
905917
906918 /// 进入一个子块, 创建一个新的子命名空间
907919 pub fn block_enter ( & mut self ) {
908- self . const_var_namespace . push ( HashMap :: new ( ) )
920+ self . const_var_namespace . push ( ( Vec :: new ( ) , HashMap :: new ( ) ) )
909921 }
910922
911923 /// 退出一个子块, 弹出最顶层命名空间
912924 /// 如果无物可弹说明逻辑出现了问题, 所以内部处理为unwrap
913925 /// 一个enter对应一个exit
914926 pub fn block_exit ( & mut self ) -> HashMap < Var , ( usize , Vec < Var > , Value ) > {
915- self . const_var_namespace . pop ( ) . unwrap ( )
927+ // this is poped block
928+ let ( leaks, mut res)
929+ = self . const_var_namespace . pop ( ) . unwrap ( ) ;
930+
931+ // do leak
932+ for leak_const_name in leaks {
933+ let value
934+ = res. remove ( & leak_const_name) . unwrap ( ) ;
935+
936+ // insert to prev block
937+ self . const_var_namespace
938+ . last_mut ( )
939+ . unwrap ( )
940+ . 1
941+ . insert ( leak_const_name, value) ;
942+ }
943+ res
944+ }
945+
946+ /// 添加一个需泄露的const
947+ pub fn add_const_value_leak ( & mut self , name : Var ) {
948+ self . const_var_namespace
949+ . last_mut ( )
950+ . unwrap ( )
951+ . 0
952+ . push ( name)
916953 }
917954
918955 /// 获取一个常量到值的使用次数与映射与其内部标记的引用,
@@ -921,7 +958,7 @@ impl CompileMeta {
921958 self . const_var_namespace
922959 . iter ( )
923960 . rev ( )
924- . find_map ( |namespace| {
961+ . find_map ( |( _ , namespace) | {
925962 namespace. get ( name)
926963 } )
927964 }
@@ -933,7 +970,7 @@ impl CompileMeta {
933970 self . const_var_namespace
934971 . iter_mut ( )
935972 . rev ( )
936- . find_map ( |namespace| {
973+ . find_map ( |( _ , namespace) | {
937974 namespace. get_mut ( name)
938975 } )
939976 }
@@ -961,6 +998,7 @@ impl CompileMeta {
961998 self . const_var_namespace
962999 . last_mut ( )
9631000 . unwrap ( )
1001+ . 1
9641002 . insert ( var, ( 0 , labels, value) )
9651003 }
9661004
@@ -1784,4 +1822,151 @@ mod tests {
17841822 let mut tag_codes = meta. compile ( ast) ;
17851823 let _logic_lines = tag_codes. compile ( ) . unwrap ( ) ;
17861824 }
1825+
1826+ #[ test]
1827+ fn take_default_result_test ( ) {
1828+ let parser = LogicLineParser :: new ( ) ;
1829+
1830+ let ast = parse ! ( parser, "take 2;" ) . unwrap ( ) ;
1831+ assert_eq ! ( ast, Take ( "__" . into( ) , "2" . into( ) ) . into( ) ) ;
1832+ }
1833+
1834+ #[ test]
1835+ fn const_value_leak_test ( ) {
1836+ let ast: Expand = vec ! [
1837+ Expand ( vec![
1838+ LogicLine :: Other ( vec![ "print" . into( ) , "N" . into( ) ] ) ,
1839+ Const ( "N" . into( ) , "2" . into( ) , Vec :: new( ) ) . into( ) ,
1840+ LogicLine :: Other ( vec![ "print" . into( ) , "N" . into( ) ] ) ,
1841+ ] ) . into( ) ,
1842+ LogicLine :: Other ( vec![ "print" . into( ) , "N" . into( ) ] ) ,
1843+ ] . into ( ) ;
1844+ let meta = CompileMeta :: new ( ) ;
1845+ let mut tag_codes = meta. compile ( ast) ;
1846+ let logic_lines = tag_codes. compile ( ) . unwrap ( ) ;
1847+ assert_eq ! ( logic_lines, vec![
1848+ "print N" ,
1849+ "print 2" ,
1850+ "print N" ,
1851+ ] ) ;
1852+
1853+ let ast: Expand = vec ! [
1854+ Expand ( vec![
1855+ LogicLine :: Other ( vec![ "print" . into( ) , "N" . into( ) ] ) ,
1856+ Const ( "N" . into( ) , "2" . into( ) , Vec :: new( ) ) . into( ) ,
1857+ LogicLine :: Other ( vec![ "print" . into( ) , "N" . into( ) ] ) ,
1858+ LogicLine :: ConstLeak ( "N" . into( ) ) ,
1859+ ] ) . into( ) ,
1860+ LogicLine :: Other ( vec![ "print" . into( ) , "N" . into( ) ] ) ,
1861+ ] . into ( ) ;
1862+ let meta = CompileMeta :: new ( ) ;
1863+ let mut tag_codes = meta. compile ( ast) ;
1864+ let logic_lines = tag_codes. compile ( ) . unwrap ( ) ;
1865+ assert_eq ! ( logic_lines, vec![
1866+ "print N" ,
1867+ "print 2" ,
1868+ "print 2" ,
1869+ ] ) ;
1870+ }
1871+
1872+ #[ test]
1873+ fn take_test2 ( ) {
1874+ let parser = LogicLineParser :: new ( ) ;
1875+
1876+ let ast = parse ! ( parser, "take X;" ) . unwrap ( ) ;
1877+ assert_eq ! ( ast, Take ( "__" . into( ) , "X" . into( ) ) . into( ) ) ;
1878+
1879+ let ast = parse ! ( parser, "take R = X;" ) . unwrap ( ) ;
1880+ assert_eq ! ( ast, Take ( "R" . into( ) , "X" . into( ) ) . into( ) ) ;
1881+
1882+ let ast = parse ! ( parser, "take[] X;" ) . unwrap ( ) ;
1883+ assert_eq ! ( ast, Take ( "__" . into( ) , "X" . into( ) ) . into( ) ) ;
1884+
1885+ let ast = parse ! ( parser, "take[] R = X;" ) . unwrap ( ) ;
1886+ assert_eq ! ( ast, Take ( "R" . into( ) , "X" . into( ) ) . into( ) ) ;
1887+
1888+ let ast = parse ! ( parser, "take[1 2] R = X;" ) . unwrap ( ) ;
1889+ assert_eq ! ( ast, Expand ( vec![
1890+ Const :: new( "_0" . into( ) , "1" . into( ) ) . into( ) ,
1891+ Const :: new( "_1" . into( ) , "2" . into( ) ) . into( ) ,
1892+ Take ( "R" . into( ) , "X" . into( ) ) . into( ) ,
1893+ LogicLine :: ConstLeak ( "R" . into( ) ) ,
1894+ ] ) . into( ) ) ;
1895+
1896+ let ast = parse ! ( parser, "take[1 2] X;" ) . unwrap ( ) ;
1897+ assert_eq ! ( ast, Expand ( vec![
1898+ Const :: new( "_0" . into( ) , "1" . into( ) ) . into( ) ,
1899+ Const :: new( "_1" . into( ) , "2" . into( ) ) . into( ) ,
1900+ Take ( "__" . into( ) , "X" . into( ) ) . into( ) ,
1901+ ] ) . into( ) ) ;
1902+ }
1903+
1904+ #[ test]
1905+ fn take_args_test ( ) {
1906+ let parser = ExpandParser :: new ( ) ;
1907+
1908+ let ast = parse ! ( parser, r#"
1909+ const M = (
1910+ print _0 _1 _2;
1911+ set $ 3;
1912+ );
1913+ take[1 2 3] M;
1914+ take[4 5 6] R = M;
1915+ print R;
1916+ "# ) . unwrap ( ) ;
1917+ let meta = CompileMeta :: new ( ) ;
1918+ let mut tag_codes = meta. compile ( ast) ;
1919+ let logic_lines = tag_codes. compile ( ) . unwrap ( ) ;
1920+ assert_eq ! ( logic_lines, vec![
1921+ "print 1" ,
1922+ "print 2" ,
1923+ "print 3" ,
1924+ "set __0 3" ,
1925+ "print 4" ,
1926+ "print 5" ,
1927+ "print 6" ,
1928+ "set __1 3" ,
1929+ "print __1" ,
1930+ ] ) ;
1931+
1932+ let ast = parse ! ( parser, r#"
1933+ const DO = (
1934+ print _0 "start";
1935+ take _1;
1936+ print _0 "start*2";
1937+ take _1;
1938+ printflush message1;
1939+ );
1940+ # 这里赋给一个常量再使用, 因为直接使用不会记录label, 无法重复被使用
1941+ # 而DO中, 会使用两次传入的参数1
1942+ const F = (
1943+ i = 0;
1944+ while i < 10 {
1945+ print i;
1946+ op i i + 1;
1947+ }
1948+ );
1949+ take["loop" F] DO;
1950+ "# ) . unwrap ( ) ;
1951+ let meta = CompileMeta :: new ( ) ;
1952+ let mut tag_codes = meta. compile ( ast) ;
1953+ let logic_lines = tag_codes. compile ( ) . unwrap ( ) ;
1954+ assert_eq ! ( logic_lines, vec![
1955+ r#"print "loop""# ,
1956+ r#"print "start""# ,
1957+ r#"set i 0"# ,
1958+ r#"jump 7 greaterThanEq i 10"# ,
1959+ r#"print i"# ,
1960+ r#"op add i i 1"# ,
1961+ r#"jump 4 lessThan i 10"# ,
1962+ r#"print "loop""# ,
1963+ r#"print "start*2""# ,
1964+ r#"set i 0"# ,
1965+ r#"jump 14 greaterThanEq i 10"# ,
1966+ r#"print i"# ,
1967+ r#"op add i i 1"# ,
1968+ r#"jump 11 lessThan i 10"# ,
1969+ r#"printflush message1"# ,
1970+ ] ) ;
1971+ }
17871972}
0 commit comments