-
Notifications
You must be signed in to change notification settings - Fork 437
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #548 from HigherOrderCO/expand-main
Expand refs in main, don't float combinators in main
- Loading branch information
Showing
41 changed files
with
258 additions
and
148 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
use crate::{ | ||
fun::{Book, Name, Pattern, Term}, | ||
maybe_grow, | ||
}; | ||
use std::collections::HashMap; | ||
|
||
impl Book { | ||
/// Expands the main function so that it is not just a reference. | ||
/// While technically correct, directly returning a reference is never what users want. | ||
pub fn expand_main(&mut self) { | ||
if self.entrypoint.is_none() { | ||
return; | ||
} | ||
|
||
let main = self.defs.get_mut(self.entrypoint.as_ref().unwrap()).unwrap(); | ||
let mut main_bod = std::mem::take(&mut main.rule_mut().body); | ||
|
||
let mut seen = vec![self.entrypoint.as_ref().unwrap().clone()]; | ||
main_bod.expand_ref_return(self, &mut seen, &mut 0); | ||
|
||
let main = self.defs.get_mut(self.entrypoint.as_ref().unwrap()).unwrap(); | ||
main.rule_mut().body = main_bod; | ||
} | ||
} | ||
|
||
impl Term { | ||
/// Expands references in the main function that are in "return" position. | ||
/// | ||
/// This applies to: | ||
/// - When main returns a reference. | ||
/// - When main returns a lambda whose body is a reference. | ||
/// - When main returns a pair or superposition and one of its elements is a reference. | ||
/// | ||
/// Only expand recursive functions once. | ||
pub fn expand_ref_return(&mut self, book: &Book, seen: &mut Vec<Name>, globals_count: &mut usize) { | ||
maybe_grow(|| match self { | ||
Term::Ref { nam } => { | ||
if seen.contains(nam) { | ||
// Don't expand recursive references | ||
} else { | ||
seen.push(nam.clone()); | ||
let mut body = book.defs.get(nam).unwrap().rule().body.clone(); | ||
body.rename_unscoped(globals_count, &mut HashMap::new()); | ||
*self = body; | ||
self.expand_ref_return(book, seen, globals_count); | ||
seen.pop().unwrap(); | ||
} | ||
} | ||
Term::Fan { els, .. } | Term::List { els } => { | ||
for el in els { | ||
el.expand_ref_return(book, seen, globals_count); | ||
} | ||
} | ||
Term::Lam { bod: nxt, .. } | ||
| Term::With { bod: nxt, .. } | ||
| Term::Open { bod: nxt, .. } | ||
| Term::Let { nxt, .. } | ||
| Term::Ask { nxt, .. } | ||
| Term::Use { nxt, .. } => nxt.expand_ref_return(book, seen, globals_count), | ||
Term::Var { .. } | ||
| Term::Link { .. } | ||
| Term::App { .. } | ||
| Term::Num { .. } | ||
| Term::Nat { .. } | ||
| Term::Str { .. } | ||
| Term::Oper { .. } | ||
| Term::Mat { .. } | ||
| Term::Swt { .. } | ||
| Term::Fold { .. } | ||
| Term::Bend { .. } | ||
| Term::Era | ||
| Term::Err => {} | ||
}) | ||
} | ||
} | ||
|
||
impl Term { | ||
/// Since expanded functions can contain unscoped variables, and | ||
/// unscoped variable names must be unique, we need to rename them | ||
/// to avoid conflicts. | ||
fn rename_unscoped(&mut self, unscoped_count: &mut usize, unscoped_map: &mut HashMap<Name, Name>) { | ||
match self { | ||
Term::Let { pat, .. } | Term::Lam { pat, .. } => pat.rename_unscoped(unscoped_count, unscoped_map), | ||
Term::Link { nam } => rename_unscoped(nam, unscoped_count, unscoped_map), | ||
_ => { | ||
// Isn't an unscoped bind or use, do nothing, just recurse. | ||
} | ||
} | ||
for child in self.children_mut() { | ||
child.rename_unscoped(unscoped_count, unscoped_map); | ||
} | ||
} | ||
} | ||
|
||
impl Pattern { | ||
fn rename_unscoped(&mut self, unscoped_count: &mut usize, unscoped_map: &mut HashMap<Name, Name>) { | ||
maybe_grow(|| { | ||
match self { | ||
Pattern::Chn(nam) => rename_unscoped(nam, unscoped_count, unscoped_map), | ||
_ => { | ||
// Pattern isn't an unscoped bind, just recurse. | ||
} | ||
} | ||
for child in self.children_mut() { | ||
child.rename_unscoped(unscoped_count, unscoped_map); | ||
} | ||
}) | ||
} | ||
} | ||
|
||
/// Generates a new name for an unscoped variable. | ||
fn rename_unscoped(nam: &mut Name, unscoped_count: &mut usize, unscoped_map: &mut HashMap<Name, Name>) { | ||
if let Some(new_nam) = unscoped_map.get(nam) { | ||
*nam = new_nam.clone(); | ||
} else { | ||
let new_nam = Name::new(format!("{nam}%{}", unscoped_count)); | ||
unscoped_map.insert(nam.clone(), new_nam.clone()); | ||
*unscoped_count += 1; | ||
*nam = new_nam; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# Despite having an unused variable in main, `map(tt,l)` should not be extracted into a new definition. | ||
def map(fn, list): | ||
fold list: | ||
case List/Cons: | ||
return List/Cons(fn(list.head), list.tail) | ||
case List/Nil: | ||
return [] | ||
|
||
def tt(x): | ||
return x*2 | ||
|
||
def main(): | ||
l = [5,6,7,8] | ||
k = [1,2,3,4] | ||
return map(tt,l) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,4 +8,4 @@ input_file: tests/golden_tests/cli/desugar_merge.bend | |
|
||
(F__M_Z) = λ* λa a | ||
|
||
(main) = F__M_Z | ||
(main) = λ* λa a |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,4 +18,4 @@ input_file: tests/golden_tests/compile_file/ref_to_ref.bend | |
|
||
@C1 = @B4 | ||
|
||
@main = ((@A1 @B1) @C1) | ||
@main = ((1 2) 2) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.