mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 07:14:46 +00:00
parent
4742847ba9
commit
6e555e428d
2 changed files with 48 additions and 20 deletions
|
@ -5,11 +5,11 @@ use std::cmp::{max_by_key, min_by_key};
|
||||||
use roc_builtins::bitcode::{FloatWidth, IntWidth};
|
use roc_builtins::bitcode::{FloatWidth, IntWidth};
|
||||||
use roc_collections::all::MutMap;
|
use roc_collections::all::MutMap;
|
||||||
use roc_module::called_via::CalledVia;
|
use roc_module::called_via::CalledVia;
|
||||||
use roc_module::ident::TagName;
|
use roc_module::ident::{Lowercase, TagName};
|
||||||
use roc_module::symbol::{Interns, ModuleId, Symbol};
|
use roc_module::symbol::{Interns, ModuleId, Symbol};
|
||||||
use roc_mono::ir::ProcLayout;
|
use roc_mono::ir::ProcLayout;
|
||||||
use roc_mono::layout::{
|
use roc_mono::layout::{
|
||||||
union_sorted_tags_help, Builtin, Layout, UnionLayout, UnionVariant, WrappedVariant,
|
union_sorted_tags_help, Builtin, Layout, LayoutCache, UnionLayout, UnionVariant, WrappedVariant,
|
||||||
};
|
};
|
||||||
use roc_parse::ast::{AssignedField, Collection, Expr, StrLiteral};
|
use roc_parse::ast::{AssignedField, Collection, Expr, StrLiteral};
|
||||||
use roc_region::all::{Loc, Region};
|
use roc_region::all::{Loc, Region};
|
||||||
|
@ -349,15 +349,11 @@ fn jit_to_ast_help<'a, A: ReplApp<'a>>(
|
||||||
Layout::Struct { field_layouts, .. } => {
|
Layout::Struct { field_layouts, .. } => {
|
||||||
let struct_addr_to_ast = |mem: &'a A::Memory, addr: usize| match content {
|
let struct_addr_to_ast = |mem: &'a A::Memory, addr: usize| match content {
|
||||||
Content::Structure(FlatType::Record(fields, _)) => {
|
Content::Structure(FlatType::Record(fields, _)) => {
|
||||||
Ok(struct_to_ast(env, mem, addr, field_layouts, *fields))
|
Ok(struct_to_ast(env, mem, addr, *fields))
|
||||||
|
}
|
||||||
|
Content::Structure(FlatType::EmptyRecord) => {
|
||||||
|
Ok(struct_to_ast(env, mem, addr, RecordFields::empty()))
|
||||||
}
|
}
|
||||||
Content::Structure(FlatType::EmptyRecord) => Ok(struct_to_ast(
|
|
||||||
env,
|
|
||||||
mem,
|
|
||||||
addr,
|
|
||||||
field_layouts,
|
|
||||||
RecordFields::empty(),
|
|
||||||
)),
|
|
||||||
Content::Structure(FlatType::TagUnion(tags, _)) => {
|
Content::Structure(FlatType::TagUnion(tags, _)) => {
|
||||||
debug_assert_eq!(tags.len(), 1);
|
debug_assert_eq!(tags.len(), 1);
|
||||||
|
|
||||||
|
@ -533,7 +529,7 @@ fn addr_to_ast<'a, M: ReplAppMemory>(
|
||||||
}
|
}
|
||||||
(_, Layout::Struct{field_layouts, ..}) => match content {
|
(_, Layout::Struct{field_layouts, ..}) => match content {
|
||||||
Content::Structure(FlatType::Record(fields, _)) => {
|
Content::Structure(FlatType::Record(fields, _)) => {
|
||||||
struct_to_ast(env, mem, addr, field_layouts, *fields)
|
struct_to_ast(env, mem, addr, *fields)
|
||||||
}
|
}
|
||||||
Content::Structure(FlatType::TagUnion(tags, _)) => {
|
Content::Structure(FlatType::TagUnion(tags, _)) => {
|
||||||
debug_assert_eq!(tags.len(), 1);
|
debug_assert_eq!(tags.len(), 1);
|
||||||
|
@ -546,7 +542,7 @@ fn addr_to_ast<'a, M: ReplAppMemory>(
|
||||||
single_tag_union_to_ast(env, mem, addr, field_layouts, tag_name, &[])
|
single_tag_union_to_ast(env, mem, addr, field_layouts, tag_name, &[])
|
||||||
}
|
}
|
||||||
Content::Structure(FlatType::EmptyRecord) => {
|
Content::Structure(FlatType::EmptyRecord) => {
|
||||||
struct_to_ast(env, mem, addr, &[], RecordFields::empty())
|
struct_to_ast(env, mem, addr, RecordFields::empty())
|
||||||
}
|
}
|
||||||
other => {
|
other => {
|
||||||
unreachable!(
|
unreachable!(
|
||||||
|
@ -856,30 +852,46 @@ fn struct_to_ast<'a, M: ReplAppMemory>(
|
||||||
env: &Env<'a, 'a>,
|
env: &Env<'a, 'a>,
|
||||||
mem: &'a M,
|
mem: &'a M,
|
||||||
addr: usize,
|
addr: usize,
|
||||||
field_layouts: &'a [Layout<'a>],
|
|
||||||
record_fields: RecordFields,
|
record_fields: RecordFields,
|
||||||
) -> Expr<'a> {
|
) -> Expr<'a> {
|
||||||
let arena = env.arena;
|
let arena = env.arena;
|
||||||
let subs = env.subs;
|
let subs = env.subs;
|
||||||
let mut output = Vec::with_capacity_in(field_layouts.len(), arena);
|
let mut output = Vec::with_capacity_in(record_fields.len(), arena);
|
||||||
|
|
||||||
let sorted_fields: Vec<_> = Vec::from_iter_in(
|
let sorted_fields: Vec<_> = Vec::from_iter_in(
|
||||||
record_fields.sorted_iterator(env.subs, Variable::EMPTY_RECORD),
|
record_fields.sorted_iterator(env.subs, Variable::EMPTY_RECORD),
|
||||||
env.arena,
|
arena,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let mut layout_cache = LayoutCache::new(env.target_info);
|
||||||
|
// We recalculate the layouts here because we will have compiled the record so that its fields
|
||||||
|
// are sorted by descending alignment, and then alphabetic, but the type of the record is
|
||||||
|
// always only sorted alphabetically. We want to arrange the rendered record in the order of
|
||||||
|
// the type.
|
||||||
|
let field_to_layout: MutMap<Lowercase, Layout> = sorted_fields
|
||||||
|
.iter()
|
||||||
|
.map(|(label, field)| {
|
||||||
|
let layout = layout_cache
|
||||||
|
.from_var(arena, *field.as_inner(), env.subs)
|
||||||
|
.unwrap();
|
||||||
|
(label.clone(), layout)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
if sorted_fields.len() == 1 {
|
if sorted_fields.len() == 1 {
|
||||||
// this is a 1-field wrapper record around another record or 1-tag tag union
|
// this is a 1-field wrapper record around another record or 1-tag tag union
|
||||||
let (label, field) = sorted_fields.into_iter().next().unwrap();
|
let (label, field) = sorted_fields.into_iter().next().unwrap();
|
||||||
|
|
||||||
let inner_content = env.subs.get_content_without_compacting(field.into_inner());
|
let inner_content = env.subs.get_content_without_compacting(field.into_inner());
|
||||||
|
debug_assert_eq!(field_to_layout.len(), 1);
|
||||||
|
let inner_layouts = arena.alloc([field_to_layout.into_values().next().unwrap()]);
|
||||||
|
|
||||||
let loc_expr = &*arena.alloc(Loc {
|
let loc_expr = &*arena.alloc(Loc {
|
||||||
value: addr_to_ast(
|
value: addr_to_ast(
|
||||||
env,
|
env,
|
||||||
mem,
|
mem,
|
||||||
addr,
|
addr,
|
||||||
&Layout::struct_no_name_order(field_layouts),
|
&Layout::struct_no_name_order(inner_layouts),
|
||||||
WhenRecursive::Unreachable,
|
WhenRecursive::Unreachable,
|
||||||
inner_content,
|
inner_content,
|
||||||
),
|
),
|
||||||
|
@ -895,19 +907,20 @@ fn struct_to_ast<'a, M: ReplAppMemory>(
|
||||||
region: Region::zero(),
|
region: Region::zero(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let output = env.arena.alloc([loc_field]);
|
let output = arena.alloc([loc_field]);
|
||||||
|
|
||||||
Expr::Record(Collection::with_items(output))
|
Expr::Record(Collection::with_items(output))
|
||||||
} else {
|
} else {
|
||||||
debug_assert_eq!(sorted_fields.len(), field_layouts.len());
|
debug_assert_eq!(sorted_fields.len(), field_to_layout.len());
|
||||||
|
|
||||||
// We'll advance this as we iterate through the fields
|
// We'll advance this as we iterate through the fields
|
||||||
let mut field_addr = addr;
|
let mut field_addr = addr;
|
||||||
|
|
||||||
for ((label, field), field_layout) in sorted_fields.into_iter().zip(field_layouts.iter()) {
|
for (label, field) in sorted_fields.into_iter() {
|
||||||
let var = field.into_inner();
|
let var = field.into_inner();
|
||||||
|
|
||||||
let content = subs.get_content_without_compacting(var);
|
let content = subs.get_content_without_compacting(var);
|
||||||
|
let field_layout = field_to_layout.get(&label).unwrap();
|
||||||
|
|
||||||
let loc_expr = &*arena.alloc(Loc {
|
let loc_expr = &*arena.alloc(Loc {
|
||||||
value: addr_to_ast(
|
value: addr_to_ast(
|
||||||
|
|
|
@ -840,7 +840,7 @@ fn function_in_list() {
|
||||||
fn function_in_record() {
|
fn function_in_record() {
|
||||||
expect_success(
|
expect_success(
|
||||||
r#"{ n: 1, adder: \x -> x + 1 }"#,
|
r#"{ n: 1, adder: \x -> x + 1 }"#,
|
||||||
r#"{ adder: <function>, n: <function> } : { adder : Num a -> Num a, n : Num * }"#,
|
r#"{ adder: <function>, n: 1 } : { adder : Num a -> Num a, n : Num * }"#,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1005,3 +1005,18 @@ fn tag_with_type_behind_alias() {
|
||||||
r#"A "value" : T"#,
|
r#"A "value" : T"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "wasm"))]
|
||||||
|
#[test]
|
||||||
|
fn issue_2588_record_with_function_and_nonfunction() {
|
||||||
|
expect_success(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
x = 1
|
||||||
|
f = \n -> n * 2
|
||||||
|
{ y: f x, f }
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
r#"{ f: <function>, y: 2 } : { f : Num a -> Num a, y : Num * }"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue