From 0dbebabdbd67ff172eab85c6fe815188f84fd4e3 Mon Sep 17 00:00:00 2001 From: Morgan Thomas Date: Tue, 23 Dec 2025 19:50:28 +0000 Subject: [PATCH] wip: issue 114 --- crates/lean_compiler/src/a_simplify_lang.rs | 197 ++++++++++++++------ crates/lean_compiler/src/lang.rs | 19 +- crates/lean_compiler/src/lib.rs | 2 +- crates/lean_compiler/tests/test_compiler.rs | 22 +++ 4 files changed, 183 insertions(+), 57 deletions(-) diff --git a/crates/lean_compiler/src/a_simplify_lang.rs b/crates/lean_compiler/src/a_simplify_lang.rs index 17f2abec..3c1485bf 100644 --- a/crates/lean_compiler/src/a_simplify_lang.rs +++ b/crates/lean_compiler/src/a_simplify_lang.rs @@ -360,12 +360,7 @@ fn check_block_scoping(block: &[Line], ctx: &mut Context) { for line in block.iter() { match line { Line::ForwardDeclaration { var } => { - let last_scope = ctx.scopes.last_mut().unwrap(); - assert!( - !last_scope.vars.contains(var), - "Variable declared multiple times in the same scope: {var}", - ); - last_scope.vars.insert(var.clone()); + ctx.add_var(var); } Line::Match { value, arms } => { check_expr_scoping(value, ctx); @@ -377,12 +372,9 @@ fn check_block_scoping(block: &[Line], ctx: &mut Context) { } Line::Assignment { var, value } => { check_expr_scoping(value, ctx); - let last_scope = ctx.scopes.last_mut().unwrap(); - assert!( - !last_scope.vars.contains(var), - "Variable declared multiple times in the same scope: {var}", - ); - last_scope.vars.insert(var.clone()); + if !ctx.defines(var) { + ctx.add_var(var); + } } Line::ArrayAssign { array, index, value } => { check_simple_expr_scoping(array, ctx); @@ -431,15 +423,12 @@ fn check_block_scoping(block: &[Line], ctx: &mut Context) { for arg in args { check_expr_scoping(arg, ctx); } - let last_scope = ctx.scopes.last_mut().unwrap(); for target in return_data { match target { AssignmentTarget::Var(var) => { - assert!( - !last_scope.vars.contains(var), - "Variable declared multiple times in the same scope: {var}", - ); - last_scope.vars.insert(var.clone()); + if !ctx.defines(var) { + ctx.add_var(var); + } } AssignmentTarget::ArrayAccess { .. } => {} } @@ -478,23 +467,17 @@ fn check_block_scoping(block: &[Line], ctx: &mut Context) { } => { check_expr_scoping(size, ctx); check_expr_scoping(vectorized_len, ctx); - let last_scope = ctx.scopes.last_mut().unwrap(); - assert!( - !last_scope.vars.contains(var), - "Variable declared multiple times in the same scope: {var}", - ); - last_scope.vars.insert(var.clone()); + if !ctx.defines(var) { + ctx.add_var(var); + } } Line::DecomposeBits { var, to_decompose } => { for expr in to_decompose { check_expr_scoping(expr, ctx); } - let last_scope = ctx.scopes.last_mut().unwrap(); - assert!( - !last_scope.vars.contains(var), - "Variable declared multiple times in the same scope: {var}", - ); - last_scope.vars.insert(var.clone()); + if !ctx.defines(var) { + ctx.add_var(var); + } } Line::DecomposeCustom { args } => { for arg in args { @@ -502,12 +485,7 @@ fn check_block_scoping(block: &[Line], ctx: &mut Context) { } } Line::PrivateInputStart { result } => { - let last_scope = ctx.scopes.last_mut().unwrap(); - assert!( - !last_scope.vars.contains(result), - "Variable declared multiple times in the same scope: {result}" - ); - last_scope.vars.insert(result.clone()); + ctx.add_var(result); } } } @@ -1973,7 +1951,17 @@ fn handle_inlined_functions(program: &mut Program) { let mut counter2 = Counter::new(); let old_body = func.body.clone(); - handle_inlined_functions_helper(&mut func.body, &inlined_functions, &mut counter1, &mut counter2); + let mut ctx = Context::new(); + for (var, _) in func.arguments.iter() { + ctx.add_var(var); + } + func.body = handle_inlined_functions_helper( + &mut ctx, + &func.body, + &inlined_functions, + &mut counter1, + &mut counter2, + ); if func.body != old_body { any_changes = true; @@ -1989,7 +1977,17 @@ fn handle_inlined_functions(program: &mut Program) { let mut counter2 = Counter::new(); let old_body = func.body.clone(); - handle_inlined_functions_helper(&mut func.body, &inlined_functions, &mut counter1, &mut counter2); + let mut ctx = Context::new(); + for (var, _) in func.arguments.iter() { + ctx.add_var(var); + } + handle_inlined_functions_helper( + &mut ctx, + &func.body, + &inlined_functions, + &mut counter1, + &mut counter2, + ); if func.body != old_body { any_changes = true; @@ -2013,13 +2011,43 @@ fn handle_inlined_functions(program: &mut Program) { } fn handle_inlined_functions_helper( - lines: &mut Vec, + ctx: &mut Context, + lines_in: &Vec, inlined_functions: &BTreeMap, inlined_var_counter: &mut Counter, total_inlined_counter: &mut Counter, -) { - for i in (0..lines.len()).rev() { - match &mut lines[i] { +) -> Vec { + let mut lines_out: Vec = Vec::new(); + for line in lines_in { + match line { + Line::ForwardDeclaration { var } => { + lines_out.push(line.clone()); + ctx.add_var(var); + } + Line::Assignment { var, .. } => { + lines_out.push(line.clone()); + if !ctx.defines(var) { + ctx.add_var(var); + } + } + Line::DecomposeBits { var, .. } => { + lines_out.push(line.clone()); + if !ctx.defines(var) { + ctx.add_var(var); + } + } + Line::PrivateInputStart { result } => { + lines_out.push(line.clone()); + if !ctx.defines(result) { + ctx.add_var(result); + } + } + Line::MAlloc { var, .. } => { + lines_out.push(line.clone()); + if !ctx.defines(var) { + ctx.add_var(var); + } + } Line::FunctionCall { function_name, args, @@ -2031,8 +2059,11 @@ fn handle_inlined_functions_helper( // Only add forward declarations for variable targets, not array accesses for target in return_data.iter() { - if let AssignmentTarget::Var(var) = target { + if let AssignmentTarget::Var(var) = target + && !ctx.defines(var) + { inlined_lines.push(Line::ForwardDeclaration { var: var.clone() }); + ctx.add_var(var); } } @@ -2059,40 +2090,96 @@ fn handle_inlined_functions_helper( let mut func_body = func.body.clone(); inline_lines(&mut func_body, &inlined_args, return_data, total_inlined_counter.next()); inlined_lines.extend(func_body); - - lines.remove(i); // remove the call to the inlined function - lines.splice(i..i, inlined_lines); + lines_out.extend(inlined_lines); + } else { + lines_out.push(line.clone()); } } Line::IfCondition { + condition, then_branch, else_branch, - .. + line_number, } => { - handle_inlined_functions_helper( + ctx.scopes.push(Scope::default()); + let then_branch_out = handle_inlined_functions_helper( + ctx, then_branch, inlined_functions, inlined_var_counter, total_inlined_counter, ); - handle_inlined_functions_helper( + ctx.scopes.pop(); + ctx.scopes.push(Scope::default()); + let else_branch_out = handle_inlined_functions_helper( + ctx, else_branch, inlined_functions, inlined_var_counter, total_inlined_counter, ); + ctx.scopes.pop(); + lines_out.push(Line::IfCondition { + condition: condition.clone(), + then_branch: then_branch_out, + else_branch: else_branch_out, + line_number: *line_number, + }); } - Line::ForLoop { body, unroll: _, .. } => { - handle_inlined_functions_helper(body, inlined_functions, inlined_var_counter, total_inlined_counter); + Line::ForLoop { + iterator, + start, + end, + body, + rev, + unroll, + line_number, + } => { + ctx.scopes.push(Scope::default()); + ctx.add_var(iterator); + let loop_body_out = handle_inlined_functions_helper( + ctx, + body, + inlined_functions, + inlined_var_counter, + total_inlined_counter, + ); + ctx.scopes.pop(); + lines_out.push(Line::ForLoop { + iterator: iterator.clone(), + start: start.clone(), + end: end.clone(), + body: loop_body_out, + rev: *rev, + unroll: *unroll, + line_number: *line_number, + }); } - Line::Match { arms, .. } => { - for (_, arm) in arms { - handle_inlined_functions_helper(arm, inlined_functions, inlined_var_counter, total_inlined_counter); + Line::Match { value, arms } => { + let mut arms_out: Vec<(usize, Vec)> = Vec::new(); + for (i, arm) in arms { + ctx.scopes.push(Scope::default()); + let arm_out = handle_inlined_functions_helper( + ctx, + arm, + inlined_functions, + inlined_var_counter, + total_inlined_counter, + ); + ctx.scopes.pop(); + arms_out.push((*i, arm_out)); } + lines_out.push(Line::Match { + value: value.clone(), + arms: arms_out, + }); + } + line => { + lines_out.push(line.clone()); } - _ => {} } } + lines_out } fn handle_const_arguments(program: &mut Program) -> bool { diff --git a/crates/lean_compiler/src/lang.rs b/crates/lean_compiler/src/lang.rs index fe5ae910..d509508a 100644 --- a/crates/lean_compiler/src/lang.rs +++ b/crates/lean_compiler/src/lang.rs @@ -461,6 +461,7 @@ pub enum Line { } /// A context specifying which variables are in scope. +#[derive(Debug)] pub struct Context { /// A list of lexical scopes, innermost scope last. pub scopes: Vec, @@ -469,6 +470,13 @@ pub struct Context { } impl Context { + pub fn new() -> Context { + Context { + scopes: vec![Scope::default()], + const_arrays: BTreeMap::new(), + } + } + pub fn defines(&self, var: &Var) -> bool { if self.const_arrays.contains_key(var) { return true; @@ -480,9 +488,18 @@ impl Context { } false } + + pub fn add_var(&mut self, var: &Var) { + let last_scope = self.scopes.last_mut().unwrap(); + assert!( + !last_scope.vars.contains(var), + "Variable declared multiple times in the same scope: {var}", + ); + last_scope.vars.insert(var.clone()); + } } -#[derive(Default)] +#[derive(Debug, Default)] pub struct Scope { /// A set of declared variables. pub vars: BTreeSet, diff --git a/crates/lean_compiler/src/lib.rs b/crates/lean_compiler/src/lib.rs index 4be13793..20824070 100644 --- a/crates/lean_compiler/src/lib.rs +++ b/crates/lean_compiler/src/lib.rs @@ -16,7 +16,7 @@ pub fn compile_program(program: String) -> Bytecode { let (parsed_program, function_locations) = parse_program(&program).unwrap(); // println!("Parsed program: {}", parsed_program.to_string()); let simple_program = simplify_program(parsed_program); - // println!("Simplified program: {}", simple_program); + println!("Simplified program: {}", simple_program); let intermediate_bytecode = compile_to_intermediate_bytecode(simple_program).unwrap(); // println!("Intermediate Bytecode:\n\n{}", intermediate_bytecode.to_string()); diff --git a/crates/lean_compiler/tests/test_compiler.rs b/crates/lean_compiler/tests/test_compiler.rs index 9dc6eeac..b9ae09a0 100644 --- a/crates/lean_compiler/tests/test_compiler.rs +++ b/crates/lean_compiler/tests/test_compiler.rs @@ -468,6 +468,28 @@ fn test_inlined_2() { compile_and_run(program.to_string(), (&[], &[]), DEFAULT_NO_VEC_RUNTIME_MEMORY, false); } +#[test] +fn test_inlined_3() { + let program = r#" + fn main() { + x = func(); + return; + } + fn func() -> 1 { + var a; + if 0 == 0 { + a = aux(); + } + return a; + } + + fn aux() inline -> 1 { + return 1; + } + "#; + compile_and_run(program.to_string(), (&[], &[]), DEFAULT_NO_VEC_RUNTIME_MEMORY, false); +} + #[test] fn test_match() { let program = r#"