Skip to content

Commit 0dbebab

Browse files
committed
wip: issue 114
1 parent 2924911 commit 0dbebab

File tree

4 files changed

+183
-57
lines changed

4 files changed

+183
-57
lines changed

crates/lean_compiler/src/a_simplify_lang.rs

Lines changed: 142 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -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

20152013
fn 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

20982185
fn handle_const_arguments(program: &mut Program) -> bool {

crates/lean_compiler/src/lang.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,7 @@ pub enum Line {
461461
}
462462

463463
/// A context specifying which variables are in scope.
464+
#[derive(Debug)]
464465
pub struct Context {
465466
/// A list of lexical scopes, innermost scope last.
466467
pub scopes: Vec<Scope>,
@@ -469,6 +470,13 @@ pub struct Context {
469470
}
470471

471472
impl Context {
473+
pub fn new() -> Context {
474+
Context {
475+
scopes: vec![Scope::default()],
476+
const_arrays: BTreeMap::new(),
477+
}
478+
}
479+
472480
pub fn defines(&self, var: &Var) -> bool {
473481
if self.const_arrays.contains_key(var) {
474482
return true;
@@ -480,9 +488,18 @@ impl Context {
480488
}
481489
false
482490
}
491+
492+
pub fn add_var(&mut self, var: &Var) {
493+
let last_scope = self.scopes.last_mut().unwrap();
494+
assert!(
495+
!last_scope.vars.contains(var),
496+
"Variable declared multiple times in the same scope: {var}",
497+
);
498+
last_scope.vars.insert(var.clone());
499+
}
483500
}
484501

485-
#[derive(Default)]
502+
#[derive(Debug, Default)]
486503
pub struct Scope {
487504
/// A set of declared variables.
488505
pub vars: BTreeSet<Var>,

crates/lean_compiler/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub fn compile_program(program: String) -> Bytecode {
1616
let (parsed_program, function_locations) = parse_program(&program).unwrap();
1717
// println!("Parsed program: {}", parsed_program.to_string());
1818
let simple_program = simplify_program(parsed_program);
19-
// println!("Simplified program: {}", simple_program);
19+
println!("Simplified program: {}", simple_program);
2020
let intermediate_bytecode = compile_to_intermediate_bytecode(simple_program).unwrap();
2121
// println!("Intermediate Bytecode:\n\n{}", intermediate_bytecode.to_string());
2222

crates/lean_compiler/tests/test_compiler.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,28 @@ fn test_inlined_2() {
468468
compile_and_run(program.to_string(), (&[], &[]), DEFAULT_NO_VEC_RUNTIME_MEMORY, false);
469469
}
470470

471+
#[test]
472+
fn test_inlined_3() {
473+
let program = r#"
474+
fn main() {
475+
x = func();
476+
return;
477+
}
478+
fn func() -> 1 {
479+
var a;
480+
if 0 == 0 {
481+
a = aux();
482+
}
483+
return a;
484+
}
485+
486+
fn aux() inline -> 1 {
487+
return 1;
488+
}
489+
"#;
490+
compile_and_run(program.to_string(), (&[], &[]), DEFAULT_NO_VEC_RUNTIME_MEMORY, false);
491+
}
492+
471493
#[test]
472494
fn test_match() {
473495
let program = r#"

0 commit comments

Comments
 (0)