mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 22:34:45 +00:00
simple when is working
This commit is contained in:
parent
2a0b010a74
commit
cccfeb51f2
6 changed files with 3269 additions and 205 deletions
1575
compiler/mono/src/decision_tree2.rs
Normal file
1575
compiler/mono/src/decision_tree2.rs
Normal file
File diff suppressed because it is too large
Load diff
1257
compiler/mono/src/experiment.rs
Normal file
1257
compiler/mono/src/experiment.rs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -596,13 +596,13 @@ impl<'a> Expr<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum IntOrFloat {
|
pub enum IntOrFloat {
|
||||||
IntType,
|
IntType,
|
||||||
FloatType,
|
FloatType,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given the `a` in `Num a`, determines whether it's an int or a float
|
/// Given the `a` in `Num a`, determines whether it's an int or a float
|
||||||
fn num_argument_to_int_or_float(subs: &Subs, var: Variable) -> IntOrFloat {
|
pub fn num_argument_to_int_or_float(subs: &Subs, var: Variable) -> IntOrFloat {
|
||||||
match subs.get_without_compacting(var).content {
|
match subs.get_without_compacting(var).content {
|
||||||
Content::Alias(Symbol::NUM_INTEGER, args, _) => {
|
Content::Alias(Symbol::NUM_INTEGER, args, _) => {
|
||||||
debug_assert!(args.is_empty());
|
debug_assert!(args.is_empty());
|
||||||
|
@ -1986,7 +1986,7 @@ pub struct WhenBranch<'a> {
|
||||||
pub guard: Option<Expr<'a>>,
|
pub guard: Option<Expr<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_can_pattern<'a>(
|
pub fn from_can_pattern<'a>(
|
||||||
env: &mut Env<'a, '_>,
|
env: &mut Env<'a, '_>,
|
||||||
procs: &mut Procs<'a>,
|
procs: &mut Procs<'a>,
|
||||||
layout_cache: &mut LayoutCache<'a>,
|
layout_cache: &mut LayoutCache<'a>,
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
// re-enable this when working on performance optimizations than have it block PRs.
|
// re-enable this when working on performance optimizations than have it block PRs.
|
||||||
#![allow(clippy::large_enum_variant)]
|
#![allow(clippy::large_enum_variant)]
|
||||||
|
|
||||||
|
pub mod experiment;
|
||||||
pub mod expr;
|
pub mod expr;
|
||||||
pub mod layout;
|
pub mod layout;
|
||||||
pub mod reset_reuse;
|
pub mod reset_reuse;
|
||||||
|
@ -20,4 +21,6 @@ pub mod reset_reuse;
|
||||||
#[allow(clippy::ptr_arg)]
|
#[allow(clippy::ptr_arg)]
|
||||||
pub mod decision_tree;
|
pub mod decision_tree;
|
||||||
#[allow(clippy::ptr_arg)]
|
#[allow(clippy::ptr_arg)]
|
||||||
|
pub mod decision_tree2;
|
||||||
|
#[allow(clippy::ptr_arg)]
|
||||||
pub mod pattern;
|
pub mod pattern;
|
||||||
|
|
|
@ -5,50 +5,6 @@ use bumpalo::collections::Vec;
|
||||||
use roc_collections::all::MutSet;
|
use roc_collections::all::MutSet;
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
|
|
||||||
/*
|
|
||||||
R : FnBodypure → FnBodyRC
|
|
||||||
R(let x = e; F ) = let x = e; R(F )
|
|
||||||
R(ret x) = ret x
|
|
||||||
R(case x of F ) = case x of D(x,ni
|
|
||||||
, R(Fi))
|
|
||||||
where ni = #fields of x in i-th branch
|
|
||||||
D : Var × N × FnBodyRC → FnBodyRC
|
|
||||||
D(z,n, case x of F ) = case x of D(z,n, F )
|
|
||||||
D(z,n, ret x) = ret x
|
|
||||||
D(z,n, let x = e; F ) = let x = e; D(z,n, F )
|
|
||||||
if z ∈ e or z ∈ F
|
|
||||||
D(z,n, F ) = let w = reset z; S(w,n, F )
|
|
||||||
otherwise, if S(w,n, F ) , F for a fresh w
|
|
||||||
D(z,n, F ) = F otherwise
|
|
||||||
S : Var × N × FnBodyRC → FnBodyRC
|
|
||||||
S(w,n, let x = ctori y; F ) = let x = reuse w in ctori y; F
|
|
||||||
if | y |= n
|
|
||||||
S(w,n, let x = e; F ) = let x = e; S(w,n, F ) otherwise
|
|
||||||
S(w,n, ret x) = ret x
|
|
||||||
S(w,n, case x of F ) = case x of S(w,n, F )
|
|
||||||
|
|
||||||
|
|
||||||
Maybe a : [ Nothing, Just a ]
|
|
||||||
|
|
||||||
map : Maybe a -> (a -> b) -> Maybe b
|
|
||||||
map = \maybe f ->
|
|
||||||
when maybe is
|
|
||||||
Nothing -> Nothing
|
|
||||||
Just x -> Just (f x)
|
|
||||||
|
|
||||||
|
|
||||||
map : Maybe a -> (a -> b) -> Maybe b
|
|
||||||
map = \maybe f ->
|
|
||||||
when maybe is
|
|
||||||
Nothing ->
|
|
||||||
let w = reset maybe
|
|
||||||
let r = reuse w in AppliedTag("Nothing", vec![])
|
|
||||||
Just x ->
|
|
||||||
let v = f x
|
|
||||||
let w = reset maybe
|
|
||||||
let r = reuse w in AppliedTag("Just", vec![v])
|
|
||||||
*/
|
|
||||||
|
|
||||||
pub fn function_r<'a>(env: &mut Env<'a, '_>, body: &'a Expr<'a>) -> Expr<'a> {
|
pub fn function_r<'a>(env: &mut Env<'a, '_>, body: &'a Expr<'a>) -> Expr<'a> {
|
||||||
use Expr::*;
|
use Expr::*;
|
||||||
|
|
||||||
|
@ -345,6 +301,143 @@ fn function_s<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn free_variables<'a>(initial: &Expr<'a>) -> MutSet<Symbol> {
|
||||||
|
use Expr::*;
|
||||||
|
let mut seen = MutSet::default();
|
||||||
|
let mut bound = MutSet::default();
|
||||||
|
let mut stack = vec![initial];
|
||||||
|
|
||||||
|
// in other words, variables that are referenced, but not stored
|
||||||
|
|
||||||
|
while let Some(expr) = stack.pop() {
|
||||||
|
match expr {
|
||||||
|
FunctionPointer(symbol, _) | Load(symbol) => {
|
||||||
|
seen.insert(*symbol);
|
||||||
|
}
|
||||||
|
Reset(symbol, expr) | Reuse(symbol, expr) => {
|
||||||
|
seen.insert(*symbol);
|
||||||
|
stack.push(expr)
|
||||||
|
}
|
||||||
|
|
||||||
|
Cond {
|
||||||
|
cond_symbol,
|
||||||
|
branching_symbol,
|
||||||
|
pass,
|
||||||
|
fail,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
seen.insert(*cond_symbol);
|
||||||
|
seen.insert(*branching_symbol);
|
||||||
|
|
||||||
|
for (symbol, _, expr) in pass.0.iter() {
|
||||||
|
seen.insert(*symbol);
|
||||||
|
stack.push(expr)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (symbol, _, expr) in fail.0.iter() {
|
||||||
|
seen.insert(*symbol);
|
||||||
|
stack.push(expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Switch {
|
||||||
|
cond,
|
||||||
|
cond_symbol,
|
||||||
|
branches,
|
||||||
|
default_branch,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
stack.push(cond);
|
||||||
|
seen.insert(*cond_symbol);
|
||||||
|
|
||||||
|
for (_, stores, expr) in branches.iter() {
|
||||||
|
stack.push(expr);
|
||||||
|
|
||||||
|
for (symbol, _, expr) in stores.iter() {
|
||||||
|
bound.insert(*symbol);
|
||||||
|
stack.push(expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stack.push(default_branch.1);
|
||||||
|
for (symbol, _, expr) in default_branch.0.iter() {
|
||||||
|
seen.insert(*symbol);
|
||||||
|
stack.push(expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Store(stores, body) => {
|
||||||
|
for (symbol, _, expr) in stores.iter() {
|
||||||
|
bound.insert(*symbol);
|
||||||
|
stack.push(&expr)
|
||||||
|
}
|
||||||
|
|
||||||
|
stack.push(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
DecAfter(symbol, body) | Inc(symbol, body) => {
|
||||||
|
seen.insert(*symbol);
|
||||||
|
stack.push(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
CallByName { name, args, .. } => {
|
||||||
|
seen.insert(*name);
|
||||||
|
for (expr, _) in args.iter() {
|
||||||
|
stack.push(expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CallByPointer(function, args, _) => {
|
||||||
|
stack.push(function);
|
||||||
|
stack.extend(args.iter());
|
||||||
|
}
|
||||||
|
|
||||||
|
RunLowLevel(_, args) => {
|
||||||
|
for (expr, _) in args.iter() {
|
||||||
|
stack.push(expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Tag { arguments, .. } => {
|
||||||
|
for (symbol, _) in arguments.iter() {
|
||||||
|
seen.insert(*symbol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Struct(arguments) => {
|
||||||
|
for (expr, _) in arguments.iter() {
|
||||||
|
stack.push(expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Array { elems, .. } => {
|
||||||
|
for expr in elems.iter() {
|
||||||
|
stack.push(expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AccessAtIndex { expr, .. } => {
|
||||||
|
stack.push(expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Int(_)
|
||||||
|
| Float(_)
|
||||||
|
| Str(_)
|
||||||
|
| Bool(_)
|
||||||
|
| Byte(_)
|
||||||
|
| EmptyArray
|
||||||
|
| RuntimeError(_)
|
||||||
|
| RuntimeErrorFunction(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for symbol in bound.iter() {
|
||||||
|
seen.remove(symbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
seen
|
||||||
|
}
|
||||||
|
|
||||||
fn symbols_in_expr<'a>(initial: &Expr<'a>) -> MutSet<Symbol> {
|
fn symbols_in_expr<'a>(initial: &Expr<'a>) -> MutSet<Symbol> {
|
||||||
use Expr::*;
|
use Expr::*;
|
||||||
let mut result = MutSet::default();
|
let mut result = MutSet::default();
|
||||||
|
@ -475,3 +568,81 @@ fn symbols_in_expr<'a>(initial: &Expr<'a>) -> MutSet<Symbol> {
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn function_c<'a>(env: &mut Env<'a, '_>, body: Expr<'a>) -> Expr<'a> {
|
||||||
|
let fv = free_variables(&body);
|
||||||
|
|
||||||
|
function_c_help(env, body, fv)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn function_c_help<'a>(env: &mut Env<'a, '_>, body: Expr<'a>, fv: MutSet<Symbol>) -> Expr<'a> {
|
||||||
|
use Expr::*;
|
||||||
|
|
||||||
|
match body {
|
||||||
|
Tag { arguments, .. } => {
|
||||||
|
let symbols = arguments
|
||||||
|
.iter()
|
||||||
|
.map(|(x, _)| x)
|
||||||
|
.copied()
|
||||||
|
.collect::<std::vec::Vec<_>>();
|
||||||
|
|
||||||
|
function_c_app(env, &symbols, &fv, body)
|
||||||
|
}
|
||||||
|
_ => body,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn function_c_app<'a>(
|
||||||
|
env: &mut Env<'a, '_>,
|
||||||
|
arguments: &[Symbol],
|
||||||
|
orig_fv: &MutSet<Symbol>,
|
||||||
|
mut application: Expr<'a>,
|
||||||
|
) -> Expr<'a> {
|
||||||
|
// in the future, this will need to be a check
|
||||||
|
let is_owned = true;
|
||||||
|
|
||||||
|
for (i, y) in arguments.iter().rev().enumerate() {
|
||||||
|
if is_owned {
|
||||||
|
let mut fv = orig_fv.clone();
|
||||||
|
fv.extend(arguments[i..].iter().copied());
|
||||||
|
|
||||||
|
application = insert_increment(env, *y, fv, application)
|
||||||
|
} else {
|
||||||
|
unimplemented!("owned references are not implemented yet")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
application
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert_increment<'a>(
|
||||||
|
env: &mut Env<'a, '_>,
|
||||||
|
symbol: Symbol,
|
||||||
|
live_variables: MutSet<Symbol>,
|
||||||
|
body: Expr<'a>,
|
||||||
|
) -> Expr<'a> {
|
||||||
|
// in the future, this will need to be a check
|
||||||
|
let is_owned = true;
|
||||||
|
|
||||||
|
if is_owned && !live_variables.contains(&symbol) {
|
||||||
|
body
|
||||||
|
} else {
|
||||||
|
Expr::Inc(symbol, env.arena.alloc(body))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert_decrement<'a>(env: &mut Env<'a, '_>, symbols: &[Symbol], mut body: Expr<'a>) -> Expr<'a> {
|
||||||
|
// in the future, this will need to be a check
|
||||||
|
let is_owned = true;
|
||||||
|
let fv = free_variables(&body);
|
||||||
|
|
||||||
|
for symbol in symbols.iter() {
|
||||||
|
let is_dead = !fv.contains(&symbol);
|
||||||
|
|
||||||
|
if is_owned && is_dead {
|
||||||
|
body = Expr::DecAfter(*symbol, env.arena.alloc(body));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body
|
||||||
|
}
|
||||||
|
|
|
@ -142,11 +142,13 @@ mod test_mono {
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
dbg!(&mono_expr);
|
||||||
procs_string.push(mono_expr.to_pretty(200));
|
procs_string.push(mono_expr.to_pretty(200));
|
||||||
|
|
||||||
let result = procs_string.join("\n");
|
let result = procs_string.join("\n");
|
||||||
|
|
||||||
assert_eq!(result, expected);
|
// assert_eq!(result, expected);
|
||||||
|
()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -701,116 +703,6 @@ mod test_mono {
|
||||||
// )
|
// )
|
||||||
// }
|
// }
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn insert_reset_reuse() {
|
|
||||||
compiles_to(
|
|
||||||
r#"
|
|
||||||
when Foo 1 is
|
|
||||||
Foo _ -> Foo 1
|
|
||||||
Bar -> Foo 2
|
|
||||||
Baz -> Foo 2
|
|
||||||
a -> a
|
|
||||||
"#,
|
|
||||||
{
|
|
||||||
use self::Builtin::*;
|
|
||||||
use Layout::{Builtin, Union};
|
|
||||||
|
|
||||||
let home = test_home();
|
|
||||||
let gen_symbol_1 = Interns::from_index(home, 1);
|
|
||||||
|
|
||||||
let union_layout = Union(&[
|
|
||||||
&[Builtin(Int64)],
|
|
||||||
&[Builtin(Int64)],
|
|
||||||
&[Builtin(Int64), Builtin(Int64)],
|
|
||||||
]);
|
|
||||||
|
|
||||||
Store(
|
|
||||||
&[(
|
|
||||||
gen_symbol_1,
|
|
||||||
union_layout.clone(),
|
|
||||||
Tag {
|
|
||||||
tag_layout: union_layout.clone(),
|
|
||||||
tag_name: TagName::Global("Foo".into()),
|
|
||||||
tag_id: 2,
|
|
||||||
union_size: 3,
|
|
||||||
arguments: &[(Int(2), Builtin(Int64)), (Int(1), Builtin(Int64))],
|
|
||||||
},
|
|
||||||
)],
|
|
||||||
&Store(
|
|
||||||
&[],
|
|
||||||
&Switch {
|
|
||||||
cond: &Load(gen_symbol_1),
|
|
||||||
cond_symbol: gen_symbol_1,
|
|
||||||
branches: &[
|
|
||||||
(
|
|
||||||
2,
|
|
||||||
&[],
|
|
||||||
Reset(
|
|
||||||
gen_symbol_1,
|
|
||||||
&Reuse(
|
|
||||||
gen_symbol_1,
|
|
||||||
&Tag {
|
|
||||||
tag_layout: union_layout.clone(),
|
|
||||||
tag_name: TagName::Global("Foo".into()),
|
|
||||||
tag_id: 2,
|
|
||||||
union_size: 3,
|
|
||||||
arguments: &[
|
|
||||||
(Int(2), Builtin(Int64)),
|
|
||||||
(Int(1), Builtin(Int64)),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
0,
|
|
||||||
&[],
|
|
||||||
Reset(
|
|
||||||
gen_symbol_1,
|
|
||||||
&Reuse(
|
|
||||||
gen_symbol_1,
|
|
||||||
&Tag {
|
|
||||||
tag_layout: union_layout.clone(),
|
|
||||||
tag_name: TagName::Global("Foo".into()),
|
|
||||||
tag_id: 2,
|
|
||||||
union_size: 3,
|
|
||||||
arguments: &[
|
|
||||||
(Int(2), Builtin(Int64)),
|
|
||||||
(Int(2), Builtin(Int64)),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
default_branch: (
|
|
||||||
&[],
|
|
||||||
&Reset(
|
|
||||||
gen_symbol_1,
|
|
||||||
&Reuse(
|
|
||||||
gen_symbol_1,
|
|
||||||
&Tag {
|
|
||||||
tag_layout: union_layout.clone(),
|
|
||||||
tag_name: TagName::Global("Foo".into()),
|
|
||||||
tag_id: 2,
|
|
||||||
union_size: 3,
|
|
||||||
arguments: &[
|
|
||||||
(Int(2), Builtin(Int64)),
|
|
||||||
(Int(2), Builtin(Int64)),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
ret_layout: union_layout.clone(),
|
|
||||||
cond_layout: union_layout,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn simple_to_string() {
|
fn simple_to_string() {
|
||||||
compiles_to_string(
|
compiles_to_string(
|
||||||
|
@ -865,51 +757,22 @@ mod test_mono {
|
||||||
procedure Num.14 (#Attr.2, #Attr.3):
|
procedure Num.14 (#Attr.2, #Attr.3):
|
||||||
Lowlevel.NumAdd (Load #Attr.2) (Load #Attr.3)
|
Lowlevel.NumAdd (Load #Attr.2) (Load #Attr.3)
|
||||||
|
|
||||||
Store Test.1: Just 0i64 3i64
|
Store Test.1:
|
||||||
Store Test.1: Load Test.1
|
Store Test.3: 0i64
|
||||||
Store Test.3: Lowlevel.And (Lowlevel.Eq 0i64 (Access @0 Load Test.1)) true
|
Store Test.4: 3i64
|
||||||
if Test.3 then
|
Just Test.3 Test.4
|
||||||
|
Store Test.8: Lowlevel.And (Lowlevel.Eq 0i64 (Access @0 Load Test.1)) true
|
||||||
|
if Test.8 then
|
||||||
Reset Test.1
|
Reset Test.1
|
||||||
|
Store Test.5: 0i64
|
||||||
|
Store Test.6: Call Num.14 (Load Test.2) 1i64
|
||||||
Reuse Test.1
|
Reuse Test.1
|
||||||
Just 0i64 (Call Num.14 (Load Test.2) 1i64)
|
Just Test.5 Test.6
|
||||||
else
|
else
|
||||||
Reset Test.1
|
Reset Test.1
|
||||||
|
Store Test.7: 1i64
|
||||||
Reuse Test.1
|
Reuse Test.1
|
||||||
Nothing 1i64
|
Nothing Test.7
|
||||||
Dec Test.1
|
|
||||||
"#
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn very_maybe_map_to_string() {
|
|
||||||
compiles_to_string(
|
|
||||||
r#"
|
|
||||||
Maybe a : [ Nothing, Just a ]
|
|
||||||
|
|
||||||
veryMaybe : Maybe (Maybe Int)
|
|
||||||
veryMaybe = Just (Just 3)
|
|
||||||
|
|
||||||
when veryMaybe is
|
|
||||||
Just (Just _) -> Just (Just 1)
|
|
||||||
Just Nothing -> Just Nothing
|
|
||||||
Nothing -> Nothing
|
|
||||||
"#,
|
|
||||||
indoc!(
|
|
||||||
r#"
|
|
||||||
Store Test.1: Just 0i64 Just 0i64 3i64
|
|
||||||
Store Test.1: Load Test.1
|
|
||||||
Store Test.5: Lowlevel.And (Lowlevel.Eq 0i64 (Access @0 Load Test.1)) true
|
|
||||||
if Test.5 then
|
|
||||||
if Test.4 then
|
|
||||||
Just 0i64 Just 0i64 1i64
|
|
||||||
else
|
|
||||||
Just 0i64 Nothing 1i64
|
|
||||||
else
|
|
||||||
Reset Test.1
|
|
||||||
Reuse Test.1
|
|
||||||
Nothing 1i64
|
|
||||||
Dec Test.1
|
Dec Test.1
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
|
@ -932,23 +795,29 @@ mod test_mono {
|
||||||
"#,
|
"#,
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
Store Test.1: These 1i64 1i64 2i64
|
Store Test.1:
|
||||||
Store Test.1: Load Test.1
|
Store Test.6: 1i64
|
||||||
|
Store Test.7: 1i64
|
||||||
|
Store Test.8: 2i64
|
||||||
|
These Test.6 Test.7 Test.8
|
||||||
switch Test.1:
|
switch Test.1:
|
||||||
case 2:
|
case 2:
|
||||||
Reset Test.1
|
Reset Test.1
|
||||||
|
Store Test.9: 2i64
|
||||||
Reuse Test.1
|
Reuse Test.1
|
||||||
This 2i64 (Load Test.2)
|
This Test.9 Test.2
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
Reset Test.1
|
Reset Test.1
|
||||||
|
Store Test.11: 0i64
|
||||||
Reuse Test.1
|
Reuse Test.1
|
||||||
That 0i64 (Load Test.3)
|
That Test.11 Test.3
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Reset Test.1
|
Reset Test.1
|
||||||
|
Store Test.13: 1i64
|
||||||
Reuse Test.1
|
Reuse Test.1
|
||||||
These 1i64 (Load Test.5) (Load Test.4)
|
These Test.13 Test.5 Test.4
|
||||||
|
|
||||||
Dec Test.1
|
Dec Test.1
|
||||||
"#
|
"#
|
||||||
|
@ -1042,7 +911,6 @@ mod test_mono {
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
procedure Test.0 (Test.2):
|
procedure Test.0 (Test.2):
|
||||||
Store Test.2: Load Test.2
|
|
||||||
Store Test.3: Lowlevel.And (Lowlevel.Eq true (Load Test.2)) true
|
Store Test.3: Lowlevel.And (Lowlevel.Eq true (Load Test.2)) true
|
||||||
if Test.3 then
|
if Test.3 then
|
||||||
true
|
true
|
||||||
|
@ -1067,7 +935,7 @@ mod test_mono {
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
procedure Test.0 (Test.2):
|
procedure Test.0 (Test.2):
|
||||||
Struct [(Load(`Test.y`), Builtin(List(Owned, Builtin(Int64)))), (Load(`Test.y`), Builtin(List(Owned, Builtin(Int64))))]
|
Struct { Load Test.2, Load Test.2 }
|
||||||
Dec Test.2
|
Dec Test.2
|
||||||
|
|
||||||
Call Test.0 [ 1i64 ]
|
Call Test.0 [ 1i64 ]
|
||||||
|
@ -1075,4 +943,194 @@ mod test_mono {
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn compiles_to_ir(src: &str, expected: &str) {
|
||||||
|
let arena = Bump::new();
|
||||||
|
let CanExprOut {
|
||||||
|
loc_expr,
|
||||||
|
var_store,
|
||||||
|
var,
|
||||||
|
constraint,
|
||||||
|
home,
|
||||||
|
mut interns,
|
||||||
|
..
|
||||||
|
} = can_expr(src);
|
||||||
|
|
||||||
|
let subs = Subs::new(var_store.into());
|
||||||
|
let mut unify_problems = Vec::new();
|
||||||
|
let (_content, mut subs) = infer_expr(subs, &mut unify_problems, &constraint, var);
|
||||||
|
|
||||||
|
// Compile and add all the Procs before adding main
|
||||||
|
let mut procs = roc_mono::experiment::Procs::default();
|
||||||
|
let mut ident_ids = interns.all_ident_ids.remove(&home).unwrap();
|
||||||
|
|
||||||
|
// assume 64-bit pointers
|
||||||
|
let pointer_size = std::mem::size_of::<u64>() as u32;
|
||||||
|
|
||||||
|
// Populate Procs and Subs, and get the low-level Expr from the canonical Expr
|
||||||
|
let mut mono_problems = Vec::new();
|
||||||
|
let mut mono_env = roc_mono::experiment::Env {
|
||||||
|
arena: &arena,
|
||||||
|
subs: &mut subs,
|
||||||
|
problems: &mut mono_problems,
|
||||||
|
home,
|
||||||
|
ident_ids: &mut ident_ids,
|
||||||
|
pointer_size,
|
||||||
|
jump_counter: arena.alloc(0),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut layout_cache = LayoutCache::default();
|
||||||
|
let ir_expr = roc_mono::experiment::from_can(
|
||||||
|
&mut mono_env,
|
||||||
|
loc_expr.value,
|
||||||
|
&mut procs,
|
||||||
|
&mut layout_cache,
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
let mono_expr = Expr::new(&mut mono_env, loc_expr.value, &mut procs);
|
||||||
|
let procs =
|
||||||
|
roc_mono::expr::specialize_all(&mut mono_env, procs, &mut LayoutCache::default());
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
procs.runtime_errors,
|
||||||
|
roc_collections::all::MutMap::default()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Put this module's ident_ids back in the interns
|
||||||
|
interns.all_ident_ids.insert(home, ident_ids);
|
||||||
|
|
||||||
|
let mut procs_string = procs
|
||||||
|
.specialized
|
||||||
|
.iter()
|
||||||
|
.map(|(_, value)| {
|
||||||
|
if let InProgressProc::Done(proc) = value {
|
||||||
|
proc.to_pretty(200)
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
dbg!(&mono_expr);
|
||||||
|
*/
|
||||||
|
let mut procs_string = vec![];
|
||||||
|
procs_string.push(ir_expr.to_pretty(200));
|
||||||
|
|
||||||
|
let result = procs_string.join("\n");
|
||||||
|
|
||||||
|
assert_eq!(result, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ir_int_literal() {
|
||||||
|
compiles_to_ir(
|
||||||
|
r#"
|
||||||
|
5
|
||||||
|
"#,
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
let Test.0 = 5i64;
|
||||||
|
ret Test.0;
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ir_assignment() {
|
||||||
|
compiles_to_ir(
|
||||||
|
r#"
|
||||||
|
x = 5
|
||||||
|
|
||||||
|
x
|
||||||
|
"#,
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
let Test.0 = 5i64;
|
||||||
|
ret Test.0;
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ir_if() {
|
||||||
|
compiles_to_ir(
|
||||||
|
r#"
|
||||||
|
if True then 1 else 2
|
||||||
|
"#,
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
let Test.1 = true;
|
||||||
|
if Test.1 then
|
||||||
|
let Test.2 = 1i64;
|
||||||
|
ret Test.2;
|
||||||
|
else
|
||||||
|
let Test.0 = 2i64;
|
||||||
|
ret Test.0;
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ir_when_enum() {
|
||||||
|
compiles_to_ir(
|
||||||
|
r#"
|
||||||
|
when Blue is
|
||||||
|
Red -> 1
|
||||||
|
White -> 2
|
||||||
|
Blue -> 3
|
||||||
|
"#,
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
let Test.0 = 0u8;
|
||||||
|
switch Test.0:
|
||||||
|
case 1:
|
||||||
|
let Test.1 = 1i64;
|
||||||
|
ret Test.1;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
let Test.2 = 2i64;
|
||||||
|
ret Test.2;
|
||||||
|
|
||||||
|
default:
|
||||||
|
let Test.3 = 3i64;
|
||||||
|
ret Test.3;
|
||||||
|
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ir_when_maybe() {
|
||||||
|
compiles_to_ir(
|
||||||
|
r#"
|
||||||
|
when Just 3 is
|
||||||
|
Just n -> n
|
||||||
|
Nothing -> 0
|
||||||
|
"#,
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
let Test.0 = 0u8;
|
||||||
|
switch Test.0:
|
||||||
|
case 1:
|
||||||
|
let Test.1 = 1i64;
|
||||||
|
ret Test.1;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
let Test.2 = 2i64;
|
||||||
|
ret Test.2;
|
||||||
|
|
||||||
|
default:
|
||||||
|
let Test.3 = 3i64;
|
||||||
|
ret Test.3;
|
||||||
|
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue