Update dev backend

This commit is contained in:
Ayaz Hafiz 2023-01-03 20:35:09 -06:00
parent 45aa9768f7
commit 6859c2e15c
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
8 changed files with 1154 additions and 356 deletions

View file

@ -14,7 +14,7 @@ use roc_mono::ir::{
Literal, ModifyRc, OptLevel, Proc, ProcLayout, SingleEntryPoint, Stmt,
};
use roc_mono::layout::{
Builtin, FieldOrderHash, Layout, LayoutInterner, Niche, RawFunctionLayout, STLayoutInterner,
Builtin, InLayout, Layout, LayoutInterner, Niche, RawFunctionLayout, STLayoutInterner,
UnionLayout,
};
@ -31,7 +31,7 @@ pub fn func_name_bytes(proc: &Proc) -> [u8; SIZE] {
proc.name.name(),
proc.args.iter().map(|x| x.0),
proc.name.niche(),
&proc.ret_layout,
proc.ret_layout,
);
bytes
}
@ -75,10 +75,10 @@ pub fn func_name_bytes_help<'a, I>(
symbol: Symbol,
argument_layouts: I,
niche: Niche<'a>,
return_layout: &Layout<'a>,
return_layout: InLayout<'a>,
) -> [u8; SIZE]
where
I: IntoIterator<Item = Layout<'a>>,
I: IntoIterator<Item = InLayout<'a>>,
{
let mut name_bytes = [0u8; SIZE];
@ -189,13 +189,13 @@ where
RawFunctionLayout::Function(_, _, _) => {
let it = top_level.arguments.iter().copied();
let bytes =
func_name_bytes_help(*symbol, it, Niche::NONE, &top_level.result);
func_name_bytes_help(*symbol, it, Niche::NONE, top_level.result);
host_exposed_functions.push((bytes, top_level.arguments));
}
RawFunctionLayout::ZeroArgumentThunk(_) => {
let bytes =
func_name_bytes_help(*symbol, [], Niche::NONE, &top_level.result);
func_name_bytes_help(*symbol, [], Niche::NONE, top_level.result);
host_exposed_functions.push((bytes, top_level.arguments));
}
@ -229,11 +229,11 @@ where
entry_point_symbol,
entry_point_layout.arguments.iter().copied(),
Niche::NONE,
&entry_point_layout.result,
entry_point_layout.result,
);
let roc_main = FuncName(&roc_main_bytes);
let mut env = Env::new(arena);
let mut env = Env::new();
let entry_point_function = build_entry_point(
&mut env,
@ -252,10 +252,7 @@ where
// construct a big pattern match picking one of the expects at random
let layout: ProcLayout<'a> = ProcLayout {
arguments: &[],
result: Layout::Struct {
field_order_hash: FieldOrderHash::from_ordered_fields(&[]),
field_layouts: &[],
},
result: Layout::UNIT,
niche: Niche::NONE,
};
@ -263,13 +260,13 @@ where
.iter()
.map(|symbol| {
(
func_name_bytes_help(*symbol, [], Niche::NONE, &layout.result),
func_name_bytes_help(*symbol, [], Niche::NONE, layout.result),
[].as_slice(),
)
})
.collect();
let mut env = Env::new(arena);
let mut env = Env::new();
let entry_point_function =
build_entry_point(&mut env, interner, layout, None, &host_exposed)?;
@ -286,7 +283,7 @@ where
let mut builder = TypeDefBuilder::new();
let mut env = Env::new(arena);
let mut env = Env::new();
let variant_types =
recursive_variant_types(&mut env, &mut builder, interner, &union_layout)?;
@ -351,10 +348,10 @@ fn terrible_hack(builder: &mut FuncDefBuilder, block: BlockId, type_id: TypeId)
fn build_entry_point<'a>(
env: &mut Env<'a>,
interner: &STLayoutInterner<'a>,
interner: &mut STLayoutInterner<'a>,
layout: roc_mono::ir::ProcLayout<'a>,
entry_point_function: Option<FuncName>,
host_exposed_functions: &[([u8; SIZE], &'a [Layout<'a>])],
host_exposed_functions: &[([u8; SIZE], &'a [InLayout<'a>])],
) -> Result<FuncDef> {
let mut builder = FuncDefBuilder::new();
let outer_block = builder.add_block();
@ -400,11 +397,12 @@ fn build_entry_point<'a>(
let block = builder.add_block();
let struct_layout = interner.insert(Layout::struct_no_name_order(layouts));
let type_id = layout_spec(
env,
&mut builder,
interner,
env.arena.alloc(Layout::struct_no_name_order(layouts)),
struct_layout,
&WhenRecursive::Unreachable,
)?;
@ -439,7 +437,7 @@ fn proc_spec<'a>(
proc: &Proc<'a>,
) -> Result<(FuncDef, MutSet<UnionLayout<'a>>)> {
let mut builder = FuncDefBuilder::new();
let mut env = Env::new(arena);
let mut env = Env::new();
let block = builder.add_block();
@ -457,25 +455,26 @@ fn proc_spec<'a>(
interner,
&mut env,
block,
&proc.ret_layout,
proc.ret_layout,
&proc.body,
)?;
let root = BlockExpr(block, value_id);
let args_struct_layout = interner.insert(Layout::struct_no_name_order(
argument_layouts.into_bump_slice(),
));
let arg_type_id = layout_spec(
&mut env,
&mut builder,
interner,
arena.alloc(Layout::struct_no_name_order(
argument_layouts.into_bump_slice(),
)),
args_struct_layout,
&WhenRecursive::Unreachable,
)?;
let ret_type_id = layout_spec(
&mut env,
&mut builder,
interner,
&proc.ret_layout,
proc.ret_layout,
&WhenRecursive::Unreachable,
)?;
@ -485,16 +484,14 @@ fn proc_spec<'a>(
}
struct Env<'a> {
arena: &'a Bump,
symbols: MutMap<Symbol, ValueId>,
join_points: MutMap<roc_mono::ir::JoinPointId, morphic_lib::ContinuationId>,
type_names: MutSet<UnionLayout<'a>>,
}
impl<'a> Env<'a> {
fn new(arena: &'a Bump) -> Self {
fn new() -> Self {
Self {
arena,
symbols: Default::default(),
join_points: Default::default(),
type_names: Default::default(),
@ -535,14 +532,14 @@ fn stmt_spec<'a>(
interner: &mut STLayoutInterner<'a>,
env: &mut Env<'a>,
block: BlockId,
layout: &Layout<'a>,
layout: InLayout<'a>,
stmt: &Stmt<'a>,
) -> Result<ValueId> {
use Stmt::*;
match stmt {
Let(symbol, expr, expr_layout, mut continuation) => {
let value_id = expr_spec(builder, interner, env, block, expr_layout, expr)?;
let value_id = expr_spec(builder, interner, env, block, *expr_layout, expr)?;
env.symbols.insert(*symbol, value_id);
let mut queue = vec![symbol];
@ -550,7 +547,8 @@ fn stmt_spec<'a>(
loop {
match continuation {
Let(symbol, expr, expr_layout, c) => {
let value_id = expr_spec(builder, interner, env, block, expr_layout, expr)?;
let value_id =
expr_spec(builder, interner, env, block, *expr_layout, expr)?;
env.symbols.insert(*symbol, value_id);
queue.push(symbol);
@ -620,7 +618,7 @@ fn stmt_spec<'a>(
env,
builder,
interner,
&p.layout,
p.layout,
&WhenRecursive::Unreachable,
)?);
}
@ -717,13 +715,13 @@ fn build_recursive_tuple_type<'a>(
env: &mut Env<'a>,
builder: &mut impl TypeContext,
interner: &STLayoutInterner<'a>,
layouts: &[Layout<'a>],
layouts: &[InLayout<'a>],
when_recursive: &WhenRecursive,
) -> Result<TypeId> {
let mut field_types = Vec::new();
for field in layouts.iter() {
let type_id = layout_spec_help(env, builder, interner, field, when_recursive)?;
let type_id = layout_spec_help(env, builder, interner, *field, when_recursive)?;
field_types.push(type_id);
}
@ -734,13 +732,13 @@ fn build_tuple_type<'a>(
env: &mut Env<'a>,
builder: &mut impl TypeContext,
interner: &STLayoutInterner<'a>,
layouts: &[Layout<'a>],
layouts: &[InLayout<'a>],
when_recursive: &WhenRecursive,
) -> Result<TypeId> {
let mut field_types = Vec::new();
for field in layouts.iter() {
field_types.push(layout_spec(env, builder, interner, field, when_recursive)?);
field_types.push(layout_spec(env, builder, interner, *field, when_recursive)?);
}
builder.add_tuple_type(&field_types)
@ -777,7 +775,7 @@ fn call_spec<'a>(
interner: &mut STLayoutInterner<'a>,
env: &mut Env<'a>,
block: BlockId,
layout: &Layout<'a>,
layout: InLayout<'a>,
call: &Call<'a>,
) -> Result<ValueId> {
use CallType::*;
@ -795,7 +793,7 @@ fn call_spec<'a>(
let arg_value_id = build_tuple_value(builder, env, block, call.arguments)?;
let args_it = arg_layouts.iter().copied();
let captures_niche = name.niche();
let bytes = func_name_bytes_help(name.name(), args_it, captures_niche, ret_layout);
let bytes = func_name_bytes_help(name.name(), args_it, captures_niche, *ret_layout);
let name = FuncName(&bytes);
let module = MOD_APP;
builder.add_call(block, spec_var, module, name, arg_value_id)
@ -814,7 +812,7 @@ fn call_spec<'a>(
env,
builder,
interner,
ret_layout,
*ret_layout,
&WhenRecursive::Unreachable,
)?;
@ -851,7 +849,7 @@ fn call_spec<'a>(
passed_function.name.name(),
args_it,
captures_niche,
&passed_function.return_layout,
passed_function.return_layout,
);
let name = FuncName(&bytes);
let module = MOD_APP;
@ -891,18 +889,17 @@ fn call_spec<'a>(
env,
builder,
interner,
return_layout,
*return_layout,
&WhenRecursive::Unreachable,
)?;
let return_layout = interner.insert(*return_layout);
let state_layout = Layout::Builtin(Builtin::List(return_layout));
let state_layout =
interner.insert(Layout::Builtin(Builtin::List(*return_layout)));
let state_type = layout_spec(
env,
builder,
interner,
&state_layout,
state_layout,
&WhenRecursive::Unreachable,
)?;
@ -928,14 +925,14 @@ fn call_spec<'a>(
with_new_heap_cell(builder, block, bag)
};
let arg0_layout = interner.insert(argument_layouts[0]);
let arg0_layout = argument_layouts[0];
let state_layout = Layout::Builtin(Builtin::List(arg0_layout));
let state_layout = interner.insert(Layout::Builtin(Builtin::List(arg0_layout)));
let state_type = layout_spec(
env,
builder,
interner,
&state_layout,
state_layout,
&WhenRecursive::Unreachable,
)?;
let init_state = list;
@ -965,18 +962,17 @@ fn call_spec<'a>(
env,
builder,
interner,
return_layout,
*return_layout,
&WhenRecursive::Unreachable,
)?;
let return_layout = interner.insert(*return_layout);
let state_layout = Layout::Builtin(Builtin::List(return_layout));
let state_layout =
interner.insert(Layout::Builtin(Builtin::List(*return_layout)));
let state_type = layout_spec(
env,
builder,
interner,
&state_layout,
state_layout,
&WhenRecursive::Unreachable,
)?;
@ -1012,18 +1008,17 @@ fn call_spec<'a>(
env,
builder,
interner,
return_layout,
*return_layout,
&WhenRecursive::Unreachable,
)?;
let return_layout = interner.insert(*return_layout);
let state_layout = Layout::Builtin(Builtin::List(return_layout));
let state_layout =
interner.insert(Layout::Builtin(Builtin::List(*return_layout)));
let state_type = layout_spec(
env,
builder,
interner,
&state_layout,
state_layout,
&WhenRecursive::Unreachable,
)?;
@ -1065,18 +1060,17 @@ fn call_spec<'a>(
env,
builder,
interner,
return_layout,
*return_layout,
&WhenRecursive::Unreachable,
)?;
let return_layout = interner.insert(*return_layout);
let state_layout = Layout::Builtin(Builtin::List(return_layout));
let state_layout =
interner.insert(Layout::Builtin(Builtin::List(*return_layout)));
let state_type = layout_spec(
env,
builder,
interner,
&state_layout,
state_layout,
&WhenRecursive::Unreachable,
)?;
@ -1126,7 +1120,7 @@ fn lowlevel_spec<'a>(
interner: &STLayoutInterner<'a>,
env: &mut Env<'a>,
block: BlockId,
layout: &Layout<'a>,
layout: InLayout<'a>,
op: &LowLevel,
update_mode: roc_mono::ir::UpdateModeId,
arguments: &[Symbol],
@ -1206,21 +1200,21 @@ fn lowlevel_spec<'a>(
let new_list = with_new_heap_cell(builder, block, bag)?;
// depending on the types, the list or value will come first in the struct
let fields = match layout {
let fields = match interner.get(layout) {
Layout::Struct { field_layouts, .. } => field_layouts,
_ => unreachable!(),
};
match fields {
[Layout::Builtin(Builtin::List(_)), Layout::Builtin(Builtin::List(_))] => {
match (interner.get(fields[0]), interner.get(fields[1])) {
(Layout::Builtin(Builtin::List(_)), Layout::Builtin(Builtin::List(_))) => {
// field name is the tie breaker, list is first in
// { list : List a, value : a }
builder.add_make_tuple(block, &[new_list, old_value])
}
[Layout::Builtin(Builtin::List(_)), _] => {
(Layout::Builtin(Builtin::List(_)), _) => {
builder.add_make_tuple(block, &[new_list, old_value])
}
[_, Layout::Builtin(Builtin::List(_))] => {
(_, Layout::Builtin(Builtin::List(_))) => {
builder.add_make_tuple(block, &[old_value, new_list])
}
_ => unreachable!(),
@ -1239,14 +1233,13 @@ fn lowlevel_spec<'a>(
ListWithCapacity => {
// essentially an empty list, capacity is not relevant for morphic
match layout {
match interner.get(layout) {
Layout::Builtin(Builtin::List(element_layout)) => {
let element_layout = interner.get(*element_layout);
let type_id = layout_spec(
env,
builder,
interner,
&element_layout,
element_layout,
&WhenRecursive::Unreachable,
)?;
new_list(builder, block, type_id)
@ -1304,7 +1297,7 @@ fn recursive_tag_variant<'a>(
builder: &mut impl TypeContext,
interner: &STLayoutInterner<'a>,
union_layout: &UnionLayout,
fields: &[Layout<'a>],
fields: &[InLayout<'a>],
) -> Result<TypeId> {
let when_recursive = WhenRecursive::Loop(*union_layout);
@ -1413,7 +1406,7 @@ fn expr_spec<'a>(
interner: &mut STLayoutInterner<'a>,
env: &mut Env<'a>,
block: BlockId,
layout: &Layout<'a>,
layout: InLayout<'a>,
expr: &Expr<'a>,
) -> Result<ValueId> {
use Expr::*;
@ -1551,7 +1544,7 @@ fn expr_spec<'a>(
env,
builder,
interner,
elem_layout,
*elem_layout,
&WhenRecursive::Unreachable,
)?;
@ -1578,14 +1571,13 @@ fn expr_spec<'a>(
}
}
EmptyArray => match layout {
EmptyArray => match interner.get(layout) {
Layout::Builtin(Builtin::List(element_layout)) => {
let element_layout = interner.get(*element_layout);
let type_id = layout_spec(
env,
builder,
interner,
&element_layout,
element_layout,
&WhenRecursive::Unreachable,
)?;
new_list(builder, block, type_id)
@ -1598,12 +1590,12 @@ fn expr_spec<'a>(
} => {
let tag_value_id = env.symbols[symbol];
let union_layout = match layout {
let union_layout = match interner.get(layout) {
Layout::Union(ul) => ul,
_ => unreachable!(),
};
let type_name_bytes = recursive_tag_union_name_bytes(union_layout).as_bytes();
let type_name_bytes = recursive_tag_union_name_bytes(&union_layout).as_bytes();
let type_name = TypeName(&type_name_bytes);
// unwrap the named wrapper
@ -1651,7 +1643,7 @@ fn layout_spec<'a>(
env: &mut Env<'a>,
builder: &mut impl TypeContext,
interner: &STLayoutInterner<'a>,
layout: &Layout<'a>,
layout: InLayout<'a>,
when_recursive: &WhenRecursive,
) -> Result<TypeId> {
layout_spec_help(env, builder, interner, layout, when_recursive)
@ -1661,7 +1653,7 @@ fn non_recursive_variant_types<'a>(
env: &mut Env<'a>,
builder: &mut impl TypeContext,
interner: &STLayoutInterner<'a>,
tags: &[&[Layout<'a>]],
tags: &[&[InLayout<'a>]],
// If there is a recursive pointer latent within this layout, coming from a containing layout.
when_recursive: &WhenRecursive,
) -> Result<Vec<TypeId>> {
@ -1684,13 +1676,13 @@ fn layout_spec_help<'a>(
env: &mut Env<'a>,
builder: &mut impl TypeContext,
interner: &STLayoutInterner<'a>,
layout: &Layout<'a>,
layout: InLayout<'a>,
when_recursive: &WhenRecursive,
) -> Result<TypeId> {
use Layout::*;
match layout {
Builtin(builtin) => builtin_spec(env, builder, interner, builtin, when_recursive),
match interner.get(layout) {
Builtin(builtin) => builtin_spec(env, builder, interner, &builtin, when_recursive),
Struct { field_layouts, .. } => {
build_recursive_tuple_type(env, builder, interner, field_layouts, when_recursive)
}
@ -1698,7 +1690,7 @@ fn layout_spec_help<'a>(
env,
builder,
interner,
&lambda_set.runtime_representation(interner),
lambda_set.runtime_representation(),
when_recursive,
),
Union(union_layout) => {
@ -1718,10 +1710,10 @@ fn layout_spec_help<'a>(
| UnionLayout::NullableUnwrapped { .. }
| UnionLayout::NullableWrapped { .. }
| UnionLayout::NonNullableUnwrapped(_) => {
let type_name_bytes = recursive_tag_union_name_bytes(union_layout).as_bytes();
let type_name_bytes = recursive_tag_union_name_bytes(&union_layout).as_bytes();
let type_name = TypeName(&type_name_bytes);
env.type_names.insert(*union_layout);
env.type_names.insert(union_layout);
Ok(builder.add_named_type(MOD_APP, type_name))
}
@ -1729,9 +1721,8 @@ fn layout_spec_help<'a>(
}
Boxed(inner_layout) => {
let inner_layout = interner.get(*inner_layout);
let inner_type =
layout_spec_help(env, builder, interner, &inner_layout, when_recursive)?;
layout_spec_help(env, builder, interner, inner_layout, when_recursive)?;
let cell_type = builder.add_heap_cell_type();
builder.add_tuple_type(&[cell_type, inner_type])
@ -1770,9 +1761,8 @@ fn builtin_spec<'a>(
Decimal | Float(_) => builder.add_tuple_type(&[]),
Str => str_type(builder),
List(element_layout) => {
let element_layout = interner.get(*element_layout);
let element_type =
layout_spec_help(env, builder, interner, &element_layout, when_recursive)?;
layout_spec_help(env, builder, interner, *element_layout, when_recursive)?;
let cell = builder.add_heap_cell_type();
let bag = builder.add_bag_type(element_type)?;