mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
Merge branch 'trunk' into dict-more
This commit is contained in:
commit
fe98229aa3
19 changed files with 691 additions and 193 deletions
|
@ -6,14 +6,31 @@ use roc_collections::all::{MutMap, MutSet};
|
|||
use roc_module::low_level::LowLevel;
|
||||
use roc_module::symbol::Symbol;
|
||||
|
||||
fn should_borrow_layout(layout: &Layout) -> bool {
|
||||
match layout {
|
||||
Layout::Closure(_, _, _) => false,
|
||||
_ => layout.is_refcounted(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn infer_borrow<'a>(
|
||||
arena: &'a Bump,
|
||||
procs: &MutMap<(Symbol, Layout<'a>), Proc<'a>>,
|
||||
passed_by_pointer: &MutMap<(Symbol, Layout<'a>), Symbol>,
|
||||
) -> ParamMap<'a> {
|
||||
let mut param_map = ParamMap {
|
||||
items: MutMap::default(),
|
||||
};
|
||||
|
||||
for (key, other) in passed_by_pointer {
|
||||
if let Some(proc) = procs.get(key) {
|
||||
let mut proc: Proc = proc.clone();
|
||||
proc.name = *other;
|
||||
|
||||
param_map.visit_proc_always_owned(arena, &proc);
|
||||
}
|
||||
}
|
||||
|
||||
for proc in procs.values() {
|
||||
param_map.visit_proc(arena, proc);
|
||||
}
|
||||
|
@ -116,7 +133,22 @@ impl<'a> ParamMap<'a> {
|
|||
fn init_borrow_args(arena: &'a Bump, ps: &'a [(Layout<'a>, Symbol)]) -> &'a [Param<'a>] {
|
||||
Vec::from_iter_in(
|
||||
ps.iter().map(|(layout, symbol)| Param {
|
||||
borrow: layout.is_refcounted(),
|
||||
borrow: should_borrow_layout(layout),
|
||||
layout: layout.clone(),
|
||||
symbol: *symbol,
|
||||
}),
|
||||
arena,
|
||||
)
|
||||
.into_bump_slice()
|
||||
}
|
||||
|
||||
fn init_borrow_args_always_owned(
|
||||
arena: &'a Bump,
|
||||
ps: &'a [(Layout<'a>, Symbol)],
|
||||
) -> &'a [Param<'a>] {
|
||||
Vec::from_iter_in(
|
||||
ps.iter().map(|(layout, symbol)| Param {
|
||||
borrow: false,
|
||||
layout: layout.clone(),
|
||||
symbol: *symbol,
|
||||
}),
|
||||
|
@ -134,6 +166,15 @@ impl<'a> ParamMap<'a> {
|
|||
self.visit_stmt(arena, proc.name, &proc.body);
|
||||
}
|
||||
|
||||
fn visit_proc_always_owned(&mut self, arena: &'a Bump, proc: &Proc<'a>) {
|
||||
self.items.insert(
|
||||
Key::Declaration(proc.name),
|
||||
Self::init_borrow_args_always_owned(arena, proc.args),
|
||||
);
|
||||
|
||||
self.visit_stmt(arena, proc.name, &proc.body);
|
||||
}
|
||||
|
||||
fn visit_stmt(&mut self, arena: &'a Bump, _fnid: Symbol, stmt: &Stmt<'a>) {
|
||||
use Stmt::*;
|
||||
|
||||
|
|
|
@ -157,6 +157,24 @@ impl<'a, 'i> Env<'a, 'i> {
|
|||
}
|
||||
}
|
||||
|
||||
fn try_insert_struct_info(&mut self, symbol: Symbol, layout: &Layout<'a>) {
|
||||
use Layout::*;
|
||||
|
||||
match layout {
|
||||
Struct(fields) => {
|
||||
self.constructor_map.insert(symbol, 0);
|
||||
self.layout_map.insert(symbol, Layout::Struct(fields));
|
||||
}
|
||||
Closure(arguments, closure_layout, result) => {
|
||||
let fpointer = Layout::FunctionPointer(arguments, result);
|
||||
let fields = self.arena.alloc([fpointer, closure_layout.layout.clone()]);
|
||||
self.constructor_map.insert(symbol, 0);
|
||||
self.layout_map.insert(symbol, Layout::Struct(fields));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn insert_struct_info(&mut self, symbol: Symbol, fields: &'a [Layout<'a>]) {
|
||||
self.constructor_map.insert(symbol, 0);
|
||||
self.layout_map.insert(symbol, Layout::Struct(fields));
|
||||
|
@ -185,7 +203,7 @@ impl<'a, 'i> Env<'a, 'i> {
|
|||
}
|
||||
|
||||
fn layout_for_constructor<'a>(
|
||||
_arena: &'a Bump,
|
||||
arena: &'a Bump,
|
||||
layout: &Layout<'a>,
|
||||
constructor: u64,
|
||||
) -> ConstructorLayout<&'a [Layout<'a>]> {
|
||||
|
@ -227,7 +245,12 @@ fn layout_for_constructor<'a>(
|
|||
debug_assert_eq!(constructor, 0);
|
||||
HasFields(fields)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
Closure(arguments, closure_layout, result) => {
|
||||
let fpointer = Layout::FunctionPointer(arguments, result);
|
||||
let fields = arena.alloc([fpointer, closure_layout.layout.clone()]);
|
||||
HasFields(fields)
|
||||
}
|
||||
other => unreachable!("weird layout {:?}", other),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -253,11 +276,11 @@ fn work_for_constructor<'a>(
|
|||
match layout_for_constructor(env.arena, full_layout, constructor) {
|
||||
Unknown => Unknown,
|
||||
IsNull => IsNull,
|
||||
HasFields(cons_layout) => {
|
||||
HasFields(constructor_layout) => {
|
||||
// figure out if there is at least one aliased refcounted field. Only then
|
||||
// does it make sense to inline the decrement
|
||||
let at_least_one_aliased = (|| {
|
||||
for (i, field_layout) in cons_layout.iter().enumerate() {
|
||||
for (i, field_layout) in constructor_layout.iter().enumerate() {
|
||||
if field_layout.contains_refcounted()
|
||||
&& field_aliases.and_then(|map| map.get(&(i as u64))).is_some()
|
||||
{
|
||||
|
@ -269,7 +292,7 @@ fn work_for_constructor<'a>(
|
|||
|
||||
// for each field, if it has refcounted content, check if it has an alias
|
||||
// if so, use the alias, otherwise load the field.
|
||||
for (i, field_layout) in cons_layout.iter().enumerate() {
|
||||
for (i, field_layout) in constructor_layout.iter().enumerate() {
|
||||
if field_layout.contains_refcounted() {
|
||||
match field_aliases.and_then(|map| map.get(&(i as u64))) {
|
||||
Some(alias_symbol) => {
|
||||
|
@ -283,7 +306,7 @@ fn work_for_constructor<'a>(
|
|||
|
||||
let expr = Expr::AccessAtIndex {
|
||||
index: i as u64,
|
||||
field_layouts: cons_layout,
|
||||
field_layouts: constructor_layout,
|
||||
structure: *symbol,
|
||||
wrapped: Wrapped::MultiTagUnion,
|
||||
};
|
||||
|
@ -350,10 +373,11 @@ pub fn expand_and_cancel_proc<'a>(
|
|||
|
||||
introduced.push(*symbol);
|
||||
}
|
||||
Layout::Closure(_, closure_layout, _) => {
|
||||
if let Layout::Struct(fields) = closure_layout.layout {
|
||||
env.insert_struct_info(*symbol, fields);
|
||||
}
|
||||
Layout::Closure(arguments, closure_layout, result) => {
|
||||
let fpointer = Layout::FunctionPointer(arguments, result);
|
||||
let fields = env.arena.alloc([fpointer, closure_layout.layout.clone()]);
|
||||
env.insert_struct_info(*symbol, fields);
|
||||
introduced.push(*symbol);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -414,7 +438,10 @@ fn expand_and_cancel<'a>(env: &mut Env<'a, '_>, stmt: &'a Stmt<'a>) -> &'a Stmt<
|
|||
|
||||
match &expr {
|
||||
Expr::AccessAtIndex {
|
||||
structure, index, ..
|
||||
structure,
|
||||
index,
|
||||
field_layouts,
|
||||
..
|
||||
} => {
|
||||
let entry = env
|
||||
.alias_map
|
||||
|
@ -423,8 +450,14 @@ fn expand_and_cancel<'a>(env: &mut Env<'a, '_>, stmt: &'a Stmt<'a>) -> &'a Stmt<
|
|||
|
||||
entry.insert(*index, symbol);
|
||||
|
||||
// if the field is a struct, we know its constructor too!
|
||||
let field_layout = &field_layouts[*index as usize];
|
||||
env.try_insert_struct_info(symbol, field_layout);
|
||||
|
||||
new_cont = expand_and_cancel(env, cont);
|
||||
|
||||
env.remove_struct_info(symbol);
|
||||
|
||||
// make sure to remove the alias, so other branches don't use it by accident
|
||||
env.alias_map
|
||||
.get_mut(structure)
|
||||
|
|
|
@ -602,7 +602,10 @@ impl<'a> Context<'a> {
|
|||
consume: bool,
|
||||
) -> Self {
|
||||
// can this type be reference-counted at runtime?
|
||||
let reference = layout.contains_refcounted();
|
||||
let reference = match layout {
|
||||
Layout::Closure(_, closure, _) => closure.layout.contains_refcounted(),
|
||||
_ => layout.contains_refcounted(),
|
||||
};
|
||||
|
||||
let info = VarInfo {
|
||||
reference,
|
||||
|
|
|
@ -136,8 +136,15 @@ pub enum SelfRecursive {
|
|||
SelfRecursive(JoinPointId),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum Parens {
|
||||
NotNeeded,
|
||||
InTypeParam,
|
||||
InFunction,
|
||||
}
|
||||
|
||||
impl<'a> Proc<'a> {
|
||||
pub fn to_doc<'b, D, A>(&'b self, alloc: &'b D, _parens: bool) -> DocBuilder<'b, D, A>
|
||||
pub fn to_doc<'b, D, A>(&'b self, alloc: &'b D, _parens: Parens) -> DocBuilder<'b, D, A>
|
||||
where
|
||||
D: DocAllocator<'b, A>,
|
||||
D::Doc: Clone,
|
||||
|
@ -148,20 +155,36 @@ impl<'a> Proc<'a> {
|
|||
.iter()
|
||||
.map(|(_, symbol)| symbol_to_doc(alloc, *symbol));
|
||||
|
||||
alloc
|
||||
.text("procedure ")
|
||||
.append(symbol_to_doc(alloc, self.name))
|
||||
.append(" (")
|
||||
.append(alloc.intersperse(args_doc, ", "))
|
||||
.append("):")
|
||||
.append(alloc.hardline())
|
||||
.append(self.body.to_doc(alloc).indent(4))
|
||||
if PRETTY_PRINT_IR_SYMBOLS {
|
||||
alloc
|
||||
.text("procedure : ")
|
||||
.append(symbol_to_doc(alloc, self.name))
|
||||
.append(" ")
|
||||
.append(self.ret_layout.to_doc(alloc, Parens::NotNeeded))
|
||||
.append(alloc.hardline())
|
||||
.append(alloc.text("procedure = "))
|
||||
.append(symbol_to_doc(alloc, self.name))
|
||||
.append(" (")
|
||||
.append(alloc.intersperse(args_doc, ", "))
|
||||
.append("):")
|
||||
.append(alloc.hardline())
|
||||
.append(self.body.to_doc(alloc).indent(4))
|
||||
} else {
|
||||
alloc
|
||||
.text("procedure ")
|
||||
.append(symbol_to_doc(alloc, self.name))
|
||||
.append(" (")
|
||||
.append(alloc.intersperse(args_doc, ", "))
|
||||
.append("):")
|
||||
.append(alloc.hardline())
|
||||
.append(self.body.to_doc(alloc).indent(4))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_pretty(&self, width: usize) -> String {
|
||||
let allocator = BoxAllocator;
|
||||
let mut w = std::vec::Vec::new();
|
||||
self.to_doc::<_, ()>(&allocator, false)
|
||||
self.to_doc::<_, ()>(&allocator, Parens::NotNeeded)
|
||||
.1
|
||||
.render(width, &mut w)
|
||||
.unwrap();
|
||||
|
@ -172,8 +195,28 @@ impl<'a> Proc<'a> {
|
|||
pub fn insert_refcount_operations(
|
||||
arena: &'a Bump,
|
||||
procs: &mut MutMap<(Symbol, Layout<'a>), Proc<'a>>,
|
||||
_passed_by_pointer: &MutMap<(Symbol, Layout<'a>), Symbol>,
|
||||
) {
|
||||
let borrow_params = arena.alloc(crate::borrow::infer_borrow(arena, procs));
|
||||
// currently we ignore the passed-by-pointerness
|
||||
let passed_by_pointer = &Default::default();
|
||||
|
||||
let borrow_params =
|
||||
arena.alloc(crate::borrow::infer_borrow(arena, procs, passed_by_pointer));
|
||||
|
||||
for (key, other) in passed_by_pointer {
|
||||
if let Some(proc) = procs.get(key) {
|
||||
let mut proc: Proc = proc.clone();
|
||||
proc.name = *other;
|
||||
|
||||
let layout = key.1.clone();
|
||||
procs.insert((*other, layout), proc);
|
||||
} else {
|
||||
unreachable!(
|
||||
"we need a by-pointer version of {:?}, but its by-name version does not exist",
|
||||
key.0
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
for (_, proc) in procs.iter_mut() {
|
||||
crate::inc_dec::visit_proc(arena, borrow_params, proc);
|
||||
|
@ -255,6 +298,7 @@ pub struct Procs<'a> {
|
|||
pub runtime_errors: MutMap<Symbol, &'a str>,
|
||||
pub externals_others_need: ExternalSpecializations,
|
||||
pub externals_we_need: MutMap<ModuleId, ExternalSpecializations>,
|
||||
pub passed_by_pointer: MutMap<(Symbol, Layout<'a>), Symbol>,
|
||||
}
|
||||
|
||||
impl<'a> Default for Procs<'a> {
|
||||
|
@ -267,6 +311,7 @@ impl<'a> Default for Procs<'a> {
|
|||
runtime_errors: MutMap::default(),
|
||||
externals_we_need: MutMap::default(),
|
||||
externals_others_need: ExternalSpecializations::default(),
|
||||
passed_by_pointer: MutMap::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -311,10 +356,14 @@ impl<'a> Procs<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn get_specialized_procs_without_rc(
|
||||
self,
|
||||
arena: &'a Bump,
|
||||
) -> MutMap<(Symbol, Layout<'a>), Proc<'a>> {
|
||||
) -> (
|
||||
MutMap<(Symbol, Layout<'a>), Proc<'a>>,
|
||||
MutMap<(Symbol, Layout<'a>), Symbol>,
|
||||
) {
|
||||
let mut result = MutMap::with_capacity_and_hasher(self.specialized.len(), default_hasher());
|
||||
|
||||
for (key, in_prog_proc) in self.specialized.into_iter() {
|
||||
|
@ -337,7 +386,7 @@ impl<'a> Procs<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
result
|
||||
(result, self.passed_by_pointer)
|
||||
}
|
||||
|
||||
// TODO investigate make this an iterator?
|
||||
|
@ -366,7 +415,11 @@ impl<'a> Procs<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
let borrow_params = arena.alloc(crate::borrow::infer_borrow(arena, &result));
|
||||
let borrow_params = arena.alloc(crate::borrow::infer_borrow(
|
||||
arena,
|
||||
&result,
|
||||
&self.passed_by_pointer,
|
||||
));
|
||||
|
||||
for (_, proc) in result.iter_mut() {
|
||||
crate::inc_dec::visit_proc(arena, borrow_params, proc);
|
||||
|
@ -406,7 +459,11 @@ impl<'a> Procs<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
let borrow_params = arena.alloc(crate::borrow::infer_borrow(arena, &result));
|
||||
let borrow_params = arena.alloc(crate::borrow::infer_borrow(
|
||||
arena,
|
||||
&result,
|
||||
&self.passed_by_pointer,
|
||||
));
|
||||
|
||||
for (_, proc) in result.iter_mut() {
|
||||
crate::inc_dec::visit_proc(arena, borrow_params, proc);
|
||||
|
@ -2435,7 +2492,7 @@ fn specialize_naked_symbol<'a>(
|
|||
match hole {
|
||||
Stmt::Jump(_, _) => todo!("not sure what to do in this case yet"),
|
||||
_ => {
|
||||
let expr = Expr::FunctionPointer(symbol, layout.clone());
|
||||
let expr = call_by_pointer(env, procs, symbol, layout.clone());
|
||||
let new_symbol = env.unique_symbol();
|
||||
return Stmt::Let(
|
||||
new_symbol,
|
||||
|
@ -3523,7 +3580,7 @@ pub fn with_hole<'a>(
|
|||
// TODO should the let have layout Pointer?
|
||||
Stmt::Let(
|
||||
assigned,
|
||||
Expr::FunctionPointer(name, layout.clone()),
|
||||
call_by_pointer(env, procs, name, layout.clone()),
|
||||
layout,
|
||||
hole,
|
||||
)
|
||||
|
@ -3720,7 +3777,7 @@ pub fn with_hole<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
let expr = Expr::FunctionPointer(name, function_ptr_layout.clone());
|
||||
let expr = call_by_pointer(env, procs, name, function_ptr_layout.clone());
|
||||
|
||||
stmt = Stmt::Let(
|
||||
function_pointer,
|
||||
|
@ -3746,7 +3803,7 @@ pub fn with_hole<'a>(
|
|||
// TODO should the let have layout Pointer?
|
||||
Stmt::Let(
|
||||
assigned,
|
||||
Expr::FunctionPointer(name, layout.clone()),
|
||||
call_by_pointer(env, procs, name, layout.clone()),
|
||||
layout,
|
||||
hole,
|
||||
)
|
||||
|
@ -5327,7 +5384,7 @@ fn handle_variable_aliasing<'a>(
|
|||
.from_var(env.arena, variable, env.subs)
|
||||
.unwrap();
|
||||
|
||||
let expr = Expr::FunctionPointer(right, layout.clone());
|
||||
let expr = call_by_pointer(env, procs, right, layout.clone());
|
||||
Stmt::Let(left, expr, layout, env.arena.alloc(result))
|
||||
} else {
|
||||
substitute_in_exprs(env.arena, &mut result, left, right);
|
||||
|
@ -5375,7 +5432,7 @@ fn reuse_function_symbol<'a>(
|
|||
|
||||
// an imported symbol is always a function pointer:
|
||||
// either it's a function, or a top-level 0-argument thunk
|
||||
let expr = Expr::FunctionPointer(original, layout.clone());
|
||||
let expr = call_by_pointer(env, procs, original, layout.clone());
|
||||
return Stmt::Let(symbol, expr, layout, env.arena.alloc(result));
|
||||
}
|
||||
_ => {
|
||||
|
@ -5473,7 +5530,7 @@ fn reuse_function_symbol<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
let expr = Expr::FunctionPointer(original, function_ptr_layout.clone());
|
||||
let expr = call_by_pointer(env, procs, original, function_ptr_layout.clone());
|
||||
|
||||
stmt = Stmt::Let(
|
||||
function_pointer,
|
||||
|
@ -5495,7 +5552,7 @@ fn reuse_function_symbol<'a>(
|
|||
|
||||
Stmt::Let(
|
||||
symbol,
|
||||
Expr::FunctionPointer(original, layout.clone()),
|
||||
call_by_pointer(env, procs, original, layout.clone()),
|
||||
layout,
|
||||
env.arena.alloc(result),
|
||||
)
|
||||
|
@ -5572,6 +5629,22 @@ where
|
|||
result
|
||||
}
|
||||
|
||||
fn call_by_pointer<'a>(
|
||||
_env: &mut Env<'a, '_>,
|
||||
procs: &mut Procs<'a>,
|
||||
symbol: Symbol,
|
||||
layout: Layout<'a>,
|
||||
) -> Expr<'a> {
|
||||
// let other = env.unique_symbol();
|
||||
let other = symbol;
|
||||
|
||||
procs
|
||||
.passed_by_pointer
|
||||
.insert((symbol, layout.clone()), other);
|
||||
|
||||
Expr::FunctionPointer(other, layout)
|
||||
}
|
||||
|
||||
fn add_needed_external<'a>(
|
||||
procs: &mut Procs<'a>,
|
||||
env: &mut Env<'a, '_>,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::ir::Parens;
|
||||
use bumpalo::collections::Vec;
|
||||
use bumpalo::Bump;
|
||||
use roc_collections::all::{default_hasher, MutMap, MutSet};
|
||||
|
@ -6,6 +7,7 @@ use roc_module::symbol::{Interns, Symbol};
|
|||
use roc_types::subs::{Content, FlatType, Subs, Variable};
|
||||
use roc_types::types::RecordField;
|
||||
use std::collections::HashMap;
|
||||
use ven_pretty::{DocAllocator, DocBuilder};
|
||||
|
||||
pub const MAX_ENUM_SIZE: usize = (std::mem::size_of::<u8>() * 8) as usize;
|
||||
const GENERATE_NULLABLE: bool = true;
|
||||
|
@ -63,6 +65,34 @@ pub enum UnionLayout<'a> {
|
|||
},
|
||||
}
|
||||
|
||||
impl<'a> UnionLayout<'a> {
|
||||
pub fn to_doc<'b, D, A>(&'b self, alloc: &'b D, _parens: Parens) -> DocBuilder<'b, D, A>
|
||||
where
|
||||
D: DocAllocator<'b, A>,
|
||||
D::Doc: Clone,
|
||||
A: Clone,
|
||||
{
|
||||
use UnionLayout::*;
|
||||
|
||||
match self {
|
||||
NonRecursive(tags) => {
|
||||
let tags_doc = tags.iter().map(|fields| {
|
||||
alloc.text("C ").append(alloc.intersperse(
|
||||
fields.iter().map(|x| x.to_doc(alloc, Parens::InTypeParam)),
|
||||
", ",
|
||||
))
|
||||
});
|
||||
|
||||
alloc
|
||||
.text("[")
|
||||
.append(alloc.intersperse(tags_doc, ", "))
|
||||
.append(alloc.text("]"))
|
||||
}
|
||||
_ => alloc.text("TODO"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct ClosureLayout<'a> {
|
||||
/// the layout that this specific closure captures
|
||||
|
@ -654,6 +684,51 @@ impl<'a> Layout<'a> {
|
|||
FunctionPointer(_, _) | Pointer(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_doc<'b, D, A>(&'b self, alloc: &'b D, parens: Parens) -> DocBuilder<'b, D, A>
|
||||
where
|
||||
D: DocAllocator<'b, A>,
|
||||
D::Doc: Clone,
|
||||
A: Clone,
|
||||
{
|
||||
use Layout::*;
|
||||
|
||||
match self {
|
||||
Builtin(builtin) => builtin.to_doc(alloc, parens),
|
||||
PhantomEmptyStruct => alloc.text("{}"),
|
||||
Struct(fields) => {
|
||||
let fields_doc = fields.iter().map(|x| x.to_doc(alloc, parens));
|
||||
|
||||
alloc
|
||||
.text("{")
|
||||
.append(alloc.intersperse(fields_doc, ", "))
|
||||
.append(alloc.text("}"))
|
||||
}
|
||||
Union(union_layout) => union_layout.to_doc(alloc, parens),
|
||||
RecursivePointer => alloc.text("*self"),
|
||||
FunctionPointer(args, result) => {
|
||||
let args_doc = args.iter().map(|x| x.to_doc(alloc, Parens::InFunction));
|
||||
|
||||
alloc
|
||||
.intersperse(args_doc, ", ")
|
||||
.append(alloc.text(" -> "))
|
||||
.append(result.to_doc(alloc, Parens::InFunction))
|
||||
}
|
||||
Closure(args, closure_layout, result) => {
|
||||
let args_doc = args.iter().map(|x| x.to_doc(alloc, Parens::InFunction));
|
||||
|
||||
let bom = closure_layout.layout.to_doc(alloc, Parens::NotNeeded);
|
||||
|
||||
alloc
|
||||
.intersperse(args_doc, ", ")
|
||||
.append(alloc.text(" {| "))
|
||||
.append(bom)
|
||||
.append(" |} -> ")
|
||||
.append(result.to_doc(alloc, Parens::InFunction))
|
||||
}
|
||||
Pointer(_) => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Avoid recomputing Layout from Variable multiple times.
|
||||
|
@ -878,6 +953,47 @@ impl<'a> Builtin<'a> {
|
|||
Str | Dict(_, _) | Set(_) => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_doc<'b, D, A>(&'b self, alloc: &'b D, _parens: Parens) -> DocBuilder<'b, D, A>
|
||||
where
|
||||
D: DocAllocator<'b, A>,
|
||||
D::Doc: Clone,
|
||||
A: Clone,
|
||||
{
|
||||
use Builtin::*;
|
||||
|
||||
match self {
|
||||
Int128 => alloc.text("Int128"),
|
||||
Int64 => alloc.text("Int64"),
|
||||
Int32 => alloc.text("Int32"),
|
||||
Int16 => alloc.text("Int16"),
|
||||
Int8 => alloc.text("Int8"),
|
||||
Int1 => alloc.text("Int1"),
|
||||
Usize => alloc.text("Usize"),
|
||||
Float128 => alloc.text("Float128"),
|
||||
Float64 => alloc.text("Float64"),
|
||||
Float32 => alloc.text("Float32"),
|
||||
Float16 => alloc.text("Float16"),
|
||||
|
||||
EmptyStr => alloc.text("EmptyStr"),
|
||||
EmptyList => alloc.text("EmptyList"),
|
||||
EmptyDict => alloc.text("EmptyDict"),
|
||||
EmptySet => alloc.text("EmptySet"),
|
||||
|
||||
Str => alloc.text("Str"),
|
||||
List(_, layout) => alloc
|
||||
.text("List ")
|
||||
.append(layout.to_doc(alloc, Parens::InTypeParam)),
|
||||
Set(layout) => alloc
|
||||
.text("Set ")
|
||||
.append(layout.to_doc(alloc, Parens::InTypeParam)),
|
||||
Dict(key_layout, value_layout) => alloc
|
||||
.text("Dict ")
|
||||
.append(key_layout.to_doc(alloc, Parens::InTypeParam))
|
||||
.append(" ")
|
||||
.append(value_layout.to_doc(alloc, Parens::InTypeParam)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn layout_from_flat_type<'a>(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue