Merge remote-tracking branch 'origin/trunk' into effect-example

This commit is contained in:
Richard Feldman 2021-07-19 20:50:31 -04:00
commit 0dd05b02d5
8 changed files with 318 additions and 197 deletions

View File

@ -1,10 +1,10 @@
use morphic_lib::TypeContext;
use morphic_lib::{
BlockExpr, BlockId, CalleeSpecVar, ConstDefBuilder, ConstName, EntryPointName, ExprContext,
FuncDef, FuncDefBuilder, FuncName, ModDefBuilder, ModName, ProgramBuilder, Result, TypeId,
UpdateModeVar, ValueId,
FuncDef, FuncDefBuilder, FuncName, ModDefBuilder, ModName, ProgramBuilder, Result,
TypeDefBuilder, TypeId, TypeName, UpdateModeVar, ValueId,
};
use roc_collections::all::MutMap;
use roc_collections::all::{MutMap, MutSet};
use roc_module::low_level::LowLevel;
use roc_module::symbol::Symbol;
use std::convert::TryFrom;
@ -26,6 +26,26 @@ pub fn func_name_bytes(proc: &Proc) -> [u8; SIZE] {
const DEBUG: bool = false;
const SIZE: usize = if DEBUG { 50 } else { 16 };
#[derive(Debug, Clone, Copy, Hash)]
struct TagUnionId(u64);
fn recursive_tag_union_name_bytes(union_layout: &UnionLayout) -> TagUnionId {
use std::collections::hash_map::DefaultHasher;
use std::hash::Hash;
use std::hash::Hasher;
let mut hasher = DefaultHasher::new();
union_layout.hash(&mut hasher);
TagUnionId(hasher.finish())
}
impl TagUnionId {
const fn as_bytes(&self) -> [u8; 8] {
self.0.to_ne_bytes()
}
}
pub fn func_name_bytes_help<'a, I>(
symbol: Symbol,
argument_layouts: I,
@ -134,6 +154,8 @@ where
let entry_point_name = FuncName(ENTRY_POINT_NAME);
m.add_func(entry_point_name, entry_point_function)?;
let mut type_definitions = MutSet::default();
// all other functions
for proc in procs {
let bytes = func_name_bytes(proc);
@ -148,11 +170,32 @@ where
);
}
let spec = proc_spec(proc)?;
let (spec, type_names) = proc_spec(proc)?;
type_definitions.extend(type_names);
m.add_func(func_name, spec)?;
}
for union_layout in type_definitions {
let type_name_bytes = recursive_tag_union_name_bytes(&union_layout).as_bytes();
let type_name = TypeName(&type_name_bytes);
let mut builder = TypeDefBuilder::new();
let variant_types = build_variant_types(&mut builder, &union_layout)?;
let root_type = if let UnionLayout::NonNullableUnwrapped(_) = union_layout {
debug_assert_eq!(variant_types.len(), 1);
variant_types[0]
} else {
builder.add_union_type(&variant_types)?
};
let type_def = builder.build(root_type)?;
m.add_named_type(type_name, type_def)?;
}
m.build()?
};
@ -195,7 +238,7 @@ fn build_entry_point(layout: crate::ir::ProcLayout, func_name: FuncName) -> Resu
Ok(spec)
}
fn proc_spec(proc: &Proc) -> Result<FuncDef> {
fn proc_spec<'a>(proc: &Proc<'a>) -> Result<(FuncDef, MutSet<UnionLayout<'a>>)> {
let mut builder = FuncDefBuilder::new();
let mut env = Env::default();
@ -218,21 +261,22 @@ fn proc_spec(proc: &Proc) -> Result<FuncDef> {
let spec = builder.build(arg_type_id, ret_type_id, root)?;
Ok(spec)
Ok((spec, env.type_names))
}
#[derive(Default)]
struct Env {
struct Env<'a> {
symbols: MutMap<Symbol, ValueId>,
join_points: MutMap<crate::ir::JoinPointId, morphic_lib::ContinuationId>,
type_names: MutSet<UnionLayout<'a>>,
}
fn stmt_spec(
fn stmt_spec<'a>(
builder: &mut FuncDefBuilder,
env: &mut Env,
env: &mut Env<'a>,
block: BlockId,
layout: &Layout,
stmt: &Stmt,
stmt: &Stmt<'a>,
) -> Result<ValueId> {
use Stmt::*;
@ -420,7 +464,27 @@ fn build_tuple_value(
builder.add_make_tuple(block, &value_ids)
}
fn build_tuple_type(builder: &mut FuncDefBuilder, layouts: &[Layout]) -> Result<TypeId> {
#[derive(Clone, Debug, PartialEq)]
enum WhenRecursive<'a> {
Unreachable,
Loop(UnionLayout<'a>),
}
fn build_recursive_tuple_type(
builder: &mut impl TypeContext,
layouts: &[Layout],
when_recursive: &WhenRecursive,
) -> Result<TypeId> {
let mut field_types = Vec::new();
for field in layouts.iter() {
field_types.push(layout_spec_help(builder, field, when_recursive)?);
}
builder.add_tuple_type(&field_types)
}
fn build_tuple_type(builder: &mut impl TypeContext, layouts: &[Layout]) -> Result<TypeId> {
let mut field_types = Vec::new();
for field in layouts.iter() {
@ -854,46 +918,95 @@ fn lowlevel_spec(
}
}
fn recursive_tag_variant(
builder: &mut impl TypeContext,
union_layout: &UnionLayout,
fields: &[Layout],
) -> Result<TypeId> {
let when_recursive = WhenRecursive::Loop(*union_layout);
let data_id = build_recursive_tuple_type(builder, fields, &when_recursive)?;
let cell_id = builder.add_heap_cell_type();
builder.add_tuple_type(&[cell_id, data_id])
}
fn build_variant_types(
builder: &mut FuncDefBuilder,
builder: &mut impl TypeContext,
union_layout: &UnionLayout,
) -> Result<Vec<TypeId>> {
use UnionLayout::*;
let mut result = Vec::new();
let mut result;
match union_layout {
NonRecursive(tags) => {
result = Vec::with_capacity(tags.len());
for tag in tags.iter() {
result.push(build_tuple_type(builder, tag)?);
}
}
Recursive(_) => unreachable!(),
NonNullableUnwrapped(_) => unreachable!(),
Recursive(tags) => {
result = Vec::with_capacity(tags.len());
for tag in tags.iter() {
result.push(recursive_tag_variant(builder, union_layout, tag)?);
}
}
NonNullableUnwrapped(fields) => {
result = vec![recursive_tag_variant(builder, union_layout, fields)?];
}
NullableWrapped {
nullable_id: _,
other_tags: _,
} => unreachable!(),
nullable_id,
other_tags: tags,
} => {
result = Vec::with_capacity(tags.len() + 1);
let cutoff = *nullable_id as usize;
for tag in tags[..cutoff].iter() {
result.push(recursive_tag_variant(builder, union_layout, tag)?);
}
let unit = builder.add_tuple_type(&[])?;
result.push(unit);
for tag in tags[cutoff..].iter() {
result.push(recursive_tag_variant(builder, union_layout, tag)?);
}
}
NullableUnwrapped {
nullable_id: _,
other_fields: _,
} => unreachable!(),
nullable_id,
other_fields: fields,
} => {
let unit = builder.add_tuple_type(&[])?;
let other_type = recursive_tag_variant(builder, union_layout, fields)?;
if *nullable_id {
// nullable_id == 1
result = vec![other_type, unit];
} else {
result = vec![unit, other_type];
}
}
}
Ok(result)
}
#[allow(dead_code)]
fn worst_case_type(context: &mut impl TypeContext) -> Result<TypeId> {
let cell = context.add_heap_cell_type();
context.add_bag_type(cell)
}
fn expr_spec(
fn expr_spec<'a>(
builder: &mut FuncDefBuilder,
env: &mut Env,
env: &mut Env<'a>,
block: BlockId,
layout: &Layout,
expr: &Expr,
layout: &Layout<'a>,
expr: &Expr<'a>,
) -> Result<ValueId> {
use Expr::*;
@ -912,21 +1025,54 @@ fn expr_spec(
tag_name: _,
tag_id,
arguments,
} => match tag_layout {
UnionLayout::NonRecursive(_) => {
let value_id = build_tuple_value(builder, env, block, arguments)?;
let variant_types = build_variant_types(builder, tag_layout)?;
builder.add_make_union(block, &variant_types, *tag_id as u32, value_id)
}
UnionLayout::Recursive(_)
| UnionLayout::NonNullableUnwrapped(_)
| UnionLayout::NullableWrapped { .. }
| UnionLayout::NullableUnwrapped { .. } => {
let result_type = worst_case_type(builder)?;
let value_id = build_tuple_value(builder, env, block, arguments)?;
builder.add_unknown_with(block, &[value_id], result_type)
}
},
} => {
let variant_types = build_variant_types(builder, tag_layout)?;
let data_id = build_tuple_value(builder, env, block, arguments)?;
let cell_id = builder.add_new_heap_cell(block)?;
let value_id = match tag_layout {
UnionLayout::NonRecursive(_) => {
let value_id = build_tuple_value(builder, env, block, arguments)?;
return builder.add_make_union(block, &variant_types, *tag_id as u32, value_id);
}
UnionLayout::NonNullableUnwrapped(_) => {
let value_id = builder.add_make_tuple(block, &[cell_id, data_id])?;
let type_name_bytes = recursive_tag_union_name_bytes(tag_layout).as_bytes();
let type_name = TypeName(&type_name_bytes);
env.type_names.insert(*tag_layout);
return builder.add_make_named(block, MOD_APP, type_name, value_id);
}
UnionLayout::Recursive(_) => builder.add_make_tuple(block, &[cell_id, data_id])?,
UnionLayout::NullableWrapped { nullable_id, .. } => {
if *tag_id == *nullable_id as u8 {
data_id
} else {
builder.add_make_tuple(block, &[cell_id, data_id])?
}
}
UnionLayout::NullableUnwrapped { nullable_id, .. } => {
if *tag_id == *nullable_id as u8 {
data_id
} else {
builder.add_make_tuple(block, &[cell_id, data_id])?
}
}
};
let union_id =
builder.add_make_union(block, &variant_types, *tag_id as u32, value_id)?;
let type_name_bytes = recursive_tag_union_name_bytes(tag_layout).as_bytes();
let type_name = TypeName(&type_name_bytes);
env.type_names.insert(*tag_layout);
builder.add_make_named(block, MOD_APP, type_name, union_id)
}
Struct(fields) => build_tuple_value(builder, env, block, fields),
UnionAtIndex {
index,
@ -942,11 +1088,45 @@ fn expr_spec(
builder.add_get_tuple_field(block, tuple_value_id, index)
}
_ => {
// for the moment recursive tag unions don't quite work
let value_id = env.symbols[structure];
let result_type = layout_spec(builder, layout)?;
builder.add_unknown_with(block, &[value_id], result_type)
UnionLayout::Recursive(_)
| UnionLayout::NullableUnwrapped { .. }
| UnionLayout::NullableWrapped { .. } => {
let index = (*index) as u32;
let tag_value_id = env.symbols[structure];
let type_name_bytes = recursive_tag_union_name_bytes(&union_layout).as_bytes();
let type_name = TypeName(&type_name_bytes);
let union_id = builder.add_unwrap_named(block, MOD_APP, type_name, tag_value_id)?;
let variant_id = builder.add_unwrap_union(block, union_id, *tag_id as u32)?;
// we're reading from this value, so touch the heap cell
let heap_cell = builder.add_get_tuple_field(block, variant_id, 0)?;
builder.add_touch(block, heap_cell)?;
let tuple_value_id = builder.add_get_tuple_field(block, variant_id, 1)?;
builder.add_get_tuple_field(block, tuple_value_id, index)
}
UnionLayout::NonNullableUnwrapped { .. } => {
let index = (*index) as u32;
debug_assert!(*tag_id == 0);
let tag_value_id = env.symbols[structure];
let type_name_bytes = recursive_tag_union_name_bytes(&union_layout).as_bytes();
let type_name = TypeName(&type_name_bytes);
let variant_id =
builder.add_unwrap_named(block, MOD_APP, type_name, tag_value_id)?;
// we're reading from this value, so touch the heap cell
let heap_cell = builder.add_get_tuple_field(block, variant_id, 0)?;
builder.add_touch(block, heap_cell)?;
let tuple_value_id = builder.add_get_tuple_field(block, variant_id, 1)?;
builder.add_get_tuple_field(block, tuple_value_id, index)
}
},
StructAtIndex {
@ -1017,34 +1197,66 @@ fn literal_spec(
}
}
fn layout_spec(builder: &mut FuncDefBuilder, layout: &Layout) -> Result<TypeId> {
fn layout_spec(builder: &mut impl TypeContext, layout: &Layout) -> Result<TypeId> {
layout_spec_help(builder, layout, &WhenRecursive::Unreachable)
}
fn layout_spec_help(
builder: &mut impl TypeContext,
layout: &Layout,
when_recursive: &WhenRecursive,
) -> Result<TypeId> {
use Layout::*;
match layout {
Builtin(builtin) => builtin_spec(builder, builtin),
Struct(fields) => build_tuple_type(builder, fields),
Union(union_layout) => match union_layout {
UnionLayout::NonRecursive(_) => {
let variant_types = build_variant_types(builder, union_layout)?;
builder.add_union_type(&variant_types)
Builtin(builtin) => builtin_spec(builder, builtin, when_recursive),
Struct(fields) => build_recursive_tuple_type(builder, fields, when_recursive),
Union(union_layout) => {
let variant_types = build_variant_types(builder, union_layout)?;
match union_layout {
UnionLayout::NonRecursive(_) => builder.add_union_type(&variant_types),
UnionLayout::Recursive(_)
| UnionLayout::NullableUnwrapped { .. }
| UnionLayout::NullableWrapped { .. }
| UnionLayout::NonNullableUnwrapped(_) => {
let type_name_bytes = recursive_tag_union_name_bytes(&union_layout).as_bytes();
let type_name = TypeName(&type_name_bytes);
Ok(builder.add_named_type(MOD_APP, type_name))
}
}
UnionLayout::Recursive(_) => worst_case_type(builder),
UnionLayout::NonNullableUnwrapped(_) => worst_case_type(builder),
UnionLayout::NullableWrapped {
nullable_id: _,
other_tags: _,
} => worst_case_type(builder),
UnionLayout::NullableUnwrapped {
nullable_id: _,
other_fields: _,
} => worst_case_type(builder),
}
RecursivePointer => match when_recursive {
WhenRecursive::Unreachable => {
unreachable!()
}
WhenRecursive::Loop(union_layout) => match union_layout {
UnionLayout::NonRecursive(_) => unreachable!(),
UnionLayout::Recursive(_)
| UnionLayout::NullableUnwrapped { .. }
| UnionLayout::NullableWrapped { .. }
| UnionLayout::NonNullableUnwrapped(_) => {
let type_name_bytes = recursive_tag_union_name_bytes(union_layout).as_bytes();
let type_name = TypeName(&type_name_bytes);
Ok(builder.add_named_type(MOD_APP, type_name))
}
},
},
RecursivePointer => worst_case_type(builder),
Closure(_, lambda_set, _) => layout_spec(builder, &lambda_set.runtime_representation()),
Closure(_, lambda_set, _) => layout_spec_help(
builder,
&lambda_set.runtime_representation(),
when_recursive,
),
}
}
fn builtin_spec(builder: &mut FuncDefBuilder, builtin: &Builtin) -> Result<TypeId> {
fn builtin_spec(
builder: &mut impl TypeContext,
builtin: &Builtin,
when_recursive: &WhenRecursive,
) -> Result<TypeId> {
use Builtin::*;
match builtin {
@ -1052,8 +1264,8 @@ fn builtin_spec(builder: &mut FuncDefBuilder, builtin: &Builtin) -> Result<TypeI
Float128 | Float64 | Float32 | Float16 => builder.add_tuple_type(&[]),
Str | EmptyStr => str_type(builder),
Dict(key_layout, value_layout) => {
let value_type = layout_spec(builder, value_layout)?;
let key_type = layout_spec(builder, key_layout)?;
let value_type = layout_spec_help(builder, value_layout, when_recursive)?;
let key_type = layout_spec_help(builder, key_layout, when_recursive)?;
let element_type = builder.add_tuple_type(&[key_type, value_type])?;
let cell = builder.add_heap_cell_type();
@ -1062,7 +1274,7 @@ fn builtin_spec(builder: &mut FuncDefBuilder, builtin: &Builtin) -> Result<TypeI
}
Set(key_layout) => {
let value_type = builder.add_tuple_type(&[])?;
let key_type = layout_spec(builder, key_layout)?;
let key_type = layout_spec_help(builder, key_layout, when_recursive)?;
let element_type = builder.add_tuple_type(&[key_type, value_type])?;
let cell = builder.add_heap_cell_type();
@ -1070,7 +1282,7 @@ fn builtin_spec(builder: &mut FuncDefBuilder, builtin: &Builtin) -> Result<TypeI
builder.add_tuple_type(&[cell, bag])
}
List(element_layout) => {
let element_type = layout_spec(builder, element_layout)?;
let element_type = layout_spec_help(builder, element_layout, when_recursive)?;
let cell = builder.add_heap_cell_type();
let bag = builder.add_bag_type(element_type)?;

View File

@ -4191,13 +4191,23 @@ fn convert_tag_union<'a>(
let field_symbols_temp = sorted_field_symbols(env, procs, layout_cache, args);
let field_symbols;
let opt_tag_id_symbol;
// we must derive the union layout from the whole_var, building it up
// from `layouts` would unroll recursive tag unions, and that leads to
// problems down the line because we hash layouts and an unrolled
// version is not the same as the minimal version.
let union_layout = match return_on_layout_error!(
env,
layout_cache.from_var(env.arena, variant_var, env.subs)
) {
Layout::Union(ul) => ul,
_ => unreachable!(),
};
use WrappedVariant::*;
let (tag, union_layout) = match variant {
Recursive { sorted_tag_layouts } => {
debug_assert!(sorted_tag_layouts.len() > 1);
opt_tag_id_symbol = None;
field_symbols = {
let mut temp = Vec::with_capacity_in(field_symbols_temp.len() + 1, arena);
@ -4214,9 +4224,6 @@ fn convert_tag_union<'a>(
layouts.push(arg_layouts);
}
debug_assert!(layouts.len() > 1);
let union_layout = UnionLayout::Recursive(layouts.into_bump_slice());
let tag = Expr::Tag {
tag_layout: union_layout,
tag_name,
@ -4227,13 +4234,11 @@ fn convert_tag_union<'a>(
(tag, union_layout)
}
NonNullableUnwrapped {
fields,
tag_name: wrapped_tag_name,
..
} => {
debug_assert_eq!(tag_name, wrapped_tag_name);
opt_tag_id_symbol = None;
field_symbols = {
let mut temp = Vec::with_capacity_in(field_symbols_temp.len(), arena);
@ -4242,8 +4247,6 @@ fn convert_tag_union<'a>(
temp.into_bump_slice()
};
let union_layout = UnionLayout::NonNullableUnwrapped(fields);
let tag = Expr::Tag {
tag_layout: union_layout,
tag_name,
@ -4254,8 +4257,6 @@ fn convert_tag_union<'a>(
(tag, union_layout)
}
NonRecursive { sorted_tag_layouts } => {
opt_tag_id_symbol = None;
field_symbols = {
let mut temp = Vec::with_capacity_in(field_symbols_temp.len(), arena);
@ -4271,8 +4272,6 @@ fn convert_tag_union<'a>(
layouts.push(arg_layouts);
}
let union_layout = UnionLayout::NonRecursive(layouts.into_bump_slice());
let tag = Expr::Tag {
tag_layout: union_layout,
tag_name,
@ -4283,12 +4282,8 @@ fn convert_tag_union<'a>(
(tag, union_layout)
}
NullableWrapped {
nullable_id,
nullable_name: _,
sorted_tag_layouts,
sorted_tag_layouts, ..
} => {
opt_tag_id_symbol = None;
field_symbols = {
let mut temp = Vec::with_capacity_in(field_symbols_temp.len() + 1, arena);
@ -4304,11 +4299,6 @@ fn convert_tag_union<'a>(
layouts.push(arg_layouts);
}
let union_layout = UnionLayout::NullableWrapped {
nullable_id,
other_tags: layouts.into_bump_slice(),
};
let tag = Expr::Tag {
tag_layout: union_layout,
tag_name,
@ -4318,16 +4308,7 @@ fn convert_tag_union<'a>(
(tag, union_layout)
}
NullableUnwrapped {
nullable_id,
nullable_name: _,
other_name: _,
other_fields,
} => {
// FIXME drop tag
let tag_id_symbol = env.unique_symbol();
opt_tag_id_symbol = Some(tag_id_symbol);
NullableUnwrapped { .. } => {
field_symbols = {
let mut temp = Vec::with_capacity_in(field_symbols_temp.len() + 1, arena);
@ -4336,11 +4317,6 @@ fn convert_tag_union<'a>(
temp.into_bump_slice()
};
let union_layout = UnionLayout::NullableUnwrapped {
nullable_id,
other_fields,
};
let tag = Expr::Tag {
tag_layout: union_layout,
tag_name,
@ -4352,26 +4328,14 @@ fn convert_tag_union<'a>(
}
};
let mut stmt = Stmt::Let(assigned, tag, Layout::Union(union_layout), hole);
let stmt = Stmt::Let(assigned, tag, Layout::Union(union_layout), hole);
let iter = field_symbols_temp
.into_iter()
.map(|x| x.2 .0)
.rev()
.zip(field_symbols.iter().rev());
stmt = assign_to_symbols(env, procs, layout_cache, iter, stmt);
if let Some(tag_id_symbol) = opt_tag_id_symbol {
// define the tag id
stmt = Stmt::Let(
tag_id_symbol,
Expr::Literal(Literal::Int(tag_id as i128)),
union_layout.tag_id_layout(),
arena.alloc(stmt),
);
}
stmt
assign_to_symbols(env, procs, layout_cache, iter, stmt)
}
}
}
@ -7047,6 +7011,15 @@ fn from_can_pattern_help<'a>(
temp
};
// we must derive the union layout from the whole_var, building it up
// from `layouts` would unroll recursive tag unions, and that leads to
// problems down the line because we hash layouts and an unrolled
// version is not the same as the minimal version.
let layout = match layout_cache.from_var(env.arena, *whole_var, env.subs) {
Ok(Layout::Union(ul)) => ul,
_ => unreachable!(),
};
use WrappedVariant::*;
match variant {
NonRecursive {
@ -7091,18 +7064,6 @@ fn from_can_pattern_help<'a>(
));
}
let layouts: Vec<&'a [Layout<'a>]> = {
let mut temp = Vec::with_capacity_in(tags.len(), env.arena);
for (_, arg_layouts) in tags.into_iter() {
temp.push(*arg_layouts);
}
temp
};
let layout = UnionLayout::NonRecursive(layouts.into_bump_slice());
Pattern::AppliedTag {
tag_name: tag_name.clone(),
tag_id: tag_id as u8,
@ -7148,19 +7109,6 @@ fn from_can_pattern_help<'a>(
));
}
let layouts: Vec<&'a [Layout<'a>]> = {
let mut temp = Vec::with_capacity_in(tags.len(), env.arena);
for (_, arg_layouts) in tags.into_iter() {
temp.push(*arg_layouts);
}
temp
};
debug_assert!(layouts.len() > 1);
let layout = UnionLayout::Recursive(layouts.into_bump_slice());
Pattern::AppliedTag {
tag_name: tag_name.clone(),
tag_id: tag_id as u8,
@ -7204,8 +7152,6 @@ fn from_can_pattern_help<'a>(
));
}
let layout = UnionLayout::NonNullableUnwrapped(fields);
Pattern::AppliedTag {
tag_name: tag_name.clone(),
tag_id: tag_id as u8,
@ -7279,21 +7225,6 @@ fn from_can_pattern_help<'a>(
));
}
let layouts: Vec<&'a [Layout<'a>]> = {
let mut temp = Vec::with_capacity_in(tags.len(), env.arena);
for (_, arg_layouts) in tags.into_iter() {
temp.push(*arg_layouts);
}
temp
};
let layout = UnionLayout::NullableWrapped {
nullable_id,
other_tags: layouts.into_bump_slice(),
};
Pattern::AppliedTag {
tag_name: tag_name.clone(),
tag_id: tag_id as u8,
@ -7350,11 +7281,6 @@ fn from_can_pattern_help<'a>(
));
}
let layout = UnionLayout::NullableUnwrapped {
nullable_id,
other_fields,
};
Pattern::AppliedTag {
tag_name: tag_name.clone(),
tag_id: tag_id as u8,

View File

@ -21,10 +21,8 @@ procedure Test.3 (Test.4):
jump Test.13 Test.4;
procedure Test.0 ():
let Test.28 = 0i64;
let Test.30 = 3i64;
let Test.26 = Just Test.30;
let Test.29 = 1i64;
let Test.28 = 3i64;
let Test.26 = Just Test.28;
let Test.27 = Nil ;
let Test.12 = Cons Test.26 Test.27;
let Test.11 = CallByName Test.3 Test.12;

View File

@ -10,9 +10,7 @@ procedure Test.2 (Test.3):
ret Test.11;
procedure Test.0 ():
let Test.17 = 0i64;
let Test.15 = 2i64;
let Test.18 = 1i64;
let Test.16 = Nil ;
let Test.9 = Cons Test.15 Test.16;
let Test.8 = CallByName Test.2 Test.9;

View File

@ -17,7 +17,6 @@ procedure Test.3 (Test.5):
ret Test.14;
procedure Test.0 ():
let Test.21 = 1i64;
let Test.2 = Nil ;
let Test.8 = CallByName Test.3 Test.2;
let Test.9 = CallByName Test.3 Test.2;

View File

@ -1,10 +1,6 @@
procedure Test.0 ():
let Test.9 = 0i64;
let Test.11 = 0i64;
let Test.13 = 0i64;
let Test.14 = 1i64;
let Test.12 = Z ;
let Test.10 = S Test.12;
let Test.8 = S Test.10;
let Test.10 = Z ;
let Test.9 = S Test.10;
let Test.8 = S Test.9;
let Test.2 = S Test.8;
ret Test.2;

View File

@ -1,11 +1,7 @@
procedure Test.0 ():
let Test.13 = 0i64;
let Test.15 = 0i64;
let Test.17 = 0i64;
let Test.18 = 1i64;
let Test.16 = Z ;
let Test.14 = S Test.16;
let Test.12 = S Test.14;
let Test.14 = Z ;
let Test.13 = S Test.14;
let Test.12 = S Test.13;
let Test.2 = S Test.12;
let Test.9 = 1i64;
let Test.10 = GetTagId Test.2;

View File

@ -1,11 +1,7 @@
procedure Test.0 ():
let Test.19 = 0i64;
let Test.21 = 0i64;
let Test.23 = 0i64;
let Test.24 = 1i64;
let Test.22 = Z ;
let Test.20 = S Test.22;
let Test.18 = S Test.20;
let Test.20 = Z ;
let Test.19 = S Test.20;
let Test.18 = S Test.19;
let Test.2 = S Test.18;
let Test.15 = 0i64;
let Test.16 = GetTagId Test.2;