@@ -360,12 +360,7 @@ fn check_block_scoping(block: &[Line], ctx: &mut Context) {
360360 for line in block. iter ( ) {
361361 match line {
362362 Line :: ForwardDeclaration { var } => {
363- let last_scope = ctx. scopes . last_mut ( ) . unwrap ( ) ;
364- assert ! (
365- !last_scope. vars. contains( var) ,
366- "Variable declared multiple times in the same scope: {var}" ,
367- ) ;
368- last_scope. vars . insert ( var. clone ( ) ) ;
363+ ctx. add_var ( var) ;
369364 }
370365 Line :: Match { value, arms } => {
371366 check_expr_scoping ( value, ctx) ;
@@ -377,12 +372,9 @@ fn check_block_scoping(block: &[Line], ctx: &mut Context) {
377372 }
378373 Line :: Assignment { var, value } => {
379374 check_expr_scoping ( value, ctx) ;
380- let last_scope = ctx. scopes . last_mut ( ) . unwrap ( ) ;
381- assert ! (
382- !last_scope. vars. contains( var) ,
383- "Variable declared multiple times in the same scope: {var}" ,
384- ) ;
385- last_scope. vars . insert ( var. clone ( ) ) ;
375+ if !ctx. defines ( var) {
376+ ctx. add_var ( var) ;
377+ }
386378 }
387379 Line :: ArrayAssign { array, index, value } => {
388380 check_simple_expr_scoping ( array, ctx) ;
@@ -431,15 +423,12 @@ fn check_block_scoping(block: &[Line], ctx: &mut Context) {
431423 for arg in args {
432424 check_expr_scoping ( arg, ctx) ;
433425 }
434- let last_scope = ctx. scopes . last_mut ( ) . unwrap ( ) ;
435426 for target in return_data {
436427 match target {
437428 AssignmentTarget :: Var ( var) => {
438- assert ! (
439- !last_scope. vars. contains( var) ,
440- "Variable declared multiple times in the same scope: {var}" ,
441- ) ;
442- last_scope. vars . insert ( var. clone ( ) ) ;
429+ if !ctx. defines ( var) {
430+ ctx. add_var ( var) ;
431+ }
443432 }
444433 AssignmentTarget :: ArrayAccess { .. } => { }
445434 }
@@ -478,36 +467,25 @@ fn check_block_scoping(block: &[Line], ctx: &mut Context) {
478467 } => {
479468 check_expr_scoping ( size, ctx) ;
480469 check_expr_scoping ( vectorized_len, ctx) ;
481- let last_scope = ctx. scopes . last_mut ( ) . unwrap ( ) ;
482- assert ! (
483- !last_scope. vars. contains( var) ,
484- "Variable declared multiple times in the same scope: {var}" ,
485- ) ;
486- last_scope. vars . insert ( var. clone ( ) ) ;
470+ if !ctx. defines ( var) {
471+ ctx. add_var ( var) ;
472+ }
487473 }
488474 Line :: DecomposeBits { var, to_decompose } => {
489475 for expr in to_decompose {
490476 check_expr_scoping ( expr, ctx) ;
491477 }
492- let last_scope = ctx. scopes . last_mut ( ) . unwrap ( ) ;
493- assert ! (
494- !last_scope. vars. contains( var) ,
495- "Variable declared multiple times in the same scope: {var}" ,
496- ) ;
497- last_scope. vars . insert ( var. clone ( ) ) ;
478+ if !ctx. defines ( var) {
479+ ctx. add_var ( var) ;
480+ }
498481 }
499482 Line :: DecomposeCustom { args } => {
500483 for arg in args {
501484 check_expr_scoping ( arg, ctx) ;
502485 }
503486 }
504487 Line :: PrivateInputStart { result } => {
505- let last_scope = ctx. scopes . last_mut ( ) . unwrap ( ) ;
506- assert ! (
507- !last_scope. vars. contains( result) ,
508- "Variable declared multiple times in the same scope: {result}"
509- ) ;
510- last_scope. vars . insert ( result. clone ( ) ) ;
488+ ctx. add_var ( result) ;
511489 }
512490 }
513491 }
@@ -1973,7 +1951,17 @@ fn handle_inlined_functions(program: &mut Program) {
19731951 let mut counter2 = Counter :: new ( ) ;
19741952 let old_body = func. body . clone ( ) ;
19751953
1976- handle_inlined_functions_helper ( & mut func. body , & inlined_functions, & mut counter1, & mut counter2) ;
1954+ let mut ctx = Context :: new ( ) ;
1955+ for ( var, _) in func. arguments . iter ( ) {
1956+ ctx. add_var ( var) ;
1957+ }
1958+ func. body = handle_inlined_functions_helper (
1959+ & mut ctx,
1960+ & func. body ,
1961+ & inlined_functions,
1962+ & mut counter1,
1963+ & mut counter2,
1964+ ) ;
19771965
19781966 if func. body != old_body {
19791967 any_changes = true ;
@@ -1989,7 +1977,17 @@ fn handle_inlined_functions(program: &mut Program) {
19891977 let mut counter2 = Counter :: new ( ) ;
19901978 let old_body = func. body . clone ( ) ;
19911979
1992- handle_inlined_functions_helper ( & mut func. body , & inlined_functions, & mut counter1, & mut counter2) ;
1980+ let mut ctx = Context :: new ( ) ;
1981+ for ( var, _) in func. arguments . iter ( ) {
1982+ ctx. add_var ( var) ;
1983+ }
1984+ handle_inlined_functions_helper (
1985+ & mut ctx,
1986+ & func. body ,
1987+ & inlined_functions,
1988+ & mut counter1,
1989+ & mut counter2,
1990+ ) ;
19931991
19941992 if func. body != old_body {
19951993 any_changes = true ;
@@ -2013,13 +2011,43 @@ fn handle_inlined_functions(program: &mut Program) {
20132011}
20142012
20152013fn handle_inlined_functions_helper (
2016- lines : & mut Vec < Line > ,
2014+ ctx : & mut Context ,
2015+ lines_in : & Vec < Line > ,
20172016 inlined_functions : & BTreeMap < String , Function > ,
20182017 inlined_var_counter : & mut Counter ,
20192018 total_inlined_counter : & mut Counter ,
2020- ) {
2021- for i in ( 0 ..lines. len ( ) ) . rev ( ) {
2022- match & mut lines[ i] {
2019+ ) -> Vec < Line > {
2020+ let mut lines_out: Vec < Line > = Vec :: new ( ) ;
2021+ for line in lines_in {
2022+ match line {
2023+ Line :: ForwardDeclaration { var } => {
2024+ lines_out. push ( line. clone ( ) ) ;
2025+ ctx. add_var ( var) ;
2026+ }
2027+ Line :: Assignment { var, .. } => {
2028+ lines_out. push ( line. clone ( ) ) ;
2029+ if !ctx. defines ( var) {
2030+ ctx. add_var ( var) ;
2031+ }
2032+ }
2033+ Line :: DecomposeBits { var, .. } => {
2034+ lines_out. push ( line. clone ( ) ) ;
2035+ if !ctx. defines ( var) {
2036+ ctx. add_var ( var) ;
2037+ }
2038+ }
2039+ Line :: PrivateInputStart { result } => {
2040+ lines_out. push ( line. clone ( ) ) ;
2041+ if !ctx. defines ( result) {
2042+ ctx. add_var ( result) ;
2043+ }
2044+ }
2045+ Line :: MAlloc { var, .. } => {
2046+ lines_out. push ( line. clone ( ) ) ;
2047+ if !ctx. defines ( var) {
2048+ ctx. add_var ( var) ;
2049+ }
2050+ }
20232051 Line :: FunctionCall {
20242052 function_name,
20252053 args,
@@ -2031,8 +2059,11 @@ fn handle_inlined_functions_helper(
20312059
20322060 // Only add forward declarations for variable targets, not array accesses
20332061 for target in return_data. iter ( ) {
2034- if let AssignmentTarget :: Var ( var) = target {
2062+ if let AssignmentTarget :: Var ( var) = target
2063+ && !ctx. defines ( var)
2064+ {
20352065 inlined_lines. push ( Line :: ForwardDeclaration { var : var. clone ( ) } ) ;
2066+ ctx. add_var ( var) ;
20362067 }
20372068 }
20382069
@@ -2059,40 +2090,96 @@ fn handle_inlined_functions_helper(
20592090 let mut func_body = func. body . clone ( ) ;
20602091 inline_lines ( & mut func_body, & inlined_args, return_data, total_inlined_counter. next ( ) ) ;
20612092 inlined_lines. extend ( func_body) ;
2062-
2063- lines . remove ( i ) ; // remove the call to the inlined function
2064- lines . splice ( i..i , inlined_lines ) ;
2093+ lines_out . extend ( inlined_lines ) ;
2094+ } else {
2095+ lines_out . push ( line . clone ( ) ) ;
20652096 }
20662097 }
20672098 Line :: IfCondition {
2099+ condition,
20682100 then_branch,
20692101 else_branch,
2070- ..
2102+ line_number ,
20712103 } => {
2072- handle_inlined_functions_helper (
2104+ ctx. scopes . push ( Scope :: default ( ) ) ;
2105+ let then_branch_out = handle_inlined_functions_helper (
2106+ ctx,
20732107 then_branch,
20742108 inlined_functions,
20752109 inlined_var_counter,
20762110 total_inlined_counter,
20772111 ) ;
2078- handle_inlined_functions_helper (
2112+ ctx. scopes . pop ( ) ;
2113+ ctx. scopes . push ( Scope :: default ( ) ) ;
2114+ let else_branch_out = handle_inlined_functions_helper (
2115+ ctx,
20792116 else_branch,
20802117 inlined_functions,
20812118 inlined_var_counter,
20822119 total_inlined_counter,
20832120 ) ;
2121+ ctx. scopes . pop ( ) ;
2122+ lines_out. push ( Line :: IfCondition {
2123+ condition : condition. clone ( ) ,
2124+ then_branch : then_branch_out,
2125+ else_branch : else_branch_out,
2126+ line_number : * line_number,
2127+ } ) ;
20842128 }
2085- Line :: ForLoop { body, unroll : _, .. } => {
2086- handle_inlined_functions_helper ( body, inlined_functions, inlined_var_counter, total_inlined_counter) ;
2129+ Line :: ForLoop {
2130+ iterator,
2131+ start,
2132+ end,
2133+ body,
2134+ rev,
2135+ unroll,
2136+ line_number,
2137+ } => {
2138+ ctx. scopes . push ( Scope :: default ( ) ) ;
2139+ ctx. add_var ( iterator) ;
2140+ let loop_body_out = handle_inlined_functions_helper (
2141+ ctx,
2142+ body,
2143+ inlined_functions,
2144+ inlined_var_counter,
2145+ total_inlined_counter,
2146+ ) ;
2147+ ctx. scopes . pop ( ) ;
2148+ lines_out. push ( Line :: ForLoop {
2149+ iterator : iterator. clone ( ) ,
2150+ start : start. clone ( ) ,
2151+ end : end. clone ( ) ,
2152+ body : loop_body_out,
2153+ rev : * rev,
2154+ unroll : * unroll,
2155+ line_number : * line_number,
2156+ } ) ;
20872157 }
2088- Line :: Match { arms, .. } => {
2089- for ( _, arm) in arms {
2090- handle_inlined_functions_helper ( arm, inlined_functions, inlined_var_counter, total_inlined_counter) ;
2158+ Line :: Match { value, arms } => {
2159+ let mut arms_out: Vec < ( usize , Vec < Line > ) > = Vec :: new ( ) ;
2160+ for ( i, arm) in arms {
2161+ ctx. scopes . push ( Scope :: default ( ) ) ;
2162+ let arm_out = handle_inlined_functions_helper (
2163+ ctx,
2164+ arm,
2165+ inlined_functions,
2166+ inlined_var_counter,
2167+ total_inlined_counter,
2168+ ) ;
2169+ ctx. scopes . pop ( ) ;
2170+ arms_out. push ( ( * i, arm_out) ) ;
20912171 }
2172+ lines_out. push ( Line :: Match {
2173+ value : value. clone ( ) ,
2174+ arms : arms_out,
2175+ } ) ;
2176+ }
2177+ line => {
2178+ lines_out. push ( line. clone ( ) ) ;
20922179 }
2093- _ => { }
20942180 }
20952181 }
2182+ lines_out
20962183}
20972184
20982185fn handle_const_arguments ( program : & mut Program ) -> bool {
0 commit comments