mirror of
https://github.com/roc-lang/roc.git
synced 2024-11-11 05:34:11 +03:00
Monomorphize optional fields
This commit is contained in:
parent
28a2f9656e
commit
2f50c0494b
@ -162,6 +162,7 @@ pub fn build(
|
||||
let mut layout_ids = LayoutIds::default();
|
||||
let mut procs = Procs::default();
|
||||
let mut mono_problems = std::vec::Vec::new();
|
||||
let mut layout_cache = LayoutCache::default();
|
||||
let mut mono_env = Env {
|
||||
arena,
|
||||
subs: &mut subs,
|
||||
@ -191,6 +192,7 @@ pub fn build(
|
||||
|
||||
procs.insert_named(
|
||||
&mut mono_env,
|
||||
&mut layout_cache,
|
||||
symbol,
|
||||
annotation,
|
||||
loc_args,
|
||||
@ -235,7 +237,6 @@ pub fn build(
|
||||
|
||||
Vec::with_capacity(num_headers)
|
||||
};
|
||||
let mut layout_cache = LayoutCache::default();
|
||||
let mut procs = roc_mono::expr::specialize_all(&mut mono_env, procs, &mut layout_cache);
|
||||
|
||||
assert_eq!(
|
||||
|
@ -1,8 +1,5 @@
|
||||
use crate::expr::Env;
|
||||
use crate::expr::Expr;
|
||||
use crate::expr::Pattern;
|
||||
use crate::layout::Builtin;
|
||||
use crate::layout::Layout;
|
||||
use crate::expr::{DestructType, Env, Expr, Pattern};
|
||||
use crate::layout::{Builtin, Layout};
|
||||
use crate::pattern::{Ctor, RenderAs, TagId, Union};
|
||||
use bumpalo::Bump;
|
||||
use roc_collections::all::{MutMap, MutSet};
|
||||
@ -393,10 +390,16 @@ fn test_at_path<'a>(selected_path: &Path, branch: Branch<'a>, all_tests: &mut Ve
|
||||
let mut arguments = std::vec::Vec::new();
|
||||
|
||||
for destruct in destructs {
|
||||
if let Some(guard) = &destruct.guard {
|
||||
arguments.push((guard.clone(), destruct.layout.clone()));
|
||||
} else {
|
||||
arguments.push((Pattern::Underscore, destruct.layout.clone()));
|
||||
match &destruct.typ {
|
||||
DestructType::Guard(guard) => {
|
||||
arguments.push((guard.clone(), destruct.layout.clone()));
|
||||
}
|
||||
DestructType::Required => {
|
||||
arguments.push((Pattern::Underscore, destruct.layout.clone()));
|
||||
}
|
||||
DestructType::Optional(_expr) => {
|
||||
todo!("test_at_type for optional destruct");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -524,10 +527,12 @@ fn to_relevant_branch_help<'a>(
|
||||
} => {
|
||||
debug_assert!(test_name == &TagName::Global("#Record".into()));
|
||||
let sub_positions = destructs.into_iter().enumerate().map(|(index, destruct)| {
|
||||
let pattern = if let Some(guard) = destruct.guard {
|
||||
guard.clone()
|
||||
} else {
|
||||
Pattern::Underscore
|
||||
let pattern = match destruct.typ {
|
||||
DestructType::Guard(guard) => guard.clone(),
|
||||
DestructType::Required => Pattern::Underscore,
|
||||
DestructType::Optional(_expr) => {
|
||||
todo!("TODO decision tree for optional field branch");
|
||||
}
|
||||
};
|
||||
|
||||
(
|
||||
|
@ -11,7 +11,6 @@ use roc_problem::can::RuntimeError;
|
||||
use roc_region::all::{Located, Region};
|
||||
use roc_types::subs::{Content, FlatType, Subs, Variable};
|
||||
use std::collections::HashMap;
|
||||
use std::hash::Hash;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct PartialProc<'a> {
|
||||
@ -56,13 +55,14 @@ impl<'a> Procs<'a> {
|
||||
pub fn insert_named(
|
||||
&mut self,
|
||||
env: &mut Env<'a, '_>,
|
||||
layout_cache: &mut LayoutCache<'a>,
|
||||
name: Symbol,
|
||||
annotation: Variable,
|
||||
loc_args: std::vec::Vec<(Variable, Located<roc_can::pattern::Pattern>)>,
|
||||
loc_body: Located<roc_can::expr::Expr>,
|
||||
ret_var: Variable,
|
||||
) {
|
||||
match patterns_to_when(env, loc_args, ret_var, loc_body) {
|
||||
match patterns_to_when(env, self, layout_cache, loc_args, ret_var, loc_body) {
|
||||
Ok((_, pattern_symbols, body)) => {
|
||||
// a named closure. Since these aren't specialized by the surrounding
|
||||
// context, we can't add pending specializations for them yet.
|
||||
@ -106,7 +106,7 @@ impl<'a> Procs<'a> {
|
||||
ret_var: Variable,
|
||||
layout_cache: &mut LayoutCache<'a>,
|
||||
) -> Result<Layout<'a>, RuntimeError> {
|
||||
match patterns_to_when(env, loc_args, ret_var, loc_body) {
|
||||
match patterns_to_when(env, self, layout_cache, loc_args, ret_var, loc_body) {
|
||||
Ok((pattern_vars, pattern_symbols, body)) => {
|
||||
// an anonymous closure. These will always be specialized already
|
||||
// by the surrounding context, so we can add pending specializations
|
||||
@ -418,6 +418,8 @@ fn num_argument_to_int_or_float(subs: &Subs, var: Variable) -> IntOrFloat {
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn patterns_to_when<'a>(
|
||||
env: &mut Env<'a, '_>,
|
||||
procs: &mut Procs<'a>,
|
||||
layout_cache: &mut LayoutCache<'a>,
|
||||
patterns: std::vec::Vec<(Variable, Located<roc_can::pattern::Pattern>)>,
|
||||
body_var: Variable,
|
||||
body: Located<roc_can::expr::Expr>,
|
||||
@ -438,7 +440,7 @@ fn patterns_to_when<'a>(
|
||||
// are only stores anyway, no branches.
|
||||
for (pattern_var, pattern) in patterns.into_iter() {
|
||||
let context = crate::pattern::Context::BadArg;
|
||||
let mono_pattern = from_can_pattern(env, &pattern.value);
|
||||
let mono_pattern = from_can_pattern(env, procs, layout_cache, &pattern.value);
|
||||
|
||||
match crate::pattern::check(
|
||||
pattern.region,
|
||||
@ -1023,11 +1025,14 @@ fn store_record_destruct<'a>(
|
||||
is_unwrapped: true,
|
||||
};
|
||||
|
||||
match &destruct.guard {
|
||||
None => {
|
||||
match &destruct.typ {
|
||||
DestructType::Required => {
|
||||
stored.push((destruct.symbol, destruct.layout.clone(), load));
|
||||
}
|
||||
Some(guard_pattern) => match &guard_pattern {
|
||||
DestructType::Optional(_expr) => {
|
||||
todo!("TODO monomorphize optional field destructure's default expr");
|
||||
}
|
||||
DestructType::Guard(guard_pattern) => match &guard_pattern {
|
||||
Identifier(symbol) => {
|
||||
stored.push((*symbol, destruct.layout.clone(), load));
|
||||
}
|
||||
@ -1097,7 +1102,15 @@ fn from_can_defs<'a>(
|
||||
|
||||
let (loc_body, ret_var) = *boxed_body;
|
||||
|
||||
procs.insert_named(env, *symbol, ann, loc_args, loc_body, ret_var);
|
||||
procs.insert_named(
|
||||
env,
|
||||
layout_cache,
|
||||
*symbol,
|
||||
ann,
|
||||
loc_args,
|
||||
loc_body,
|
||||
ret_var,
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
@ -1107,7 +1120,7 @@ fn from_can_defs<'a>(
|
||||
}
|
||||
|
||||
// If it wasn't specifically an Identifier & Closure, proceed as normal.
|
||||
let mono_pattern = from_can_pattern(env, &loc_pattern.value);
|
||||
let mono_pattern = from_can_pattern(env, procs, layout_cache, &loc_pattern.value);
|
||||
|
||||
let layout = layout_cache
|
||||
.from_var(env.arena, def.expr_var, env.subs, env.pointer_size)
|
||||
@ -1195,7 +1208,7 @@ fn from_can_when<'a>(
|
||||
|
||||
let loc_when_pattern = &first.patterns[0];
|
||||
|
||||
let mono_pattern = from_can_pattern(env, &loc_when_pattern.value);
|
||||
let mono_pattern = from_can_pattern(env, procs, layout_cache, &loc_when_pattern.value);
|
||||
|
||||
// record pattern matches can have 1 branch and typecheck, but may still not be exhaustive
|
||||
let guard = if first.guard.is_some() {
|
||||
@ -1259,7 +1272,7 @@ fn from_can_when<'a>(
|
||||
};
|
||||
|
||||
for loc_pattern in when_branch.patterns {
|
||||
let mono_pattern = from_can_pattern(env, &loc_pattern.value);
|
||||
let mono_pattern = from_can_pattern(env, procs, layout_cache, &loc_pattern.value);
|
||||
|
||||
loc_branches.push((
|
||||
Located::at(loc_pattern.region, mono_pattern.clone()),
|
||||
@ -1632,7 +1645,7 @@ fn specialize<'a>(
|
||||
|
||||
/// A pattern, including possible problems (e.g. shadowing) so that
|
||||
/// codegen can generate a runtime error if this pattern is reached.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Pattern<'a> {
|
||||
Identifier(Symbol),
|
||||
Underscore,
|
||||
@ -1666,12 +1679,19 @@ pub enum Pattern<'a> {
|
||||
UnsupportedPattern(Region),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct RecordDestruct<'a> {
|
||||
pub label: Lowercase,
|
||||
pub layout: Layout<'a>,
|
||||
pub symbol: Symbol,
|
||||
pub guard: Option<Pattern<'a>>,
|
||||
pub typ: DestructType<'a>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum DestructType<'a> {
|
||||
Required,
|
||||
Optional(Expr<'a>),
|
||||
Guard(Pattern<'a>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
@ -1683,6 +1703,8 @@ pub struct WhenBranch<'a> {
|
||||
|
||||
fn from_can_pattern<'a>(
|
||||
env: &mut Env<'a, '_>,
|
||||
procs: &mut Procs<'a>,
|
||||
layout_cache: &mut LayoutCache<'a>,
|
||||
can_pattern: &roc_can::pattern::Pattern,
|
||||
) -> Pattern<'a> {
|
||||
use roc_can::pattern::Pattern::*;
|
||||
@ -1786,7 +1808,10 @@ fn from_can_pattern<'a>(
|
||||
|
||||
let mut mono_args = Vec::with_capacity_in(arguments.len(), env.arena);
|
||||
for ((_, loc_pat), layout) in arguments.iter().zip(field_layouts.iter()) {
|
||||
mono_args.push((from_can_pattern(env, &loc_pat.value), layout.clone()));
|
||||
mono_args.push((
|
||||
from_can_pattern(env, procs, layout_cache, &loc_pat.value),
|
||||
layout.clone(),
|
||||
));
|
||||
}
|
||||
|
||||
let layout = Layout::Struct(field_layouts.into_bump_slice());
|
||||
@ -1825,7 +1850,10 @@ fn from_can_pattern<'a>(
|
||||
// disregard the tag discriminant layout
|
||||
let it = argument_layouts[1..].iter();
|
||||
for ((_, loc_pat), layout) in arguments.iter().zip(it) {
|
||||
mono_args.push((from_can_pattern(env, &loc_pat.value), layout.clone()));
|
||||
mono_args.push((
|
||||
from_can_pattern(env, procs, layout_cache, &loc_pat.value),
|
||||
layout.clone(),
|
||||
));
|
||||
}
|
||||
|
||||
let mut layouts: Vec<&'a [Layout<'a>]> =
|
||||
@ -1876,6 +1904,8 @@ fn from_can_pattern<'a>(
|
||||
|
||||
mono_destructs.push(from_can_record_destruct(
|
||||
env,
|
||||
procs,
|
||||
layout_cache,
|
||||
&destruct.value,
|
||||
field_layout.clone(),
|
||||
));
|
||||
@ -1885,7 +1915,7 @@ fn from_can_pattern<'a>(
|
||||
label: label.clone(),
|
||||
symbol: env.unique_symbol(),
|
||||
layout: field_layout.clone(),
|
||||
guard: Some(Pattern::Underscore),
|
||||
typ: DestructType::Guard(Pattern::Underscore),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
@ -1894,7 +1924,7 @@ fn from_can_pattern<'a>(
|
||||
label: label.clone(),
|
||||
symbol: env.unique_symbol(),
|
||||
layout: field_layout.clone(),
|
||||
guard: Some(Pattern::Underscore),
|
||||
typ: DestructType::Guard(Pattern::Underscore),
|
||||
});
|
||||
}
|
||||
field_layouts.push(field_layout);
|
||||
@ -1910,6 +1940,8 @@ fn from_can_pattern<'a>(
|
||||
|
||||
fn from_can_record_destruct<'a>(
|
||||
env: &mut Env<'a, '_>,
|
||||
procs: &mut Procs<'a>,
|
||||
layout_cache: &mut LayoutCache<'a>,
|
||||
can_rd: &roc_can::pattern::RecordDestruct,
|
||||
field_layout: Layout<'a>,
|
||||
) -> RecordDestruct<'a> {
|
||||
@ -1917,9 +1949,14 @@ fn from_can_record_destruct<'a>(
|
||||
label: can_rd.label.clone(),
|
||||
symbol: can_rd.symbol,
|
||||
layout: field_layout,
|
||||
guard: match &can_rd.guard {
|
||||
None => None,
|
||||
Some((_, loc_pattern)) => Some(from_can_pattern(env, &loc_pattern.value)),
|
||||
typ: match &can_rd.typ {
|
||||
roc_can::pattern::DestructType::Required => DestructType::Required,
|
||||
roc_can::pattern::DestructType::Optional(_, loc_expr) => {
|
||||
DestructType::Optional(from_can(env, loc_expr.value.clone(), procs, layout_cache))
|
||||
}
|
||||
roc_can::pattern::DestructType::Guard(_, loc_pattern) => DestructType::Guard(
|
||||
from_can_pattern(env, procs, layout_cache, &loc_pattern.value),
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -313,9 +313,10 @@ fn layout_from_flat_type<'a>(
|
||||
// Determine the layouts of the fields, maintaining sort order
|
||||
let mut layouts = Vec::with_capacity_in(sorted_fields.len(), arena);
|
||||
|
||||
for (_, field_var) in sorted_fields {
|
||||
for (_, field) in sorted_fields {
|
||||
use LayoutProblem::*;
|
||||
|
||||
let field_var = field.into_inner();
|
||||
let field_content = subs.get_without_compacting(field_var).content;
|
||||
|
||||
match Layout::new(arena, field_content, subs, pointer_size) {
|
||||
@ -372,7 +373,8 @@ pub fn sort_record_fields<'a>(
|
||||
// Sort the fields by label
|
||||
let mut sorted_fields = Vec::with_capacity_in(fields_map.len(), arena);
|
||||
|
||||
for (label, var) in fields_map {
|
||||
for (label, field) in fields_map {
|
||||
let var = field.into_inner();
|
||||
let layout = Layout::from_var(arena, var, subs, pointer_size)
|
||||
.expect("invalid layout from var");
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::expr::DestructType;
|
||||
use roc_collections::all::{Index, MutMap};
|
||||
use roc_module::ident::{Lowercase, TagName};
|
||||
use roc_region::all::{Located, Region};
|
||||
@ -66,9 +67,9 @@ fn simplify<'a>(pattern: &crate::expr::Pattern<'a>) -> Pattern {
|
||||
for destruct in destructures {
|
||||
field_names.push(destruct.label.clone());
|
||||
|
||||
match &destruct.guard {
|
||||
None => patterns.push(Anything),
|
||||
Some(guard) => patterns.push(simplify(guard)),
|
||||
match &destruct.typ {
|
||||
DestructType::Required | DestructType::Optional(_) => patterns.push(Anything),
|
||||
DestructType::Guard(guard) => patterns.push(simplify(guard)),
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user