From 9abbcfaafc2eb834d477c30ac2d686f5a25aa3fe Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Sat, 22 Jun 2024 19:07:18 -0500 Subject: [PATCH 01/22] Optimize literal list construction in LLVM backend Currently, list literals are always heap-allocated and their elements are stored by emitting a GEP and store for each item in the literal. This produces huge quantities of IR, causing compile times for e.g. programs with large literals or ingested files to blow up. Instead, if a list literal consists entirely of literal values, create a global section for the literal and return a pointer to it. --- crates/compiler/gen_llvm/src/llvm/build.rs | 149 ++++++--------------- crates/compiler/mono/src/ir/literal.rs | 11 ++ 2 files changed, 51 insertions(+), 109 deletions(-) diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index c941fff5936..437af4d2430 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -2915,130 +2915,61 @@ fn list_literal<'a, 'ctx>( let list_length = elems.len(); let list_length_intval = env.ptr_int().const_int(list_length as _, false); - // TODO re-enable, currently causes morphic segfaults because it tries to update - // constants in-place... - // if element_type.is_int_type() { - if false { + let is_all_constant = elems.iter().all(|e| e.is_literal()); + + if is_all_constant { let element_type = element_type.into_int_type(); - let element_width = layout_interner.stack_size(element_layout); - let size = list_length * element_width as usize; - let alignment = layout_interner - .alignment_bytes(element_layout) - .max(env.target.ptr_width() as u32); - let mut is_all_constant = true; - let zero_elements = - (env.target.ptr_width() as u8 as f64 / element_width as f64).ceil() as usize; + let element_width = layout_interner.stack_size(element_layout); - // runtime-evaluated elements - let mut runtime_evaluated_elements = Vec::with_capacity_in(list_length, env.arena); + let refcount_slot_bytes = layout_interner + .alignment_bytes(element_layout) + .max(env.target.ptr_width() as u32) as usize; - // set up a global that contains all the literal elements of the array - // any variables or expressions are represented as `undef` - let global = { - let mut global_elements = Vec::with_capacity_in(list_length, env.arena); + let refcount_slot_elements = + (refcount_slot_bytes as f64 / element_width as f64).ceil() as usize; - // Add zero bytes that represent the refcount - // - // - if all elements are const, then we store the whole list as a constant. - // It then needs a refcount before the first element. - // - but if the list is not all constants, then we will just copy the constant values, - // and we do not need that refcount at the start - // - // In the latter case, we won't store the zeros in the globals - // (we slice them off again below) - for _ in 0..zero_elements { - global_elements.push(element_type.const_zero()); - } + let data_bytes = list_length * element_width as usize; - // Copy the elements from the list literal into the array - for (index, element) in elems.iter().enumerate() { - match element { - ListLiteralElement::Literal(literal) => { - let val = build_exp_literal(env, layout_interner, element_layout, literal); - global_elements.push(val.into_int_value()); - } - ListLiteralElement::Symbol(symbol) => { - let val = scope.load_symbol(symbol); + assert!(refcount_slot_elements > 0); - // here we'd like to furthermore check for intval.is_const(). - // if all elements are const for LLVM, we could make the array a constant. - // BUT morphic does not know about this, and could allow us to modify that - // array in-place. That would cause a segfault. So, we'll have to find - // constants ourselves and cannot lean on LLVM here. + let mut bytes = Vec::with_capacity_in(refcount_slot_elements + data_bytes, env.arena); - is_all_constant = false; + // Fill the refcount slot with nulls + for _ in 0..(refcount_slot_elements) { + bytes.push(element_type.const_zero()); + } - runtime_evaluated_elements.push((index, val)); + // Copy the elements from the list literal into the array + for element in elems.iter() { + let literal = element.get_literal().expect("is_all_constant is true"); + let val = build_exp_literal(env, layout_interner, element_layout, &literal); + bytes.push(val.into_int_value()); + } - global_elements.push(element_type.get_undef()); - } - }; - } + let typ = element_type.array_type(bytes.len() as u32); + let global = env.module.add_global(typ, None, "roc__list_literal"); - let const_elements = if is_all_constant { - global_elements.into_bump_slice() - } else { - &global_elements[zero_elements..] - }; + global.set_initializer(&element_type.const_array(bytes.into_bump_slice())); + global.set_constant(true); + global.set_alignment(layout_interner.alignment_bytes(element_layout)); + global.set_unnamed_addr(true); + global.set_linkage(inkwell::module::Linkage::Private); - // use None for the address space (e.g. Const does not work) - let typ = element_type.array_type(const_elements.len() as u32); - let global = env.module.add_global(typ, None, "roc__list_literal"); + let with_rc_ptr = global.as_pointer_value(); - global.set_constant(true); - global.set_alignment(alignment); - global.set_unnamed_addr(true); - global.set_linkage(inkwell::module::Linkage::Private); - - global.set_initializer(&element_type.const_array(const_elements)); - global.as_pointer_value() + let data_ptr = unsafe { + env.builder.new_build_in_bounds_gep( + element_type, + with_rc_ptr, + &[env + .ptr_int() + .const_int(refcount_slot_elements as u64, false)], + "get_data_ptr", + ) }; - if is_all_constant { - // all elements are constants, so we can use the memory in the constants section directly - // here we make a pointer to the first actual element (skipping the 0 bytes that - // represent the refcount) - let zero = env.ptr_int().const_zero(); - let offset = env.ptr_int().const_int(zero_elements as _, false); - - let ptr = unsafe { - env.builder.new_build_in_bounds_gep( - element_type, - global, - &[zero, offset], - "first_element_pointer", - ) - }; - - super::build_list::store_list(env, ptr, list_length_intval).into() - } else { - // some of our elements are non-constant, so we must allocate space on the heap - let ptr = allocate_list(env, layout_interner, element_layout, list_length_intval); - - // then, copy the relevant segment from the constant section into the heap - env.builder - .build_memcpy( - ptr, - alignment, - global, - alignment, - env.ptr_int().const_int(size as _, false), - ) - .unwrap(); - - // then replace the `undef`s with the values that we evaluate at runtime - for (index, val) in runtime_evaluated_elements { - let index_val = ctx.i64_type().const_int(index as u64, false); - let elem_ptr = unsafe { - builder.new_build_in_bounds_gep(element_type, ptr, &[index_val], "index") - }; - - builder.new_build_store(elem_ptr, val); - } - - super::build_list::store_list(env, ptr, list_length_intval).into() - } + super::build_list::store_list(env, data_ptr, list_length_intval).into() } else { let ptr = allocate_list(env, layout_interner, element_layout, list_length_intval); diff --git a/crates/compiler/mono/src/ir/literal.rs b/crates/compiler/mono/src/ir/literal.rs index c7dcabf6825..36f68d87a1e 100644 --- a/crates/compiler/mono/src/ir/literal.rs +++ b/crates/compiler/mono/src/ir/literal.rs @@ -49,6 +49,17 @@ impl<'a> ListLiteralElement<'a> { _ => None, } } + + pub fn get_literal(&self) -> Option> { + match self { + Self::Literal(l) => Some(*l), + _ => None, + } + } + + pub fn is_literal(&self) -> bool { + matches!(self, Self::Literal(_)) + } } pub enum NumLiteral { From 462872551ed58145272adb3880998e25c95d7673 Mon Sep 17 00:00:00 2001 From: Brendan Hansknecht Date: Fri, 9 Aug 2024 19:07:01 -0700 Subject: [PATCH 02/22] fix up list literal constant loading --- crates/compiler/gen_llvm/src/llvm/build.rs | 27 +++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index 437af4d2430..9fed4a17dce 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -2915,9 +2915,13 @@ fn list_literal<'a, 'ctx>( let list_length = elems.len(); let list_length_intval = env.ptr_int().const_int(list_length as _, false); + // Anything that requires refcounting contains nested pointers. + // Nested pointers in globals will break the surgical linker. + // For now, block them from being constants. + let is_refcounted = layout_interner.contains_refcounted(element_layout); let is_all_constant = elems.iter().all(|e| e.is_literal()); - if is_all_constant { + if is_all_constant && !is_refcounted { let element_type = element_type.into_int_type(); let element_width = layout_interner.stack_size(element_layout); @@ -2947,18 +2951,26 @@ fn list_literal<'a, 'ctx>( bytes.push(val.into_int_value()); } + let alignment = layout_interner + .alignment_bytes(element_layout) + .max(env.target.ptr_width() as u32); + let typ = element_type.array_type(bytes.len() as u32); let global = env.module.add_global(typ, None, "roc__list_literal"); global.set_initializer(&element_type.const_array(bytes.into_bump_slice())); global.set_constant(true); - global.set_alignment(layout_interner.alignment_bytes(element_layout)); + global.set_alignment(alignment); global.set_unnamed_addr(true); global.set_linkage(inkwell::module::Linkage::Private); + // Currently, morphic will break if we use the global directly. + // It will attempt to update the global in place. + // This is invalid due to putting the global in the read only section. + // For now, eagerly copy the global into a new allocation with unique refcount. let with_rc_ptr = global.as_pointer_value(); - let data_ptr = unsafe { + let const_data_ptr = unsafe { env.builder.new_build_in_bounds_gep( element_type, with_rc_ptr, @@ -2969,6 +2981,15 @@ fn list_literal<'a, 'ctx>( ) }; + let data_ptr = allocate_list(env, layout_interner, element_layout, list_length_intval); + + let byte_size = env + .ptr_int() + .const_int(list_length as u64 * element_width as u64, false); + builder + .build_memcpy(data_ptr, alignment, const_data_ptr, alignment, byte_size) + .unwrap(); + super::build_list::store_list(env, data_ptr, list_length_intval).into() } else { let ptr = allocate_list(env, layout_interner, element_layout, list_length_intval); From 6b04318e27359404421cd99d8208b6ea6944ce07 Mon Sep 17 00:00:00 2001 From: Brendan Hansknecht Date: Fri, 9 Aug 2024 19:27:47 -0700 Subject: [PATCH 03/22] handle float types --- crates/compiler/gen_llvm/src/llvm/build.rs | 68 +++++++++++++++------- 1 file changed, 47 insertions(+), 21 deletions(-) diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index 9fed4a17dce..fa3c51a4582 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -2919,16 +2919,17 @@ fn list_literal<'a, 'ctx>( // Nested pointers in globals will break the surgical linker. // For now, block them from being constants. let is_refcounted = layout_interner.contains_refcounted(element_layout); + // NOTE: we should be able to create a constant of records, but these literals are only primitives. let is_all_constant = elems.iter().all(|e| e.is_literal()); if is_all_constant && !is_refcounted { - let element_type = element_type.into_int_type(); - let element_width = layout_interner.stack_size(element_layout); - let refcount_slot_bytes = layout_interner + let alignment = layout_interner .alignment_bytes(element_layout) - .max(env.target.ptr_width() as u32) as usize; + .max(env.target.ptr_width() as u32); + + let refcount_slot_bytes = alignment as usize; let refcount_slot_elements = (refcount_slot_bytes as f64 / element_width as f64).ceil() as usize; @@ -2937,28 +2938,53 @@ fn list_literal<'a, 'ctx>( assert!(refcount_slot_elements > 0); - let mut bytes = Vec::with_capacity_in(refcount_slot_elements + data_bytes, env.arena); + // There must be a generic way to do this, but types here are making me duplicate code. + let global = if element_type.is_int_type() { + let element_type = element_type.into_int_type(); + let mut bytes = Vec::with_capacity_in(refcount_slot_elements + data_bytes, env.arena); - // Fill the refcount slot with nulls - for _ in 0..(refcount_slot_elements) { - bytes.push(element_type.const_zero()); - } + // Fill the refcount slot with nulls + for _ in 0..(refcount_slot_elements) { + bytes.push(element_type.const_zero()); + } - // Copy the elements from the list literal into the array - for element in elems.iter() { - let literal = element.get_literal().expect("is_all_constant is true"); - let val = build_exp_literal(env, layout_interner, element_layout, &literal); - bytes.push(val.into_int_value()); - } + // Copy the elements from the list literal into the array + for element in elems.iter() { + let literal = element.get_literal().expect("is_all_constant is true"); + let val = build_exp_literal(env, layout_interner, element_layout, &literal); + bytes.push(val.into_int_value()); + } - let alignment = layout_interner - .alignment_bytes(element_layout) - .max(env.target.ptr_width() as u32); + let typ = element_type.array_type(bytes.len() as u32); + let global = env.module.add_global(typ, None, "roc__list_literal"); + + global.set_initializer(&element_type.const_array(bytes.into_bump_slice())); + global + } else if element_type.is_float_type() { + let element_type = element_type.into_float_type(); + let mut bytes = Vec::with_capacity_in(refcount_slot_elements + data_bytes, env.arena); - let typ = element_type.array_type(bytes.len() as u32); - let global = env.module.add_global(typ, None, "roc__list_literal"); + // Fill the refcount slot with nulls + for _ in 0..(refcount_slot_elements) { + bytes.push(element_type.const_zero()); + } + + // Copy the elements from the list literal into the array + for element in elems.iter() { + let literal = element.get_literal().expect("is_all_constant is true"); + let val = build_exp_literal(env, layout_interner, element_layout, &literal); + bytes.push(val.into_float_value()); + } + + let typ = element_type.array_type(bytes.len() as u32); + let global = env.module.add_global(typ, None, "roc__list_literal"); + + global.set_initializer(&element_type.const_array(bytes.into_bump_slice())); + global + } else { + internal_error!("unexpected element type: {:?}", element_type); + }; - global.set_initializer(&element_type.const_array(bytes.into_bump_slice())); global.set_constant(true); global.set_alignment(alignment); global.set_unnamed_addr(true); From 1d1b09520ca0a288f417c24a8d328d6682faaafc Mon Sep 17 00:00:00 2001 From: Luke Boswell Date: Fri, 6 Sep 2024 08:53:10 +1000 Subject: [PATCH 04/22] add heap as a new crate --- Cargo.lock | 23 +++- Cargo.toml | 1 + crates/roc_std_heap/Cargo.toml | 13 ++ crates/roc_std_heap/src/lib.rs | 239 +++++++++++++++++++++++++++++++++ 4 files changed, 273 insertions(+), 3 deletions(-) create mode 100644 crates/roc_std_heap/Cargo.toml create mode 100644 crates/roc_std_heap/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index f4299c78b84..1925825b62f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1399,9 +1399,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.149" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "libloading" @@ -1540,6 +1540,15 @@ dependencies = [ "libc", ] +[[package]] +name = "memmap2" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322" +dependencies = [ + "libc", +] + [[package]] name = "memoffset" version = "0.6.5" @@ -2705,7 +2714,7 @@ dependencies = [ "indoc", "libc", "mach_object", - "memmap2", + "memmap2 0.5.10", "object", "roc_collections", "roc_error_macros", @@ -3133,6 +3142,14 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "roc_std_heap" +version = "0.0.1" +dependencies = [ + "memmap2 0.9.4", + "roc_std", +] + [[package]] name = "roc_target" version = "0.0.1" diff --git a/Cargo.toml b/Cargo.toml index a02dc7b7de2..6dafb57e8e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,7 @@ members = [ "crates/wasm_module", "crates/wasm_interp", "crates/language_server", + "crates/roc_std_heap", ] exclude = [ diff --git a/crates/roc_std_heap/Cargo.toml b/crates/roc_std_heap/Cargo.toml new file mode 100644 index 00000000000..885643722c4 --- /dev/null +++ b/crates/roc_std_heap/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "roc_std_heap" +description = "Rust representations of a Roc threadsafe version of the refcounted heap that can avoid a wrapping Mutex and RefCell" + +authors = ["The Roc Contributors"] +edition = "2021" +license = "UPL-1.0" +repository = "https://github.com/roc-lang/roc" +version = "0.0.1" + +[dependencies] +roc_std = { path = "../roc_std" } +memmap2 = "=0.9.4" diff --git a/crates/roc_std_heap/src/lib.rs b/crates/roc_std_heap/src/lib.rs new file mode 100644 index 00000000000..eaab3065b8f --- /dev/null +++ b/crates/roc_std_heap/src/lib.rs @@ -0,0 +1,239 @@ +//! This heap module attempts to make simple single type heaps. +//! These are used for allocating and deallocating resources beyond the scope of roc. +//! +//! For example, roc can not free file resources. +//! Instead, they will be tracked and reference counted in a side heap. +//! When freed, the underlying resource can be released. +//! +//! To make checking resource types quick, all heaps allocate to a single mmap. +//! Then a simple range check on a pointer can confirm is a pointer is into a specific heap. + +use memmap2::MmapMut; +use roc_std::RocBox; +use std::{ + cell::UnsafeCell, + ffi::c_void, + io::{Error, ErrorKind, Result}, + marker::PhantomData, + mem, ptr, + sync::Mutex, +}; + +const REFCOUNT_ONE: usize = isize::MIN as usize; + +/// ThreadSafeRefcountedResourceHeap is a threadsafe version of the refcounted heap that can avoid a wrapping Mutex and RefCell. +/// This is very important for dealloc performance. +/// No lock is needed to check if a pointer is in range of the underlying mmap. +/// This leads to a solid perf bump over the naive lock everywhere solution. +/// Otherwise, alloc and dealloc, always use a mutex, but are much rarer to be called. +/// If perf becomes a problem once basic-cli has threading, we should consider sharding the heap by thread. +pub struct ThreadSafeRefcountedResourceHeap { + heap: UnsafeCell>, + guard: Mutex<()>, +} + +impl ThreadSafeRefcountedResourceHeap { + pub fn new(max_elements: usize) -> Result> { + RefcountedResourceHeap::new(max_elements).map(|heap| ThreadSafeRefcountedResourceHeap { + heap: UnsafeCell::new(heap), + guard: Mutex::new(()), + }) + } + + pub fn alloc_for(self: &Self, data: T) -> Result> { + let _g = self.guard.lock().unwrap(); + unsafe { &mut *self.heap.get() }.alloc_for(data) + } + + pub fn dealloc(self: &Self, ptr: *const U) { + let _g = self.guard.lock().unwrap(); + unsafe { &mut *self.heap.get() }.dealloc(ptr) + } + + // This is safe to call at any time with no lock! + pub fn in_range(self: &Self, ptr: *const U) -> bool { + unsafe { &*self.heap.get() }.in_range(ptr) + } + + pub fn box_to_resource<'a>(data: RocBox<()>) -> &'a mut T { + RefcountedResourceHeap::box_to_resource(data) + } +} + +unsafe impl Sync for ThreadSafeRefcountedResourceHeap {} +unsafe impl Send for ThreadSafeRefcountedResourceHeap {} + +#[repr(C)] +struct Refcounted(usize, T); + +/// HeapOfRefcounted is a wrapper around Heap for data that roc stores with a refcount. +/// It will return a pointer to right after the refcount (what a `Box {}` would expect in Roc). +pub struct RefcountedResourceHeap(Heap>); + +impl RefcountedResourceHeap { + pub fn new(max_elements: usize) -> Result> { + Heap::new(max_elements).map(|heap| RefcountedResourceHeap(heap)) + } + + pub fn alloc_for(self: &mut Self, data: T) -> Result> { + self.0.alloc().map(|alloc_ptr| { + unsafe { std::ptr::write(alloc_ptr, Refcounted(REFCOUNT_ONE, data)) }; + let box_ptr = alloc_ptr as usize + mem::size_of::(); + unsafe { std::mem::transmute(box_ptr) } + }) + } + + pub fn dealloc(self: &mut Self, ptr: *const U) { + self.0.dealloc(ptr as _); + } + + pub fn in_range(self: &Self, ptr: *const U) -> bool { + self.0.in_range(ptr as _) + } + + pub fn box_to_resource<'a>(data: RocBox<()>) -> &'a mut T { + let box_ptr: usize = unsafe { std::mem::transmute(data) }; + + let alloc_ptr = (box_ptr - mem::size_of::()) as *mut Refcounted; + let alloc: &mut Refcounted = unsafe { &mut *alloc_ptr }; + &mut alloc.1 + } +} + +/// The Heap is one mmap of data that can be interpreted multiple ways. +/// +/// It can be view as list of unions between `T` and `usize`. +/// In the case of a `T`, it is an allocated element. +/// In the case of a `usize`, it is part of the freed list. +/// The value of the `usize` is the next free node. +/// +/// Note: If we ever need better multithreaded performance, +/// we could shard the heap and lock individual shards. +pub struct Heap { + data: MmapMut, + elements: usize, + max_elements: usize, + free_list: *const c_void, + phantom: PhantomData, +} + +unsafe impl Send for Heap {} + +impl Heap { + pub fn new(max_elements: usize) -> Result> { + debug_assert!(max_elements > 0); + + let max_bytes = max_elements * Self::node_size(); + Ok(Self { + data: MmapMut::map_anon(max_bytes)?, + elements: 0, + max_elements, + free_list: ptr::null(), + phantom: PhantomData::default(), + }) + } + + pub fn alloc(self: &mut Self) -> Result<*mut T> { + if self.free_list != ptr::null() { + // Open slot on the free list. + let root = self.free_list as *const *const c_void; + let next = unsafe { *root }; + self.free_list = next; + + // Convert root into a `*mut T` for use. + return Ok(root as *mut T); + } + + // If has available memory allocate at end. + if self.elements < self.max_elements { + let offset = self.elements * Self::node_size(); + let elem_ptr = unsafe { self.data.as_mut_ptr().offset(offset as isize) }; + self.elements += 1; + return Ok(elem_ptr as *mut T); + } + + return Err(Error::from(ErrorKind::OutOfMemory)); + } + + pub fn dealloc(self: &mut Self, elem_ptr: *mut T) { + debug_assert!(self.in_range(elem_ptr)); + + // Just push the freed value to the start of the free list. + let old_root = self.free_list; + self.free_list = elem_ptr as *const c_void; + unsafe { *(self.free_list as *mut *const c_void) = old_root }; + + unsafe { + // Free the underlying resource. + std::ptr::drop_in_place(elem_ptr); + } + } + + pub fn in_range(self: &Self, elem_ptr: *mut T) -> bool { + let start = self.data.as_ptr(); + let offset = self.elements * Self::node_size(); + let end = unsafe { start.offset(offset as isize) }; + (start as usize) <= (elem_ptr as usize) && (elem_ptr as usize) < (end as usize) + } + + const fn node_size() -> usize { + let a = mem::size_of::(); + let b = mem::size_of::(); + if a > b { + a + } else { + b + } + } +} + +#[cfg(test)] +mod test { + use std::u128; + + use super::*; + + #[test] + fn alloc_to_limit() { + let limit = 4; + let mut heap = Heap::::new(limit).unwrap(); + let mut ptrs = vec![]; + loop { + match heap.alloc() { + Ok(ptr) => ptrs.push(ptr), + Err(_) => break, + } + } + + assert_eq!(ptrs.len(), limit); + for ptr in ptrs { + assert!(heap.in_range(ptr)); + } + } + + #[test] + fn reuse_freed_elems() { + let limit = 4; + let mut heap = Heap::::new(limit).unwrap(); + let a = heap.alloc().unwrap(); + let b = heap.alloc().unwrap(); + let c = heap.alloc().unwrap(); + let d = heap.alloc().unwrap(); + + heap.dealloc(c); + assert_eq!(c, heap.alloc().unwrap()); + + assert!(heap.alloc().is_err()); + + heap.dealloc(d); + heap.dealloc(a); + heap.dealloc(b); + + // These should be reused in reverse order. + assert_eq!(b, heap.alloc().unwrap()); + assert_eq!(a, heap.alloc().unwrap()); + assert_eq!(d, heap.alloc().unwrap()); + + assert!(heap.alloc().is_err()); + } +} From f21654a78ebd2a289e30dedac18546d63a24f129 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Geron?= Date: Wed, 11 Sep 2024 15:32:30 +1200 Subject: [PATCH 05/22] Add a test case for List.dropAt at an index located in the middle of the list --- crates/compiler/test_gen/src/gen_list.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/compiler/test_gen/src/gen_list.rs b/crates/compiler/test_gen/src/gen_list.rs index 401ddc5711a..4d2c42a070b 100644 --- a/crates/compiler/test_gen/src/gen_list.rs +++ b/crates/compiler/test_gen/src/gen_list.rs @@ -547,6 +547,11 @@ fn list_drop_at() { RocList::from_slice(&[2, 3]), RocList ); + assert_evals_to!( + "List.dropAt [1, 2, 3] 1", + RocList::from_slice(&[1, 3]), + RocList + ); assert_evals_to!( "List.dropAt [0, 0, 0] 3", RocList::from_slice(&[0, 0, 0]), From 515e2e3e3aa3a9e7b46186035b5f2ad9e2407734 Mon Sep 17 00:00:00 2001 From: Brendan Hansknecht Date: Tue, 17 Sep 2024 13:19:53 -0700 Subject: [PATCH 06/22] clippy --- crates/roc_std_heap/src/lib.rs | 64 +++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/crates/roc_std_heap/src/lib.rs b/crates/roc_std_heap/src/lib.rs index eaab3065b8f..018840071bd 100644 --- a/crates/roc_std_heap/src/lib.rs +++ b/crates/roc_std_heap/src/lib.rs @@ -40,18 +40,21 @@ impl ThreadSafeRefcountedResourceHeap { }) } - pub fn alloc_for(self: &Self, data: T) -> Result> { + pub fn alloc_for(&self, data: T) -> Result> { let _g = self.guard.lock().unwrap(); unsafe { &mut *self.heap.get() }.alloc_for(data) } - pub fn dealloc(self: &Self, ptr: *const U) { + /// # Safety + /// + /// This function will drop the pointed to data. It must be initialized. + pub unsafe fn dealloc(&self, ptr: *const U) { let _g = self.guard.lock().unwrap(); - unsafe { &mut *self.heap.get() }.dealloc(ptr) + (*self.heap.get()).dealloc(ptr) } // This is safe to call at any time with no lock! - pub fn in_range(self: &Self, ptr: *const U) -> bool { + pub fn in_range(&self, ptr: *const U) -> bool { unsafe { &*self.heap.get() }.in_range(ptr) } @@ -75,7 +78,7 @@ impl RefcountedResourceHeap { Heap::new(max_elements).map(|heap| RefcountedResourceHeap(heap)) } - pub fn alloc_for(self: &mut Self, data: T) -> Result> { + pub fn alloc_for(&mut self, data: T) -> Result> { self.0.alloc().map(|alloc_ptr| { unsafe { std::ptr::write(alloc_ptr, Refcounted(REFCOUNT_ONE, data)) }; let box_ptr = alloc_ptr as usize + mem::size_of::(); @@ -83,11 +86,14 @@ impl RefcountedResourceHeap { }) } - pub fn dealloc(self: &mut Self, ptr: *const U) { + /// # Safety + /// + /// This function will drop the pointed to data. It must be initialized. + pub unsafe fn dealloc(&mut self, ptr: *const U) { self.0.dealloc(ptr as _); } - pub fn in_range(self: &Self, ptr: *const U) -> bool { + pub fn in_range(&self, ptr: *const U) -> bool { self.0.in_range(ptr as _) } @@ -129,12 +135,12 @@ impl Heap { elements: 0, max_elements, free_list: ptr::null(), - phantom: PhantomData::default(), + phantom: PhantomData, }) } - pub fn alloc(self: &mut Self) -> Result<*mut T> { - if self.free_list != ptr::null() { + pub fn alloc(&mut self) -> Result<*mut T> { + if self.free_list.is_null() { // Open slot on the free list. let root = self.free_list as *const *const c_void; let next = unsafe { *root }; @@ -147,32 +153,33 @@ impl Heap { // If has available memory allocate at end. if self.elements < self.max_elements { let offset = self.elements * Self::node_size(); - let elem_ptr = unsafe { self.data.as_mut_ptr().offset(offset as isize) }; + let elem_ptr = unsafe { self.data.as_mut_ptr().add(offset) }; self.elements += 1; return Ok(elem_ptr as *mut T); } - return Err(Error::from(ErrorKind::OutOfMemory)); + Err(Error::from(ErrorKind::OutOfMemory)) } - pub fn dealloc(self: &mut Self, elem_ptr: *mut T) { + /// # Safety + /// + /// This function will drop the pointed to data. It must be initialized. + pub unsafe fn dealloc(&mut self, elem_ptr: *mut T) { debug_assert!(self.in_range(elem_ptr)); // Just push the freed value to the start of the free list. let old_root = self.free_list; self.free_list = elem_ptr as *const c_void; - unsafe { *(self.free_list as *mut *const c_void) = old_root }; + *(self.free_list as *mut *const c_void) = old_root; - unsafe { - // Free the underlying resource. - std::ptr::drop_in_place(elem_ptr); - } + // Free the underlying resource. + std::ptr::drop_in_place(elem_ptr); } - pub fn in_range(self: &Self, elem_ptr: *mut T) -> bool { + pub fn in_range(&self, elem_ptr: *mut T) -> bool { let start = self.data.as_ptr(); let offset = self.elements * Self::node_size(); - let end = unsafe { start.offset(offset as isize) }; + let end = unsafe { start.add(offset) }; (start as usize) <= (elem_ptr as usize) && (elem_ptr as usize) < (end as usize) } @@ -198,11 +205,8 @@ mod test { let limit = 4; let mut heap = Heap::::new(limit).unwrap(); let mut ptrs = vec![]; - loop { - match heap.alloc() { - Ok(ptr) => ptrs.push(ptr), - Err(_) => break, - } + while let Ok(ptr) = heap.alloc() { + ptrs.push(ptr); } assert_eq!(ptrs.len(), limit); @@ -220,14 +224,16 @@ mod test { let c = heap.alloc().unwrap(); let d = heap.alloc().unwrap(); - heap.dealloc(c); + unsafe { heap.dealloc(c) }; assert_eq!(c, heap.alloc().unwrap()); assert!(heap.alloc().is_err()); - heap.dealloc(d); - heap.dealloc(a); - heap.dealloc(b); + unsafe { + heap.dealloc(d); + heap.dealloc(a); + heap.dealloc(b); + } // These should be reused in reverse order. assert_eq!(b, heap.alloc().unwrap()); From dc538ef788c5c1068c33244f6a68f3208f010a57 Mon Sep 17 00:00:00 2001 From: Brendan Hansknecht Date: Tue, 17 Sep 2024 13:27:39 -0700 Subject: [PATCH 07/22] add function from basic-webserver impl --- crates/roc_std_heap/src/lib.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/crates/roc_std_heap/src/lib.rs b/crates/roc_std_heap/src/lib.rs index 018840071bd..19a4da65003 100644 --- a/crates/roc_std_heap/src/lib.rs +++ b/crates/roc_std_heap/src/lib.rs @@ -61,6 +61,15 @@ impl ThreadSafeRefcountedResourceHeap { pub fn box_to_resource<'a>(data: RocBox<()>) -> &'a mut T { RefcountedResourceHeap::box_to_resource(data) } + + pub fn box_to_refcount<'a>(data: &RocBox<()>) -> &'a mut usize { + RefcountedResourceHeap::::box_to_refcount(data) + } + + pub fn promote_all_to_constant(self: &Self) { + let _g = self.guard.lock().unwrap(); + unsafe { &mut *self.heap.get() }.promote_all_to_constant(); + } } unsafe impl Sync for ThreadSafeRefcountedResourceHeap {} @@ -104,6 +113,26 @@ impl RefcountedResourceHeap { let alloc: &mut Refcounted = unsafe { &mut *alloc_ptr }; &mut alloc.1 } + + pub fn box_to_refcount<'a>(data: &RocBox<()>) -> &'a mut usize { + let box_ptr: &usize = unsafe { std::mem::transmute(data) }; + + let rc_ptr = (*box_ptr - mem::size_of::()) as *mut usize; + unsafe { &mut *rc_ptr } + } + + /// Promotes all live references to constants. + /// Does this my walking all allocations and setting the refcount to zero (constant). + /// It will also end up walking freed elements, but their bytes are uninitialized and don't matter. + /// This is great for calling after an init function where all lived data is guarenteed to live until the server finishes running. + pub fn promote_all_to_constant(self: &mut Self) { + for i in 0..self.0.elements { + let offset = i * Heap::>::node_size(); + let elem_ptr = unsafe { self.0.data.as_mut_ptr().offset(offset as isize) }; + let rc_ptr = elem_ptr as *mut usize; + unsafe { *rc_ptr = 0 }; + } + } } /// The Heap is one mmap of data that can be interpreted multiple ways. From 8305affe2577bb8cdd584771436e68aef4f15020 Mon Sep 17 00:00:00 2001 From: Brendan Hansknecht Date: Tue, 17 Sep 2024 13:28:28 -0700 Subject: [PATCH 08/22] more clippy --- crates/roc_std_heap/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/roc_std_heap/src/lib.rs b/crates/roc_std_heap/src/lib.rs index 19a4da65003..a77d46b41c9 100644 --- a/crates/roc_std_heap/src/lib.rs +++ b/crates/roc_std_heap/src/lib.rs @@ -66,7 +66,7 @@ impl ThreadSafeRefcountedResourceHeap { RefcountedResourceHeap::::box_to_refcount(data) } - pub fn promote_all_to_constant(self: &Self) { + pub fn promote_all_to_constant(&self) { let _g = self.guard.lock().unwrap(); unsafe { &mut *self.heap.get() }.promote_all_to_constant(); } @@ -125,10 +125,10 @@ impl RefcountedResourceHeap { /// Does this my walking all allocations and setting the refcount to zero (constant). /// It will also end up walking freed elements, but their bytes are uninitialized and don't matter. /// This is great for calling after an init function where all lived data is guarenteed to live until the server finishes running. - pub fn promote_all_to_constant(self: &mut Self) { + pub fn promote_all_to_constant(&mut self) { for i in 0..self.0.elements { let offset = i * Heap::>::node_size(); - let elem_ptr = unsafe { self.0.data.as_mut_ptr().offset(offset as isize) }; + let elem_ptr = unsafe { self.0.data.as_mut_ptr().add(offset) }; let rc_ptr = elem_ptr as *mut usize; unsafe { *rc_ptr = 0 }; } From ad7be994ce4288393ee5096d1db7dfaf8aee8442 Mon Sep 17 00:00:00 2001 From: Brendan Hansknecht Date: Tue, 17 Sep 2024 13:33:33 -0700 Subject: [PATCH 09/22] minor cleanup --- crates/roc_std_heap/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/roc_std_heap/src/lib.rs b/crates/roc_std_heap/src/lib.rs index a77d46b41c9..9a9dc152cf5 100644 --- a/crates/roc_std_heap/src/lib.rs +++ b/crates/roc_std_heap/src/lib.rs @@ -20,6 +20,7 @@ use std::{ }; const REFCOUNT_ONE: usize = isize::MIN as usize; +const REFCOUNT_CONSTANT: usize = 0; /// ThreadSafeRefcountedResourceHeap is a threadsafe version of the refcounted heap that can avoid a wrapping Mutex and RefCell. /// This is very important for dealloc performance. @@ -130,7 +131,7 @@ impl RefcountedResourceHeap { let offset = i * Heap::>::node_size(); let elem_ptr = unsafe { self.0.data.as_mut_ptr().add(offset) }; let rc_ptr = elem_ptr as *mut usize; - unsafe { *rc_ptr = 0 }; + unsafe { *rc_ptr = REFCOUNT_CONSTANT }; } } } From 3e423ce41813322320060a02ab376f664efeabc3 Mon Sep 17 00:00:00 2001 From: Brendan Hansknecht Date: Tue, 17 Sep 2024 13:37:11 -0700 Subject: [PATCH 10/22] typo --- crates/roc_std_heap/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/roc_std_heap/src/lib.rs b/crates/roc_std_heap/src/lib.rs index 9a9dc152cf5..0dc8af1a0b5 100644 --- a/crates/roc_std_heap/src/lib.rs +++ b/crates/roc_std_heap/src/lib.rs @@ -125,7 +125,7 @@ impl RefcountedResourceHeap { /// Promotes all live references to constants. /// Does this my walking all allocations and setting the refcount to zero (constant). /// It will also end up walking freed elements, but their bytes are uninitialized and don't matter. - /// This is great for calling after an init function where all lived data is guarenteed to live until the server finishes running. + /// This is great for calling after an init function where all lived data is guaranteed to live until the server finishes running. pub fn promote_all_to_constant(&mut self) { for i in 0..self.0.elements { let offset = i * Heap::>::node_size(); From 7989ee763c307bd4f7031ab9eb1c22e8fac7d7dd Mon Sep 17 00:00:00 2001 From: Brendan Hansknecht Date: Tue, 17 Sep 2024 14:20:36 -0700 Subject: [PATCH 11/22] fix null check (accidentally inverted conditional) --- crates/roc_std_heap/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/roc_std_heap/src/lib.rs b/crates/roc_std_heap/src/lib.rs index 0dc8af1a0b5..1af5dcc8997 100644 --- a/crates/roc_std_heap/src/lib.rs +++ b/crates/roc_std_heap/src/lib.rs @@ -170,7 +170,7 @@ impl Heap { } pub fn alloc(&mut self) -> Result<*mut T> { - if self.free_list.is_null() { + if !self.free_list.is_null() { // Open slot on the free list. let root = self.free_list as *const *const c_void; let next = unsafe { *root }; From 033d87034c01e76c1a0798b301bd7b91816f6f4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Geron?= Date: Wed, 11 Sep 2024 15:32:30 +1200 Subject: [PATCH 12/22] Add a test case for List.dropAt at an index located in the middle of the list --- crates/compiler/test_gen/src/gen_list.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/compiler/test_gen/src/gen_list.rs b/crates/compiler/test_gen/src/gen_list.rs index 401ddc5711a..4d2c42a070b 100644 --- a/crates/compiler/test_gen/src/gen_list.rs +++ b/crates/compiler/test_gen/src/gen_list.rs @@ -547,6 +547,11 @@ fn list_drop_at() { RocList::from_slice(&[2, 3]), RocList ); + assert_evals_to!( + "List.dropAt [1, 2, 3] 1", + RocList::from_slice(&[1, 3]), + RocList + ); assert_evals_to!( "List.dropAt [0, 0, 0] 3", RocList::from_slice(&[0, 0, 0]), From c10b25cf6e8a69b4c95ce9eeeb2ce29cda6ec85f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Geron?= Date: Thu, 19 Sep 2024 10:43:05 +1200 Subject: [PATCH 13/22] Fixes #7065 in List.dropAt, author: @bhansconnect --- crates/compiler/builtins/bitcode/src/list.zig | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/crates/compiler/builtins/bitcode/src/list.zig b/crates/compiler/builtins/bitcode/src/list.zig index e89b39c5611..c95e6e8063e 100644 --- a/crates/compiler/builtins/bitcode/src/list.zig +++ b/crates/compiler/builtins/bitcode/src/list.zig @@ -618,6 +618,16 @@ pub fn listDropAt( ) callconv(.C) RocList { const size = list.len(); const size_u64 = @as(u64, @intCast(size)); + + // NOTE + // we need to return an empty list explicitly, + // because we rely on the pointer field being null if the list is empty + // which also requires duplicating the utils.decref call to spend the RC token + if (size <= 1) { + list.decref(alignment, element_width, elements_refcounted, dec); + return RocList.empty(); + } + // If droping the first or last element, return a seamless slice. // For simplicity, do this by calling listSublist. // In the future, we can test if it is faster to manually inline the important parts here. @@ -638,25 +648,16 @@ pub fn listDropAt( // were >= than `size`, and we know `size` fits in usize. const drop_index: usize = @intCast(drop_index_u64); - if (elements_refcounted) { - const element = source_ptr + drop_index * element_width; - dec(element); - } - - // NOTE - // we need to return an empty list explicitly, - // because we rely on the pointer field being null if the list is empty - // which also requires duplicating the utils.decref call to spend the RC token - if (size < 2) { - list.decref(alignment, element_width, elements_refcounted, dec); - return RocList.empty(); - } - if (list.isUnique()) { - var i = drop_index; - const copy_target = source_ptr; + if (elements_refcounted) { + const element = source_ptr + drop_index * element_width; + dec(element); + } + + const copy_target = source_ptr + (drop_index * element_width); const copy_source = copy_target + element_width; - std.mem.copyForwards(u8, copy_target[i..size], copy_source[i..size]); + const copy_size = (size - drop_index - 1) * element_width; + std.mem.copyForwards(u8, copy_target[0..copy_size], copy_source[0..copy_size]); var new_list = list; From a9594fa75dcf862fd49d2affc81de718fcc499b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Sep 2024 04:16:02 +0000 Subject: [PATCH 14/22] Bump serve-static and express in /crates/compiler/checkmate/www Bumps [serve-static](https://github.com/expressjs/serve-static) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together. Updates `serve-static` from 1.15.0 to 1.16.2 - [Release notes](https://github.com/expressjs/serve-static/releases) - [Changelog](https://github.com/expressjs/serve-static/blob/v1.16.2/HISTORY.md) - [Commits](https://github.com/expressjs/serve-static/compare/v1.15.0...v1.16.2) Updates `express` from 4.19.2 to 4.21.0 - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/4.21.0/History.md) - [Commits](https://github.com/expressjs/express/compare/4.19.2...4.21.0) --- updated-dependencies: - dependency-name: serve-static dependency-type: indirect - dependency-name: express dependency-type: indirect ... Signed-off-by: dependabot[bot] --- .../compiler/checkmate/www/package-lock.json | 237 +++++++++++++----- 1 file changed, 168 insertions(+), 69 deletions(-) diff --git a/crates/compiler/checkmate/www/package-lock.json b/crates/compiler/checkmate/www/package-lock.json index 0f9ae79b541..b933542cb82 100644 --- a/crates/compiler/checkmate/www/package-lock.json +++ b/crates/compiler/checkmate/www/package-lock.json @@ -5917,9 +5917,9 @@ "dev": true }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "dev": true, "dependencies": { "bytes": "3.1.2", @@ -5930,7 +5930,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -6091,13 +6091,19 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7249,6 +7255,23 @@ "node": ">= 10" } }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", @@ -7597,9 +7620,9 @@ } }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "dev": true, "engines": { "node": ">= 0.8" @@ -7704,6 +7727,27 @@ "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", "dev": true }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-module-lexer": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.0.tgz", @@ -8646,37 +8690,37 @@ } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", + "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", "dev": true, "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -8883,13 +8927,13 @@ } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dev": true, "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -9249,10 +9293,13 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/function.prototype.name": { "version": "1.1.5", @@ -9300,15 +9347,19 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -9590,12 +9641,12 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -9640,6 +9691,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -13153,10 +13216,13 @@ } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/merge-stream": { "version": "2.0.0", @@ -13538,10 +13604,13 @@ } }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", "dev": true, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -13889,9 +13958,9 @@ "dev": true }, "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", "dev": true }, "node_modules/path-type": { @@ -15501,12 +15570,12 @@ } }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dev": true, "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -16560,9 +16629,9 @@ "dev": true }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dev": true, "dependencies": { "debug": "2.6.9", @@ -16598,6 +16667,15 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -16692,20 +16770,37 @@ } }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dev": true, "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" } }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -16743,14 +16838,18 @@ } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" From 584a6c2bd27470e94700ea94c8b1d0a1770eae1c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Sep 2024 04:16:05 +0000 Subject: [PATCH 15/22] Bump body-parser and express in /crates/compiler/checkmate/www Bumps [body-parser](https://github.com/expressjs/body-parser) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together. Updates `body-parser` from 1.20.2 to 1.20.3 - [Release notes](https://github.com/expressjs/body-parser/releases) - [Changelog](https://github.com/expressjs/body-parser/blob/master/HISTORY.md) - [Commits](https://github.com/expressjs/body-parser/compare/1.20.2...1.20.3) Updates `express` from 4.19.2 to 4.21.0 - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/4.21.0/History.md) - [Commits](https://github.com/expressjs/express/compare/4.19.2...4.21.0) --- updated-dependencies: - dependency-name: body-parser dependency-type: indirect - dependency-name: express dependency-type: indirect ... Signed-off-by: dependabot[bot] --- .../compiler/checkmate/www/package-lock.json | 237 +++++++++++++----- 1 file changed, 168 insertions(+), 69 deletions(-) diff --git a/crates/compiler/checkmate/www/package-lock.json b/crates/compiler/checkmate/www/package-lock.json index 0f9ae79b541..b933542cb82 100644 --- a/crates/compiler/checkmate/www/package-lock.json +++ b/crates/compiler/checkmate/www/package-lock.json @@ -5917,9 +5917,9 @@ "dev": true }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "dev": true, "dependencies": { "bytes": "3.1.2", @@ -5930,7 +5930,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -6091,13 +6091,19 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7249,6 +7255,23 @@ "node": ">= 10" } }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", @@ -7597,9 +7620,9 @@ } }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "dev": true, "engines": { "node": ">= 0.8" @@ -7704,6 +7727,27 @@ "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", "dev": true }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-module-lexer": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.0.tgz", @@ -8646,37 +8690,37 @@ } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", + "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", "dev": true, "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -8883,13 +8927,13 @@ } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dev": true, "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -9249,10 +9293,13 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/function.prototype.name": { "version": "1.1.5", @@ -9300,15 +9347,19 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -9590,12 +9641,12 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -9640,6 +9691,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -13153,10 +13216,13 @@ } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/merge-stream": { "version": "2.0.0", @@ -13538,10 +13604,13 @@ } }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", "dev": true, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -13889,9 +13958,9 @@ "dev": true }, "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", "dev": true }, "node_modules/path-type": { @@ -15501,12 +15570,12 @@ } }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dev": true, "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -16560,9 +16629,9 @@ "dev": true }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dev": true, "dependencies": { "debug": "2.6.9", @@ -16598,6 +16667,15 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -16692,20 +16770,37 @@ } }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dev": true, "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" } }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -16743,14 +16838,18 @@ } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" From 9745e1931c1ae57166fa0fd6d12bc7a9273c862f Mon Sep 17 00:00:00 2001 From: Stuart Hinson Date: Thu, 19 Sep 2024 20:46:44 -0400 Subject: [PATCH 16/22] Dict.update alter fn is passed a Result --- crates/compiler/builtins/roc/Dict.roc | 24 +- crates/compiler/test_mono/generated/dict.txt | 34 +- .../generated/inspect_derived_dict.txt | 1178 ++++++++--------- 3 files changed, 618 insertions(+), 618 deletions(-) diff --git a/crates/compiler/builtins/roc/Dict.roc b/crates/compiler/builtins/roc/Dict.roc index 31c95b77643..ede2fd42c28 100644 --- a/crates/compiler/builtins/roc/Dict.roc +++ b/crates/compiler/builtins/roc/Dict.roc @@ -509,33 +509,33 @@ removeHelper = \buckets, bucketIndex, distAndFingerprint, data, key -> ## is missing. This is more efficient than doing both a `Dict.get` and then a ## `Dict.insert` call, and supports being piped. ## ```roc -## alterValue : [Present Bool, Missing] -> [Present Bool, Missing] +## alterValue : Result Bool [Missing] -> Result Bool [Missing] ## alterValue = \possibleValue -> ## when possibleValue is -## Missing -> Present Bool.false -## Present value -> if value then Missing else Present Bool.true +## Err -> Ok Bool.false +## Ok value -> if value then Err Missing else Ok Bool.true ## ## expect Dict.update (Dict.empty {}) "a" alterValue == Dict.single "a" Bool.false ## expect Dict.update (Dict.single "a" Bool.false) "a" alterValue == Dict.single "a" Bool.true ## expect Dict.update (Dict.single "a" Bool.true) "a" alterValue == Dict.empty {} ## ``` -update : Dict k v, k, ([Present v, Missing] -> [Present v, Missing]) -> Dict k v +update : Dict k v, k, (Result v [Missing] -> Result v [Missing]) -> Dict k v update = \@Dict { buckets, data, maxBucketCapacity, maxLoadFactor, shifts }, key, alter -> { bucketIndex, result } = find (@Dict { buckets, data, maxBucketCapacity, maxLoadFactor, shifts }) key when result is Ok value -> - when alter (Present value) is - Present newValue -> + when alter (Ok value) is + Ok newValue -> bucket = listGetUnsafe buckets bucketIndex newData = List.set data (Num.toU64 bucket.dataIndex) (key, newValue) @Dict { buckets, data: newData, maxBucketCapacity, maxLoadFactor, shifts } - Missing -> + Err Missing -> removeBucket (@Dict { buckets, data, maxBucketCapacity, maxLoadFactor, shifts }) bucketIndex Err KeyNotFound -> - when alter Missing is - Present newValue -> + when alter (Err Missing) is + Ok newValue -> if List.len data >= maxBucketCapacity then # Need to reallocate let regular insert handle that. insert (@Dict { buckets, data, maxBucketCapacity, maxLoadFactor, shifts }) key newValue @@ -556,7 +556,7 @@ update = \@Dict { buckets, data, maxBucketCapacity, maxLoadFactor, shifts }, key distAndFingerprint = incrementDistN baseDistAndFingerprint (Num.toU32 dist) insertHelper buckets data bucketIndex distAndFingerprint key newValue maxBucketCapacity maxLoadFactor shifts - Missing -> + Err Missing -> @Dict { buckets, data, maxBucketCapacity, maxLoadFactor, shifts } circularDist = \start, end, size -> @@ -1216,8 +1216,8 @@ expect List.walk badKeys (Dict.empty {}) \acc, k -> Dict.update acc k \val -> when val is - Present p -> Present (p |> Num.addWrap 1) - Missing -> Present 0 + Ok p -> Ok (p |> Num.addWrap 1) + Err Missing -> Ok 0 allInsertedCorrectly = List.walk badKeys Bool.true \acc, k -> diff --git a/crates/compiler/test_mono/generated/dict.txt b/crates/compiler/test_mono/generated/dict.txt index 4e06c0eeb56..3e3a4d569da 100644 --- a/crates/compiler/test_mono/generated/dict.txt +++ b/crates/compiler/test_mono/generated/dict.txt @@ -1,29 +1,29 @@ -procedure Dict.1 (Dict.730): - let Dict.739 : List {U32, U32} = Array []; - let Dict.740 : List {[], []} = Array []; - let Dict.741 : U64 = 0i64; +procedure Dict.1 (Dict.731): + let Dict.740 : List {U32, U32} = Array []; + let Dict.741 : List {[], []} = Array []; + let Dict.742 : U64 = 0i64; let Dict.51 : Float32 = CallByName Dict.51; let Dict.52 : U8 = CallByName Dict.52; - let Dict.738 : {List {U32, U32}, List {[], []}, U64, Float32, U8} = Struct {Dict.739, Dict.740, Dict.741, Dict.51, Dict.52}; - ret Dict.738; + let Dict.739 : {List {U32, U32}, List {[], []}, U64, Float32, U8} = Struct {Dict.740, Dict.741, Dict.742, Dict.51, Dict.52}; + ret Dict.739; -procedure Dict.4 (Dict.736): - let Dict.163 : List {[], []} = StructAtIndex 1 Dict.736; - let #Derived_gen.0 : List {U32, U32} = StructAtIndex 0 Dict.736; +procedure Dict.4 (Dict.737): + let Dict.163 : List {[], []} = StructAtIndex 1 Dict.737; + let #Derived_gen.0 : List {U32, U32} = StructAtIndex 0 Dict.737; dec #Derived_gen.0; - let Dict.737 : U64 = CallByName List.6 Dict.163; + let Dict.738 : U64 = CallByName List.6 Dict.163; dec Dict.163; - ret Dict.737; + ret Dict.738; procedure Dict.51 (): - let Dict.745 : Float32 = 0.8f64; - ret Dict.745; + let Dict.746 : Float32 = 0.8f64; + ret Dict.746; procedure Dict.52 (): - let Dict.743 : U8 = 64i64; - let Dict.744 : U8 = 3i64; - let Dict.742 : U8 = CallByName Num.75 Dict.743 Dict.744; - ret Dict.742; + let Dict.744 : U8 = 64i64; + let Dict.745 : U8 = 3i64; + let Dict.743 : U8 = CallByName Num.75 Dict.744 Dict.745; + ret Dict.743; procedure List.6 (#Attr.2): let List.625 : U64 = lowlevel ListLenU64 #Attr.2; diff --git a/crates/compiler/test_mono/generated/inspect_derived_dict.txt b/crates/compiler/test_mono/generated/inspect_derived_dict.txt index 80360493fa1..60ae196bdfc 100644 --- a/crates/compiler/test_mono/generated/inspect_derived_dict.txt +++ b/crates/compiler/test_mono/generated/inspect_derived_dict.txt @@ -34,705 +34,705 @@ procedure Bool.7 (Bool.19, Bool.20): let Bool.27 : Int1 = CallByName Bool.12 Bool.19 Bool.20; ret Bool.27; -procedure Dict.1 (Dict.730): - let Dict.892 : List {U32, U32} = Array []; - let Dict.893 : List {Str, I64} = Array []; - let Dict.894 : U64 = 0i64; +procedure Dict.1 (Dict.731): + let Dict.893 : List {U32, U32} = Array []; + let Dict.894 : List {Str, I64} = Array []; + let Dict.895 : U64 = 0i64; let Dict.51 : Float32 = CallByName Dict.51; let Dict.52 : U8 = CallByName Dict.52; - let Dict.891 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = Struct {Dict.892, Dict.893, Dict.894, Dict.51, Dict.52}; - ret Dict.891; + let Dict.892 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = Struct {Dict.893, Dict.894, Dict.895, Dict.51, Dict.52}; + ret Dict.892; -procedure Dict.10 (Dict.731, Dict.186, Dict.187): - let Dict.185 : List {Str, I64} = StructAtIndex 1 Dict.731; - let #Derived_gen.67 : List {U32, U32} = StructAtIndex 0 Dict.731; +procedure Dict.10 (Dict.732, Dict.186, Dict.187): + let Dict.185 : List {Str, I64} = StructAtIndex 1 Dict.732; + let #Derived_gen.67 : List {U32, U32} = StructAtIndex 0 Dict.732; dec #Derived_gen.67; - let Dict.1108 : {Str, Int1} = CallByName List.18 Dict.185 Dict.186 Dict.187; + let Dict.1109 : {Str, Int1} = CallByName List.18 Dict.185 Dict.186 Dict.187; dec Dict.185; - ret Dict.1108; - -procedure Dict.100 (Dict.544, Dict.545, Dict.546): - let Dict.1061 : U8 = CallByName Dict.22 Dict.544 Dict.545; - let Dict.547 : U64 = CallByName Num.133 Dict.1061; - let Dict.1060 : U8 = 1i64; - let Dict.1059 : U64 = CallByName Num.74 Dict.546 Dict.1060; - let Dict.1058 : U64 = CallByName Num.51 Dict.1059 Dict.545; - let Dict.1057 : U8 = CallByName Dict.22 Dict.544 Dict.1058; - let Dict.548 : U64 = CallByName Num.133 Dict.1057; - let Dict.1056 : U64 = 1i64; - let Dict.1055 : U64 = CallByName Num.75 Dict.546 Dict.1056; - let Dict.1054 : U64 = CallByName Num.51 Dict.1055 Dict.545; - let Dict.1053 : U8 = CallByName Dict.22 Dict.544 Dict.1054; - let Dict.549 : U64 = CallByName Num.133 Dict.1053; - let Dict.1052 : U8 = 16i64; - let Dict.1049 : U64 = CallByName Num.72 Dict.547 Dict.1052; - let Dict.1051 : U8 = 8i64; - let Dict.1050 : U64 = CallByName Num.72 Dict.548 Dict.1051; - let Dict.550 : U64 = CallByName Num.71 Dict.1049 Dict.1050; - let Dict.1048 : U64 = CallByName Num.71 Dict.550 Dict.549; - ret Dict.1048; + ret Dict.1109; + +procedure Dict.100 (Dict.545, Dict.546, Dict.547): + let Dict.1062 : U8 = CallByName Dict.22 Dict.545 Dict.546; + let Dict.548 : U64 = CallByName Num.133 Dict.1062; + let Dict.1061 : U8 = 1i64; + let Dict.1060 : U64 = CallByName Num.74 Dict.547 Dict.1061; + let Dict.1059 : U64 = CallByName Num.51 Dict.1060 Dict.546; + let Dict.1058 : U8 = CallByName Dict.22 Dict.545 Dict.1059; + let Dict.549 : U64 = CallByName Num.133 Dict.1058; + let Dict.1057 : U64 = 1i64; + let Dict.1056 : U64 = CallByName Num.75 Dict.547 Dict.1057; + let Dict.1055 : U64 = CallByName Num.51 Dict.1056 Dict.546; + let Dict.1054 : U8 = CallByName Dict.22 Dict.545 Dict.1055; + let Dict.550 : U64 = CallByName Num.133 Dict.1054; + let Dict.1053 : U8 = 16i64; + let Dict.1050 : U64 = CallByName Num.72 Dict.548 Dict.1053; + let Dict.1052 : U8 = 8i64; + let Dict.1051 : U64 = CallByName Num.72 Dict.549 Dict.1052; + let Dict.551 : U64 = CallByName Num.71 Dict.1050 Dict.1051; + let Dict.1049 : U64 = CallByName Num.71 Dict.551 Dict.550; + ret Dict.1049; procedure Dict.12 (Dict.158): - let Dict.890 : {} = Struct {}; - let Dict.738 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = CallByName Dict.1 Dict.890; - let Dict.739 : {} = Struct {}; - let Dict.737 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = CallByName List.18 Dict.158 Dict.738 Dict.739; - ret Dict.737; + let Dict.891 : {} = Struct {}; + let Dict.739 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = CallByName Dict.1 Dict.891; + let Dict.740 : {} = Struct {}; + let Dict.738 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = CallByName List.18 Dict.158 Dict.739 Dict.740; + ret Dict.738; procedure Dict.127 (Dict.128, Dict.126): - let Dict.1105 : {} = Struct {}; let Dict.1106 : {} = Struct {}; let Dict.1107 : {} = Struct {}; - let Dict.1104 : {{List {U32, U32}, List {Str, I64}, U64, Float32, U8}, {}, {}, {}} = CallByName Inspect.42 Dict.126 Dict.1105 Dict.1106 Dict.1107; - let Dict.1103 : Str = CallByName Inspect.31 Dict.1104 Dict.128; - ret Dict.1103; - -procedure Dict.159 (Dict.160, Dict.740): - let Dict.161 : Str = StructAtIndex 0 Dict.740; - let Dict.162 : I64 = StructAtIndex 1 Dict.740; - let Dict.741 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = CallByName Dict.8 Dict.160 Dict.161 Dict.162; - ret Dict.741; - -procedure Dict.188 (Dict.189, Dict.1110, Dict.187): - let Dict.190 : Str = StructAtIndex 0 Dict.1110; - let Dict.191 : I64 = StructAtIndex 1 Dict.1110; - let Dict.1112 : {Str, Int1} = CallByName Inspect.191 Dict.189 Dict.190 Dict.191 Dict.187; - ret Dict.1112; - -procedure Dict.20 (Dict.727): - let Dict.155 : U64 = StructAtIndex 2 Dict.727; - let #Derived_gen.70 : List {U32, U32} = StructAtIndex 0 Dict.727; + let Dict.1108 : {} = Struct {}; + let Dict.1105 : {{List {U32, U32}, List {Str, I64}, U64, Float32, U8}, {}, {}, {}} = CallByName Inspect.42 Dict.126 Dict.1106 Dict.1107 Dict.1108; + let Dict.1104 : Str = CallByName Inspect.31 Dict.1105 Dict.128; + ret Dict.1104; + +procedure Dict.159 (Dict.160, Dict.741): + let Dict.161 : Str = StructAtIndex 0 Dict.741; + let Dict.162 : I64 = StructAtIndex 1 Dict.741; + let Dict.742 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = CallByName Dict.8 Dict.160 Dict.161 Dict.162; + ret Dict.742; + +procedure Dict.188 (Dict.189, Dict.1111, Dict.187): + let Dict.190 : Str = StructAtIndex 0 Dict.1111; + let Dict.191 : I64 = StructAtIndex 1 Dict.1111; + let Dict.1113 : {Str, Int1} = CallByName Inspect.191 Dict.189 Dict.190 Dict.191 Dict.187; + ret Dict.1113; + +procedure Dict.20 (Dict.728): + let Dict.155 : U64 = StructAtIndex 2 Dict.728; + let #Derived_gen.70 : List {U32, U32} = StructAtIndex 0 Dict.728; dec #Derived_gen.70; - let #Derived_gen.69 : List {Str, I64} = StructAtIndex 1 Dict.727; + let #Derived_gen.69 : List {Str, I64} = StructAtIndex 1 Dict.728; dec #Derived_gen.69; ret Dict.155; procedure Dict.22 (#Attr.2, #Attr.3): - let Dict.772 : {U32, U32} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret Dict.772; + let Dict.773 : {U32, U32} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret Dict.773; procedure Dict.22 (#Attr.2, #Attr.3): - let Dict.788 : {Str, I64} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret Dict.788; + let Dict.789 : {Str, I64} = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret Dict.789; procedure Dict.22 (#Attr.2, #Attr.3): - let Dict.951 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; - ret Dict.951; + let Dict.952 : U8 = lowlevel ListGetUnsafe #Attr.2 #Attr.3; + ret Dict.952; procedure Dict.23 (#Attr.2): - let Dict.824 : U64 = lowlevel DictPseudoSeed #Attr.2; - ret Dict.824; + let Dict.825 : U64 = lowlevel DictPseudoSeed #Attr.2; + ret Dict.825; -procedure Dict.4 (Dict.736): - let Dict.163 : List {Str, I64} = StructAtIndex 1 Dict.736; - let #Derived_gen.66 : List {U32, U32} = StructAtIndex 0 Dict.736; +procedure Dict.4 (Dict.737): + let Dict.163 : List {Str, I64} = StructAtIndex 1 Dict.737; + let #Derived_gen.66 : List {U32, U32} = StructAtIndex 0 Dict.737; dec #Derived_gen.66; - let Dict.889 : U64 = CallByName List.6 Dict.163; + let Dict.890 : U64 = CallByName List.6 Dict.163; dec Dict.163; - ret Dict.889; - -procedure Dict.405 (Dict.406, Dict.847, Dict.408, Dict.404): - let Dict.407 : Str = StructAtIndex 0 Dict.847; - let Dict.852 : {U64, U32} = CallByName Dict.72 Dict.406 Dict.407 Dict.404; - let Dict.409 : U64 = StructAtIndex 0 Dict.852; - let Dict.410 : U32 = StructAtIndex 1 Dict.852; - let Dict.851 : U32 = CallByName Num.131 Dict.408; - let Dict.850 : {U32, U32} = Struct {Dict.851, Dict.410}; - let Dict.849 : List {U32, U32} = CallByName Dict.74 Dict.406 Dict.850 Dict.409; - ret Dict.849; + ret Dict.890; + +procedure Dict.406 (Dict.407, Dict.848, Dict.409, Dict.405): + let Dict.408 : Str = StructAtIndex 0 Dict.848; + let Dict.853 : {U64, U32} = CallByName Dict.72 Dict.407 Dict.408 Dict.405; + let Dict.410 : U64 = StructAtIndex 0 Dict.853; + let Dict.411 : U32 = StructAtIndex 1 Dict.853; + let Dict.852 : U32 = CallByName Num.131 Dict.409; + let Dict.851 : {U32, U32} = Struct {Dict.852, Dict.411}; + let Dict.850 : List {U32, U32} = CallByName Dict.74 Dict.407 Dict.851 Dict.410; + ret Dict.850; procedure Dict.43 (Dict.126): - let Dict.1100 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = CallByName Inspect.30 Dict.126; - ret Dict.1100; + let Dict.1101 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = CallByName Inspect.30 Dict.126; + ret Dict.1101; procedure Dict.45 (#Derived_gen.42, #Derived_gen.43, #Derived_gen.44, #Derived_gen.45, #Derived_gen.46, #Derived_gen.47, #Derived_gen.48, #Derived_gen.49, #Derived_gen.50): - joinpoint Dict.743 Dict.228 Dict.229 Dict.230 Dict.231 Dict.232 Dict.233 Dict.234 Dict.235 Dict.236: + joinpoint Dict.744 Dict.228 Dict.229 Dict.230 Dict.231 Dict.232 Dict.233 Dict.234 Dict.235 Dict.236: let Dict.237 : {U32, U32} = CallByName Dict.22 Dict.228 Dict.230; - let Dict.790 : U32 = StructAtIndex 1 Dict.237; - let Dict.778 : Int1 = CallByName Bool.11 Dict.231 Dict.790; - if Dict.778 then - let Dict.789 : U32 = StructAtIndex 0 Dict.237; - let Dict.787 : U64 = CallByName Num.133 Dict.789; - let Dict.786 : {Str, I64} = CallByName Dict.22 Dict.229 Dict.787; - let Dict.238 : Str = StructAtIndex 0 Dict.786; - let Dict.781 : Int1 = CallByName Bool.11 Dict.238 Dict.232; - if Dict.781 then - let Dict.785 : U32 = StructAtIndex 0 Dict.237; - let Dict.783 : U64 = CallByName Num.133 Dict.785; - let Dict.784 : {Str, I64} = Struct {Dict.232, Dict.233}; - let Dict.239 : List {Str, I64} = CallByName List.3 Dict.229 Dict.783 Dict.784; - let Dict.782 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = Struct {Dict.228, Dict.239, Dict.234, Dict.235, Dict.236}; - ret Dict.782; + let Dict.791 : U32 = StructAtIndex 1 Dict.237; + let Dict.779 : Int1 = CallByName Bool.11 Dict.231 Dict.791; + if Dict.779 then + let Dict.790 : U32 = StructAtIndex 0 Dict.237; + let Dict.788 : U64 = CallByName Num.133 Dict.790; + let Dict.787 : {Str, I64} = CallByName Dict.22 Dict.229 Dict.788; + let Dict.238 : Str = StructAtIndex 0 Dict.787; + let Dict.782 : Int1 = CallByName Bool.11 Dict.238 Dict.232; + if Dict.782 then + let Dict.786 : U32 = StructAtIndex 0 Dict.237; + let Dict.784 : U64 = CallByName Num.133 Dict.786; + let Dict.785 : {Str, I64} = Struct {Dict.232, Dict.233}; + let Dict.239 : List {Str, I64} = CallByName List.3 Dict.229 Dict.784 Dict.785; + let Dict.783 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = Struct {Dict.228, Dict.239, Dict.234, Dict.235, Dict.236}; + ret Dict.783; else - let Dict.780 : U64 = CallByName List.6 Dict.228; - let Dict.240 : U64 = CallByName Dict.75 Dict.230 Dict.780; + let Dict.781 : U64 = CallByName List.6 Dict.228; + let Dict.240 : U64 = CallByName Dict.75 Dict.230 Dict.781; let Dict.241 : U32 = CallByName Dict.55 Dict.231; - jump Dict.743 Dict.228 Dict.229 Dict.240 Dict.241 Dict.232 Dict.233 Dict.234 Dict.235 Dict.236; + jump Dict.744 Dict.228 Dict.229 Dict.240 Dict.241 Dict.232 Dict.233 Dict.234 Dict.235 Dict.236; else - let Dict.777 : U32 = StructAtIndex 1 Dict.237; - let Dict.757 : Int1 = CallByName Num.24 Dict.231 Dict.777; - if Dict.757 then - let Dict.776 : {Str, I64} = Struct {Dict.232, Dict.233}; - let Dict.242 : List {Str, I64} = CallByName List.4 Dict.229 Dict.776; - let Dict.774 : U64 = CallByName List.6 Dict.242; - let Dict.775 : U64 = 1i64; - let Dict.243 : U64 = CallByName Num.75 Dict.774 Dict.775; - let Dict.773 : U32 = CallByName Num.131 Dict.243; - let Dict.759 : {U32, U32} = Struct {Dict.773, Dict.231}; - let Dict.244 : List {U32, U32} = CallByName Dict.74 Dict.228 Dict.759 Dict.230; - let Dict.758 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = Struct {Dict.244, Dict.242, Dict.234, Dict.235, Dict.236}; - ret Dict.758; + let Dict.778 : U32 = StructAtIndex 1 Dict.237; + let Dict.758 : Int1 = CallByName Num.24 Dict.231 Dict.778; + if Dict.758 then + let Dict.777 : {Str, I64} = Struct {Dict.232, Dict.233}; + let Dict.242 : List {Str, I64} = CallByName List.4 Dict.229 Dict.777; + let Dict.775 : U64 = CallByName List.6 Dict.242; + let Dict.776 : U64 = 1i64; + let Dict.243 : U64 = CallByName Num.75 Dict.775 Dict.776; + let Dict.774 : U32 = CallByName Num.131 Dict.243; + let Dict.760 : {U32, U32} = Struct {Dict.774, Dict.231}; + let Dict.244 : List {U32, U32} = CallByName Dict.74 Dict.228 Dict.760 Dict.230; + let Dict.759 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = Struct {Dict.244, Dict.242, Dict.234, Dict.235, Dict.236}; + ret Dict.759; else - let Dict.750 : U64 = CallByName List.6 Dict.228; - let Dict.245 : U64 = CallByName Dict.75 Dict.230 Dict.750; + let Dict.751 : U64 = CallByName List.6 Dict.228; + let Dict.245 : U64 = CallByName Dict.75 Dict.230 Dict.751; let Dict.246 : U32 = CallByName Dict.55 Dict.231; - jump Dict.743 Dict.228 Dict.229 Dict.245 Dict.246 Dict.232 Dict.233 Dict.234 Dict.235 Dict.236; + jump Dict.744 Dict.228 Dict.229 Dict.245 Dict.246 Dict.232 Dict.233 Dict.234 Dict.235 Dict.236; in inc #Derived_gen.46; - jump Dict.743 #Derived_gen.42 #Derived_gen.43 #Derived_gen.44 #Derived_gen.45 #Derived_gen.46 #Derived_gen.47 #Derived_gen.48 #Derived_gen.49 #Derived_gen.50; + jump Dict.744 #Derived_gen.42 #Derived_gen.43 #Derived_gen.44 #Derived_gen.45 #Derived_gen.46 #Derived_gen.47 #Derived_gen.48 #Derived_gen.49 #Derived_gen.50; procedure Dict.48 (): - let Dict.867 : U32 = 0i64; let Dict.868 : U32 = 0i64; - let Dict.866 : {U32, U32} = Struct {Dict.867, Dict.868}; - ret Dict.866; + let Dict.869 : U32 = 0i64; + let Dict.867 : {U32, U32} = Struct {Dict.868, Dict.869}; + ret Dict.867; procedure Dict.49 (): - let Dict.748 : U32 = 1i64; - let Dict.749 : U8 = 8i64; - let Dict.747 : U32 = CallByName Num.72 Dict.748 Dict.749; - ret Dict.747; + let Dict.749 : U32 = 1i64; + let Dict.750 : U8 = 8i64; + let Dict.748 : U32 = CallByName Num.72 Dict.749 Dict.750; + ret Dict.748; procedure Dict.50 (): - let Dict.798 : U32 = CallByName Dict.49; - let Dict.799 : U32 = 1i64; - let Dict.797 : U32 = CallByName Num.75 Dict.798 Dict.799; - ret Dict.797; + let Dict.799 : U32 = CallByName Dict.49; + let Dict.800 : U32 = 1i64; + let Dict.798 : U32 = CallByName Num.75 Dict.799 Dict.800; + ret Dict.798; procedure Dict.51 (): - let Dict.898 : Float32 = 0.8f64; - ret Dict.898; + let Dict.899 : Float32 = 0.8f64; + ret Dict.899; procedure Dict.52 (): - let Dict.896 : U8 = 64i64; - let Dict.897 : U8 = 3i64; - let Dict.895 : U8 = CallByName Num.75 Dict.896 Dict.897; - ret Dict.895; + let Dict.897 : U8 = 64i64; + let Dict.898 : U8 = 3i64; + let Dict.896 : U8 = CallByName Num.75 Dict.897 Dict.898; + ret Dict.896; procedure Dict.53 (): - let Dict.841 : U64 = 1i64; - let Dict.842 : U8 = 32i64; - let Dict.840 : U64 = CallByName Num.72 Dict.841 Dict.842; - ret Dict.840; + let Dict.842 : U64 = 1i64; + let Dict.843 : U8 = 32i64; + let Dict.841 : U64 = CallByName Num.72 Dict.842 Dict.843; + ret Dict.841; procedure Dict.54 (): - let Dict.839 : U64 = CallByName Dict.53; - ret Dict.839; - -procedure Dict.55 (Dict.313): - let Dict.746 : U32 = CallByName Dict.49; - let Dict.745 : U32 = CallByName Num.51 Dict.313 Dict.746; - ret Dict.745; - -procedure Dict.66 (Dict.726): - let Dict.383 : List {Str, I64} = StructAtIndex 1 Dict.726; - let Dict.384 : U64 = StructAtIndex 2 Dict.726; - let Dict.385 : Float32 = StructAtIndex 3 Dict.726; - let Dict.386 : U8 = StructAtIndex 4 Dict.726; - let #Derived_gen.68 : List {U32, U32} = StructAtIndex 0 Dict.726; + let Dict.840 : U64 = CallByName Dict.53; + ret Dict.840; + +procedure Dict.55 (Dict.314): + let Dict.747 : U32 = CallByName Dict.49; + let Dict.746 : U32 = CallByName Num.51 Dict.314 Dict.747; + ret Dict.746; + +procedure Dict.66 (Dict.727): + let Dict.384 : List {Str, I64} = StructAtIndex 1 Dict.727; + let Dict.385 : U64 = StructAtIndex 2 Dict.727; + let Dict.386 : Float32 = StructAtIndex 3 Dict.727; + let Dict.387 : U8 = StructAtIndex 4 Dict.727; + let #Derived_gen.68 : List {U32, U32} = StructAtIndex 0 Dict.727; dec #Derived_gen.68; - let Dict.884 : U64 = CallByName Dict.54; - let Dict.843 : Int1 = CallByName Bool.7 Dict.384 Dict.884; - if Dict.843 then - let Dict.883 : U8 = 1i64; - let Dict.387 : U8 = CallByName Num.75 Dict.386 Dict.883; - let Dict.862 : {List {U32, U32}, U64} = CallByName Dict.67 Dict.387 Dict.385; - let Dict.388 : List {U32, U32} = StructAtIndex 0 Dict.862; - let Dict.389 : U64 = StructAtIndex 1 Dict.862; - let Dict.390 : List {U32, U32} = CallByName Dict.71 Dict.388 Dict.383 Dict.387; - let Dict.844 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = Struct {Dict.390, Dict.383, Dict.389, Dict.385, Dict.387}; - ret Dict.844; + let Dict.885 : U64 = CallByName Dict.54; + let Dict.844 : Int1 = CallByName Bool.7 Dict.385 Dict.885; + if Dict.844 then + let Dict.884 : U8 = 1i64; + let Dict.388 : U8 = CallByName Num.75 Dict.387 Dict.884; + let Dict.863 : {List {U32, U32}, U64} = CallByName Dict.67 Dict.388 Dict.386; + let Dict.389 : List {U32, U32} = StructAtIndex 0 Dict.863; + let Dict.390 : U64 = StructAtIndex 1 Dict.863; + let Dict.391 : List {U32, U32} = CallByName Dict.71 Dict.389 Dict.384 Dict.388; + let Dict.845 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = Struct {Dict.391, Dict.384, Dict.390, Dict.386, Dict.388}; + ret Dict.845; else - dec Dict.383; - let Dict.834 : Str = "Dict hit limit of "; - let Dict.838 : U64 = CallByName Dict.54; - let Dict.836 : Str = CallByName Num.96 Dict.838; - let Dict.837 : Str = " elements. Unable to grow more."; - let Dict.835 : Str = CallByName Str.3 Dict.836 Dict.837; - dec Dict.837; - let Dict.833 : Str = CallByName Str.3 Dict.834 Dict.835; - dec Dict.835; - Crash Dict.833 - -procedure Dict.67 (Dict.391, Dict.392): - let Dict.393 : U64 = CallByName Dict.70 Dict.391; - let Dict.876 : U64 = CallByName Dict.54; - let Dict.871 : Int1 = CallByName Bool.11 Dict.393 Dict.876; - if Dict.871 then - let Dict.874 : {U32, U32} = CallByName Dict.48; - let Dict.875 : U64 = CallByName Dict.54; - let Dict.873 : List {U32, U32} = CallByName List.11 Dict.874 Dict.875; + dec Dict.384; + let Dict.835 : Str = "Dict hit limit of "; + let Dict.839 : U64 = CallByName Dict.54; + let Dict.837 : Str = CallByName Num.96 Dict.839; + let Dict.838 : Str = " elements. Unable to grow more."; + let Dict.836 : Str = CallByName Str.3 Dict.837 Dict.838; + dec Dict.838; + let Dict.834 : Str = CallByName Str.3 Dict.835 Dict.836; + dec Dict.836; + Crash Dict.834 + +procedure Dict.67 (Dict.392, Dict.393): + let Dict.394 : U64 = CallByName Dict.70 Dict.392; + let Dict.877 : U64 = CallByName Dict.54; + let Dict.872 : Int1 = CallByName Bool.11 Dict.394 Dict.877; + if Dict.872 then + let Dict.875 : {U32, U32} = CallByName Dict.48; + let Dict.876 : U64 = CallByName Dict.54; + let Dict.874 : List {U32, U32} = CallByName List.11 Dict.875 Dict.876; let Dict.54 : U64 = CallByName Dict.54; - let Dict.872 : {List {U32, U32}, U64} = Struct {Dict.873, Dict.54}; - ret Dict.872; + let Dict.873 : {List {U32, U32}, U64} = Struct {Dict.874, Dict.54}; + ret Dict.873; else - let Dict.870 : Float32 = CallByName Num.139 Dict.393; - let Dict.869 : Float32 = CallByName Num.21 Dict.870 Dict.392; - let Dict.394 : U64 = CallByName Num.50 Dict.869; - let Dict.865 : {U32, U32} = CallByName Dict.48; - let Dict.864 : List {U32, U32} = CallByName List.11 Dict.865 Dict.393; - let Dict.863 : {List {U32, U32}, U64} = Struct {Dict.864, Dict.394}; - ret Dict.863; - -procedure Dict.70 (Dict.401): - let Dict.880 : U64 = 1i64; - let Dict.882 : U8 = 64i64; - let Dict.881 : U8 = CallByName Num.75 Dict.882 Dict.401; - let Dict.878 : U64 = CallByName Num.72 Dict.880 Dict.881; - let Dict.879 : U64 = CallByName Dict.54; - let Dict.877 : U64 = CallByName Num.148 Dict.878 Dict.879; - ret Dict.877; - -procedure Dict.71 (Dict.402, Dict.403, Dict.404): - let Dict.845 : List {U32, U32} = CallByName List.83 Dict.403 Dict.402 Dict.404; - ret Dict.845; - -procedure Dict.72 (Dict.411, Dict.412, Dict.413): - let Dict.414 : U64 = CallByName Dict.76 Dict.412; - let Dict.415 : U32 = CallByName Dict.77 Dict.414; - let Dict.416 : U64 = CallByName Dict.78 Dict.414 Dict.413; - let Dict.853 : {U64, U32} = CallByName Dict.73 Dict.411 Dict.416 Dict.415; - ret Dict.853; + let Dict.871 : Float32 = CallByName Num.139 Dict.394; + let Dict.870 : Float32 = CallByName Num.21 Dict.871 Dict.393; + let Dict.395 : U64 = CallByName Num.50 Dict.870; + let Dict.866 : {U32, U32} = CallByName Dict.48; + let Dict.865 : List {U32, U32} = CallByName List.11 Dict.866 Dict.394; + let Dict.864 : {List {U32, U32}, U64} = Struct {Dict.865, Dict.395}; + ret Dict.864; + +procedure Dict.70 (Dict.402): + let Dict.881 : U64 = 1i64; + let Dict.883 : U8 = 64i64; + let Dict.882 : U8 = CallByName Num.75 Dict.883 Dict.402; + let Dict.879 : U64 = CallByName Num.72 Dict.881 Dict.882; + let Dict.880 : U64 = CallByName Dict.54; + let Dict.878 : U64 = CallByName Num.148 Dict.879 Dict.880; + ret Dict.878; + +procedure Dict.71 (Dict.403, Dict.404, Dict.405): + let Dict.846 : List {U32, U32} = CallByName List.83 Dict.404 Dict.403 Dict.405; + ret Dict.846; + +procedure Dict.72 (Dict.412, Dict.413, Dict.414): + let Dict.415 : U64 = CallByName Dict.76 Dict.413; + let Dict.416 : U32 = CallByName Dict.77 Dict.415; + let Dict.417 : U64 = CallByName Dict.78 Dict.415 Dict.414; + let Dict.854 : {U64, U32} = CallByName Dict.73 Dict.412 Dict.417 Dict.416; + ret Dict.854; procedure Dict.73 (#Derived_gen.16, #Derived_gen.17, #Derived_gen.18): - joinpoint Dict.854 Dict.417 Dict.418 Dict.419: - let Dict.420 : {U32, U32} = CallByName Dict.22 Dict.417 Dict.418; - let Dict.861 : U32 = StructAtIndex 1 Dict.420; - let Dict.856 : Int1 = CallByName Num.22 Dict.419 Dict.861; - if Dict.856 then - let Dict.860 : U64 = CallByName List.6 Dict.417; - let Dict.858 : U64 = CallByName Dict.75 Dict.418 Dict.860; - let Dict.859 : U32 = CallByName Dict.55 Dict.419; - jump Dict.854 Dict.417 Dict.858 Dict.859; + joinpoint Dict.855 Dict.418 Dict.419 Dict.420: + let Dict.421 : {U32, U32} = CallByName Dict.22 Dict.418 Dict.419; + let Dict.862 : U32 = StructAtIndex 1 Dict.421; + let Dict.857 : Int1 = CallByName Num.22 Dict.420 Dict.862; + if Dict.857 then + let Dict.861 : U64 = CallByName List.6 Dict.418; + let Dict.859 : U64 = CallByName Dict.75 Dict.419 Dict.861; + let Dict.860 : U32 = CallByName Dict.55 Dict.420; + jump Dict.855 Dict.418 Dict.859 Dict.860; else - dec Dict.417; - let Dict.855 : {U64, U32} = Struct {Dict.418, Dict.419}; - ret Dict.855; + dec Dict.418; + let Dict.856 : {U64, U32} = Struct {Dict.419, Dict.420}; + ret Dict.856; in inc #Derived_gen.16; - jump Dict.854 #Derived_gen.16 #Derived_gen.17 #Derived_gen.18; + jump Dict.855 #Derived_gen.16 #Derived_gen.17 #Derived_gen.18; procedure Dict.74 (#Derived_gen.51, #Derived_gen.52, #Derived_gen.53): - joinpoint Dict.760 Dict.421 Dict.422 Dict.423: - let Dict.424 : {U32, U32} = CallByName Dict.22 Dict.421 Dict.423; - let Dict.770 : U32 = StructAtIndex 1 Dict.424; - let Dict.771 : U32 = 0i64; - let Dict.762 : Int1 = CallByName Bool.7 Dict.770 Dict.771; - if Dict.762 then - let Dict.425 : List {U32, U32} = CallByName List.3 Dict.421 Dict.423 Dict.422; - let Dict.767 : U32 = StructAtIndex 0 Dict.424; - let Dict.768 : U32 = StructAtIndex 1 Dict.424; - let Dict.769 : U32 = CallByName Dict.55 Dict.768; - let Dict.764 : {U32, U32} = Struct {Dict.767, Dict.769}; - let Dict.766 : U64 = CallByName List.6 Dict.425; - let Dict.765 : U64 = CallByName Dict.75 Dict.423 Dict.766; - jump Dict.760 Dict.425 Dict.764 Dict.765; + joinpoint Dict.761 Dict.422 Dict.423 Dict.424: + let Dict.425 : {U32, U32} = CallByName Dict.22 Dict.422 Dict.424; + let Dict.771 : U32 = StructAtIndex 1 Dict.425; + let Dict.772 : U32 = 0i64; + let Dict.763 : Int1 = CallByName Bool.7 Dict.771 Dict.772; + if Dict.763 then + let Dict.426 : List {U32, U32} = CallByName List.3 Dict.422 Dict.424 Dict.423; + let Dict.768 : U32 = StructAtIndex 0 Dict.425; + let Dict.769 : U32 = StructAtIndex 1 Dict.425; + let Dict.770 : U32 = CallByName Dict.55 Dict.769; + let Dict.765 : {U32, U32} = Struct {Dict.768, Dict.770}; + let Dict.767 : U64 = CallByName List.6 Dict.426; + let Dict.766 : U64 = CallByName Dict.75 Dict.424 Dict.767; + jump Dict.761 Dict.426 Dict.765 Dict.766; else - let Dict.761 : List {U32, U32} = CallByName List.3 Dict.421 Dict.423 Dict.422; - ret Dict.761; + let Dict.762 : List {U32, U32} = CallByName List.3 Dict.422 Dict.424 Dict.423; + ret Dict.762; in - jump Dict.760 #Derived_gen.51 #Derived_gen.52 #Derived_gen.53; - -procedure Dict.75 (Dict.426, Dict.427): - let Dict.756 : U64 = 1i64; - let Dict.755 : U64 = CallByName Num.51 Dict.426 Dict.756; - let Dict.752 : Int1 = CallByName Bool.7 Dict.755 Dict.427; - if Dict.752 then - let Dict.754 : U64 = 1i64; - let Dict.753 : U64 = CallByName Num.51 Dict.426 Dict.754; - ret Dict.753; + jump Dict.761 #Derived_gen.51 #Derived_gen.52 #Derived_gen.53; + +procedure Dict.75 (Dict.427, Dict.428): + let Dict.757 : U64 = 1i64; + let Dict.756 : U64 = CallByName Num.51 Dict.427 Dict.757; + let Dict.753 : Int1 = CallByName Bool.7 Dict.756 Dict.428; + if Dict.753 then + let Dict.755 : U64 = 1i64; + let Dict.754 : U64 = CallByName Num.51 Dict.427 Dict.755; + ret Dict.754; else - let Dict.751 : U64 = 0i64; - ret Dict.751; - -procedure Dict.76 (Dict.428): - let Dict.804 : [C , C U64] = TagId(0) ; - let Dict.803 : {U64, U64} = CallByName Dict.80 Dict.804; - let Dict.801 : {U64, U64} = CallByName Hash.19 Dict.803 Dict.428; - let Dict.800 : U64 = CallByName Dict.83 Dict.801; - ret Dict.800; - -procedure Dict.77 (Dict.430): - let Dict.795 : U32 = CallByName Num.131 Dict.430; - let Dict.796 : U32 = CallByName Dict.50; - let Dict.793 : U32 = CallByName Num.69 Dict.795 Dict.796; - let Dict.794 : U32 = CallByName Dict.49; - let Dict.792 : U32 = CallByName Num.71 Dict.793 Dict.794; + let Dict.752 : U64 = 0i64; + ret Dict.752; + +procedure Dict.76 (Dict.429): + let Dict.805 : [C , C U64] = TagId(0) ; + let Dict.804 : {U64, U64} = CallByName Dict.80 Dict.805; + let Dict.802 : {U64, U64} = CallByName Hash.19 Dict.804 Dict.429; + let Dict.801 : U64 = CallByName Dict.83 Dict.802; + ret Dict.801; + +procedure Dict.77 (Dict.431): + let Dict.796 : U32 = CallByName Num.131 Dict.431; + let Dict.797 : U32 = CallByName Dict.50; + let Dict.794 : U32 = CallByName Num.69 Dict.796 Dict.797; + let Dict.795 : U32 = CallByName Dict.49; + let Dict.793 : U32 = CallByName Num.71 Dict.794 Dict.795; + ret Dict.793; + +procedure Dict.78 (Dict.432, Dict.433): + let Dict.792 : U64 = CallByName Num.74 Dict.432 Dict.433; ret Dict.792; -procedure Dict.78 (Dict.431, Dict.432): - let Dict.791 : U64 = CallByName Num.74 Dict.431 Dict.432; - ret Dict.791; - procedure Dict.8 (Dict.217, Dict.218, Dict.219): - joinpoint Dict.831 Dict.829: - let Dict.220 : List {U32, U32} = StructAtIndex 0 Dict.829; - let Dict.221 : List {Str, I64} = StructAtIndex 1 Dict.829; - let Dict.222 : U64 = StructAtIndex 2 Dict.829; - let Dict.223 : Float32 = StructAtIndex 3 Dict.829; - let Dict.224 : U8 = StructAtIndex 4 Dict.829; + joinpoint Dict.832 Dict.830: + let Dict.220 : List {U32, U32} = StructAtIndex 0 Dict.830; + let Dict.221 : List {Str, I64} = StructAtIndex 1 Dict.830; + let Dict.222 : U64 = StructAtIndex 2 Dict.830; + let Dict.223 : Float32 = StructAtIndex 3 Dict.830; + let Dict.224 : U8 = StructAtIndex 4 Dict.830; inc Dict.218; let Dict.225 : U64 = CallByName Dict.76 Dict.218; let Dict.226 : U32 = CallByName Dict.77 Dict.225; let Dict.227 : U64 = CallByName Dict.78 Dict.225 Dict.224; - let Dict.742 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = CallByName Dict.45 Dict.220 Dict.221 Dict.227 Dict.226 Dict.218 Dict.219 Dict.222 Dict.223 Dict.224; + let Dict.743 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = CallByName Dict.45 Dict.220 Dict.221 Dict.227 Dict.226 Dict.218 Dict.219 Dict.222 Dict.223 Dict.224; dec Dict.218; - ret Dict.742; + ret Dict.743; in inc 2 Dict.217; - let Dict.886 : U64 = CallByName Dict.4 Dict.217; - let Dict.887 : U64 = CallByName Dict.20 Dict.217; - let Dict.885 : Int1 = CallByName Num.22 Dict.886 Dict.887; - if Dict.885 then - jump Dict.831 Dict.217; + let Dict.887 : U64 = CallByName Dict.4 Dict.217; + let Dict.888 : U64 = CallByName Dict.20 Dict.217; + let Dict.886 : Int1 = CallByName Num.22 Dict.887 Dict.888; + if Dict.886 then + jump Dict.832 Dict.217; else - let Dict.830 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = CallByName Dict.66 Dict.217; - jump Dict.831 Dict.830; - -procedure Dict.80 (Dict.434): - joinpoint Dict.821 Dict.435: - let Dict.806 : U64 = CallByName Dict.82 Dict.435; - let Dict.805 : {U64, U64} = Struct {Dict.806, Dict.435}; - ret Dict.805; + let Dict.831 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = CallByName Dict.66 Dict.217; + jump Dict.832 Dict.831; + +procedure Dict.80 (Dict.435): + joinpoint Dict.822 Dict.436: + let Dict.807 : U64 = CallByName Dict.82 Dict.436; + let Dict.806 : {U64, U64} = Struct {Dict.807, Dict.436}; + ret Dict.806; in - let Dict.826 : U8 = 0i64; - let Dict.827 : U8 = GetTagId Dict.434; - let Dict.828 : Int1 = lowlevel Eq Dict.826 Dict.827; - if Dict.828 then - let Dict.823 : {} = Struct {}; - let Dict.822 : U64 = CallByName Dict.23 Dict.823; - jump Dict.821 Dict.822; + let Dict.827 : U8 = 0i64; + let Dict.828 : U8 = GetTagId Dict.435; + let Dict.829 : Int1 = lowlevel Eq Dict.827 Dict.828; + if Dict.829 then + let Dict.824 : {} = Struct {}; + let Dict.823 : U64 = CallByName Dict.23 Dict.824; + jump Dict.822 Dict.823; else - let Dict.436 : U64 = UnionAtIndex (Id 1) (Index 0) Dict.434; - jump Dict.821 Dict.436; - -procedure Dict.81 (Dict.715, Dict.716): - let Dict.439 : U64 = StructAtIndex 0 Dict.716; - let Dict.440 : U64 = StructAtIndex 1 Dict.716; - let Dict.442 : U64 = StructAtIndex 2 Dict.716; - let Dict.441 : U64 = StructAtIndex 3 Dict.716; - let Dict.437 : U64 = StructAtIndex 0 Dict.715; - let Dict.438 : U64 = StructAtIndex 1 Dict.715; - let Dict.920 : U64 = CallByName Dict.93; - let Dict.918 : U64 = CallByName Num.70 Dict.439 Dict.920; - let Dict.919 : U64 = CallByName Num.70 Dict.440 Dict.441; - let Dict.443 : {U64, U64} = CallByName Dict.97 Dict.918 Dict.919; - let Dict.915 : U64 = StructAtIndex 0 Dict.443; - let Dict.916 : U64 = CallByName Dict.92; - let Dict.914 : U64 = CallByName Num.70 Dict.915 Dict.916; - let Dict.444 : U64 = CallByName Num.70 Dict.914 Dict.442; - let Dict.911 : U64 = StructAtIndex 1 Dict.443; - let Dict.912 : U64 = CallByName Dict.93; - let Dict.445 : U64 = CallByName Num.70 Dict.911 Dict.912; - let Dict.446 : U64 = CallByName Dict.96 Dict.444 Dict.445; - let Dict.903 : U64 = CallByName Dict.96 Dict.438 Dict.446; - let Dict.902 : {U64, U64} = Struct {Dict.437, Dict.903}; - ret Dict.902; - -procedure Dict.82 (Dict.447): - let Dict.819 : U64 = CallByName Dict.92; - let Dict.809 : U64 = CallByName Num.70 Dict.447 Dict.819; - let Dict.810 : U64 = CallByName Dict.93; - let Dict.808 : U64 = CallByName Dict.96 Dict.809 Dict.810; - let Dict.807 : U64 = CallByName Num.70 Dict.808 Dict.447; - ret Dict.807; - -procedure Dict.83 (Dict.734): - let Dict.448 : U64 = StructAtIndex 1 Dict.734; - ret Dict.448; - -procedure Dict.89 (Dict.709, Dict.487): - let Dict.485 : U64 = StructAtIndex 0 Dict.709; - let Dict.486 : U64 = StructAtIndex 1 Dict.709; - let Dict.488 : U64 = CallByName List.6 Dict.487; - joinpoint Dict.925 Dict.489: - let Dict.900 : {U64, U64} = Struct {Dict.485, Dict.486}; - let Dict.921 : U64 = StructAtIndex 0 Dict.489; - let Dict.922 : U64 = StructAtIndex 1 Dict.489; - let Dict.923 : U64 = StructAtIndex 2 Dict.489; - let Dict.901 : {U64, U64, U64, U64} = Struct {Dict.921, Dict.922, Dict.488, Dict.923}; - let Dict.899 : {U64, U64} = CallByName Dict.81 Dict.900 Dict.901; - ret Dict.899; + let Dict.437 : U64 = UnionAtIndex (Id 1) (Index 0) Dict.435; + jump Dict.822 Dict.437; + +procedure Dict.81 (Dict.716, Dict.717): + let Dict.440 : U64 = StructAtIndex 0 Dict.717; + let Dict.441 : U64 = StructAtIndex 1 Dict.717; + let Dict.443 : U64 = StructAtIndex 2 Dict.717; + let Dict.442 : U64 = StructAtIndex 3 Dict.717; + let Dict.438 : U64 = StructAtIndex 0 Dict.716; + let Dict.439 : U64 = StructAtIndex 1 Dict.716; + let Dict.921 : U64 = CallByName Dict.93; + let Dict.919 : U64 = CallByName Num.70 Dict.440 Dict.921; + let Dict.920 : U64 = CallByName Num.70 Dict.441 Dict.442; + let Dict.444 : {U64, U64} = CallByName Dict.97 Dict.919 Dict.920; + let Dict.916 : U64 = StructAtIndex 0 Dict.444; + let Dict.917 : U64 = CallByName Dict.92; + let Dict.915 : U64 = CallByName Num.70 Dict.916 Dict.917; + let Dict.445 : U64 = CallByName Num.70 Dict.915 Dict.443; + let Dict.912 : U64 = StructAtIndex 1 Dict.444; + let Dict.913 : U64 = CallByName Dict.93; + let Dict.446 : U64 = CallByName Num.70 Dict.912 Dict.913; + let Dict.447 : U64 = CallByName Dict.96 Dict.445 Dict.446; + let Dict.904 : U64 = CallByName Dict.96 Dict.439 Dict.447; + let Dict.903 : {U64, U64} = Struct {Dict.438, Dict.904}; + ret Dict.903; + +procedure Dict.82 (Dict.448): + let Dict.820 : U64 = CallByName Dict.92; + let Dict.810 : U64 = CallByName Num.70 Dict.448 Dict.820; + let Dict.811 : U64 = CallByName Dict.93; + let Dict.809 : U64 = CallByName Dict.96 Dict.810 Dict.811; + let Dict.808 : U64 = CallByName Num.70 Dict.809 Dict.448; + ret Dict.808; + +procedure Dict.83 (Dict.735): + let Dict.449 : U64 = StructAtIndex 1 Dict.735; + ret Dict.449; + +procedure Dict.89 (Dict.710, Dict.488): + let Dict.486 : U64 = StructAtIndex 0 Dict.710; + let Dict.487 : U64 = StructAtIndex 1 Dict.710; + let Dict.489 : U64 = CallByName List.6 Dict.488; + joinpoint Dict.926 Dict.490: + let Dict.901 : {U64, U64} = Struct {Dict.486, Dict.487}; + let Dict.922 : U64 = StructAtIndex 0 Dict.490; + let Dict.923 : U64 = StructAtIndex 1 Dict.490; + let Dict.924 : U64 = StructAtIndex 2 Dict.490; + let Dict.902 : {U64, U64, U64, U64} = Struct {Dict.922, Dict.923, Dict.489, Dict.924}; + let Dict.900 : {U64, U64} = CallByName Dict.81 Dict.901 Dict.902; + ret Dict.900; in - let Dict.1099 : U64 = 16i64; - let Dict.1039 : Int1 = CallByName Num.23 Dict.488 Dict.1099; - if Dict.1039 then - joinpoint Dict.1041 Dict.924: - jump Dict.925 Dict.924; + let Dict.1100 : U64 = 16i64; + let Dict.1040 : Int1 = CallByName Num.23 Dict.489 Dict.1100; + if Dict.1040 then + joinpoint Dict.1042 Dict.925: + jump Dict.926 Dict.925; in - let Dict.1098 : U64 = 4i64; - let Dict.1063 : Int1 = CallByName Num.25 Dict.488 Dict.1098; - if Dict.1063 then - let Dict.1097 : U8 = 3i64; - let Dict.1095 : U64 = CallByName Num.74 Dict.488 Dict.1097; - let Dict.1096 : U8 = 2i64; - let Dict.490 : U64 = CallByName Num.72 Dict.1095 Dict.1096; - let Dict.1094 : U64 = 0i64; - let Dict.1092 : U64 = CallByName Dict.99 Dict.487 Dict.1094; - let Dict.1093 : U8 = 32i64; - let Dict.1090 : U64 = CallByName Num.72 Dict.1092 Dict.1093; - let Dict.1091 : U64 = CallByName Dict.99 Dict.487 Dict.490; - let Dict.491 : U64 = CallByName Num.71 Dict.1090 Dict.1091; - let Dict.1089 : U64 = 4i64; - let Dict.1088 : U64 = CallByName Num.75 Dict.488 Dict.1089; - let Dict.1086 : U64 = CallByName Dict.99 Dict.487 Dict.1088; - let Dict.1087 : U8 = 32i64; - let Dict.1064 : U64 = CallByName Num.72 Dict.1086 Dict.1087; - let Dict.1085 : U64 = 4i64; - let Dict.1084 : U64 = CallByName Num.75 Dict.488 Dict.1085; - let Dict.1066 : U64 = CallByName Num.75 Dict.1084 Dict.490; - let Dict.1065 : U64 = CallByName Dict.99 Dict.487 Dict.1066; - let Dict.492 : U64 = CallByName Num.71 Dict.1064 Dict.1065; - let Dict.1040 : {U64, U64, U64} = Struct {Dict.491, Dict.492, Dict.485}; - jump Dict.1041 Dict.1040; + let Dict.1099 : U64 = 4i64; + let Dict.1064 : Int1 = CallByName Num.25 Dict.489 Dict.1099; + if Dict.1064 then + let Dict.1098 : U8 = 3i64; + let Dict.1096 : U64 = CallByName Num.74 Dict.489 Dict.1098; + let Dict.1097 : U8 = 2i64; + let Dict.491 : U64 = CallByName Num.72 Dict.1096 Dict.1097; + let Dict.1095 : U64 = 0i64; + let Dict.1093 : U64 = CallByName Dict.99 Dict.488 Dict.1095; + let Dict.1094 : U8 = 32i64; + let Dict.1091 : U64 = CallByName Num.72 Dict.1093 Dict.1094; + let Dict.1092 : U64 = CallByName Dict.99 Dict.488 Dict.491; + let Dict.492 : U64 = CallByName Num.71 Dict.1091 Dict.1092; + let Dict.1090 : U64 = 4i64; + let Dict.1089 : U64 = CallByName Num.75 Dict.489 Dict.1090; + let Dict.1087 : U64 = CallByName Dict.99 Dict.488 Dict.1089; + let Dict.1088 : U8 = 32i64; + let Dict.1065 : U64 = CallByName Num.72 Dict.1087 Dict.1088; + let Dict.1086 : U64 = 4i64; + let Dict.1085 : U64 = CallByName Num.75 Dict.489 Dict.1086; + let Dict.1067 : U64 = CallByName Num.75 Dict.1085 Dict.491; + let Dict.1066 : U64 = CallByName Dict.99 Dict.488 Dict.1067; + let Dict.493 : U64 = CallByName Num.71 Dict.1065 Dict.1066; + let Dict.1041 : {U64, U64, U64} = Struct {Dict.492, Dict.493, Dict.486}; + jump Dict.1042 Dict.1041; else - let Dict.1062 : U64 = 0i64; - let Dict.1044 : Int1 = CallByName Num.24 Dict.488 Dict.1062; - if Dict.1044 then + let Dict.1063 : U64 = 0i64; + let Dict.1045 : Int1 = CallByName Num.24 Dict.489 Dict.1063; + if Dict.1045 then + let Dict.1048 : U64 = 0i64; + let Dict.1046 : U64 = CallByName Dict.100 Dict.488 Dict.1048 Dict.489; let Dict.1047 : U64 = 0i64; - let Dict.1045 : U64 = CallByName Dict.100 Dict.487 Dict.1047 Dict.488; - let Dict.1046 : U64 = 0i64; - let Dict.1040 : {U64, U64, U64} = Struct {Dict.1045, Dict.1046, Dict.485}; - jump Dict.1041 Dict.1040; + let Dict.1041 : {U64, U64, U64} = Struct {Dict.1046, Dict.1047, Dict.486}; + jump Dict.1042 Dict.1041; else - let Dict.1042 : U64 = 0i64; let Dict.1043 : U64 = 0i64; - let Dict.1040 : {U64, U64, U64} = Struct {Dict.1042, Dict.1043, Dict.485}; - jump Dict.1041 Dict.1040; + let Dict.1044 : U64 = 0i64; + let Dict.1041 : {U64, U64, U64} = Struct {Dict.1043, Dict.1044, Dict.486}; + jump Dict.1042 Dict.1041; else - let Dict.1038 : U64 = 48i64; - let Dict.1036 : Int1 = CallByName Num.23 Dict.488 Dict.1038; - if Dict.1036 then - let Dict.1037 : U64 = 0i64; - let Dict.924 : {U64, U64, U64} = CallByName Dict.91 Dict.485 Dict.487 Dict.1037 Dict.488; - jump Dict.925 Dict.924; + let Dict.1039 : U64 = 48i64; + let Dict.1037 : Int1 = CallByName Num.23 Dict.489 Dict.1039; + if Dict.1037 then + let Dict.1038 : U64 = 0i64; + let Dict.925 : {U64, U64, U64} = CallByName Dict.91 Dict.486 Dict.488 Dict.1038 Dict.489; + jump Dict.926 Dict.925; else - let Dict.926 : U64 = 0i64; - let Dict.924 : {U64, U64, U64} = CallByName Dict.90 Dict.485 Dict.485 Dict.485 Dict.487 Dict.926 Dict.488; - jump Dict.925 Dict.924; + let Dict.927 : U64 = 0i64; + let Dict.925 : {U64, U64, U64} = CallByName Dict.90 Dict.486 Dict.486 Dict.486 Dict.488 Dict.927 Dict.489; + jump Dict.926 Dict.925; procedure Dict.90 (#Derived_gen.6, #Derived_gen.7, #Derived_gen.8, #Derived_gen.9, #Derived_gen.10, #Derived_gen.11): - joinpoint Dict.927 Dict.493 Dict.494 Dict.495 Dict.496 Dict.497 Dict.498: - let Dict.1034 : U64 = CallByName Dict.98 Dict.496 Dict.497; - let Dict.1035 : U64 = CallByName Dict.93; - let Dict.1029 : U64 = CallByName Num.70 Dict.1034 Dict.1035; - let Dict.1033 : U64 = 8i64; - let Dict.1032 : U64 = CallByName Num.51 Dict.497 Dict.1033; - let Dict.1031 : U64 = CallByName Dict.98 Dict.496 Dict.1032; - let Dict.1030 : U64 = CallByName Num.70 Dict.1031 Dict.493; - let Dict.499 : U64 = CallByName Dict.96 Dict.1029 Dict.1030; - let Dict.1028 : U64 = 16i64; - let Dict.1027 : U64 = CallByName Num.51 Dict.497 Dict.1028; - let Dict.1024 : U64 = CallByName Dict.98 Dict.496 Dict.1027; - let Dict.1025 : U64 = CallByName Dict.94; - let Dict.1019 : U64 = CallByName Num.70 Dict.1024 Dict.1025; - let Dict.1023 : U64 = 24i64; - let Dict.1022 : U64 = CallByName Num.51 Dict.497 Dict.1023; - let Dict.1021 : U64 = CallByName Dict.98 Dict.496 Dict.1022; - let Dict.1020 : U64 = CallByName Num.70 Dict.1021 Dict.494; - let Dict.500 : U64 = CallByName Dict.96 Dict.1019 Dict.1020; - let Dict.1018 : U64 = 32i64; - let Dict.1017 : U64 = CallByName Num.51 Dict.497 Dict.1018; - let Dict.1014 : U64 = CallByName Dict.98 Dict.496 Dict.1017; - let Dict.1015 : U64 = CallByName Dict.95; - let Dict.1009 : U64 = CallByName Num.70 Dict.1014 Dict.1015; - let Dict.1013 : U64 = 40i64; - let Dict.1012 : U64 = CallByName Num.51 Dict.497 Dict.1013; - let Dict.1011 : U64 = CallByName Dict.98 Dict.496 Dict.1012; - let Dict.1010 : U64 = CallByName Num.70 Dict.1011 Dict.495; - let Dict.501 : U64 = CallByName Dict.96 Dict.1009 Dict.1010; + joinpoint Dict.928 Dict.494 Dict.495 Dict.496 Dict.497 Dict.498 Dict.499: + let Dict.1035 : U64 = CallByName Dict.98 Dict.497 Dict.498; + let Dict.1036 : U64 = CallByName Dict.93; + let Dict.1030 : U64 = CallByName Num.70 Dict.1035 Dict.1036; + let Dict.1034 : U64 = 8i64; + let Dict.1033 : U64 = CallByName Num.51 Dict.498 Dict.1034; + let Dict.1032 : U64 = CallByName Dict.98 Dict.497 Dict.1033; + let Dict.1031 : U64 = CallByName Num.70 Dict.1032 Dict.494; + let Dict.500 : U64 = CallByName Dict.96 Dict.1030 Dict.1031; + let Dict.1029 : U64 = 16i64; + let Dict.1028 : U64 = CallByName Num.51 Dict.498 Dict.1029; + let Dict.1025 : U64 = CallByName Dict.98 Dict.497 Dict.1028; + let Dict.1026 : U64 = CallByName Dict.94; + let Dict.1020 : U64 = CallByName Num.70 Dict.1025 Dict.1026; + let Dict.1024 : U64 = 24i64; + let Dict.1023 : U64 = CallByName Num.51 Dict.498 Dict.1024; + let Dict.1022 : U64 = CallByName Dict.98 Dict.497 Dict.1023; + let Dict.1021 : U64 = CallByName Num.70 Dict.1022 Dict.495; + let Dict.501 : U64 = CallByName Dict.96 Dict.1020 Dict.1021; + let Dict.1019 : U64 = 32i64; + let Dict.1018 : U64 = CallByName Num.51 Dict.498 Dict.1019; + let Dict.1015 : U64 = CallByName Dict.98 Dict.497 Dict.1018; + let Dict.1016 : U64 = CallByName Dict.95; + let Dict.1010 : U64 = CallByName Num.70 Dict.1015 Dict.1016; + let Dict.1014 : U64 = 40i64; + let Dict.1013 : U64 = CallByName Num.51 Dict.498 Dict.1014; + let Dict.1012 : U64 = CallByName Dict.98 Dict.497 Dict.1013; + let Dict.1011 : U64 = CallByName Num.70 Dict.1012 Dict.496; + let Dict.502 : U64 = CallByName Dict.96 Dict.1010 Dict.1011; + let Dict.1009 : U64 = 48i64; + let Dict.503 : U64 = CallByName Num.75 Dict.499 Dict.1009; let Dict.1008 : U64 = 48i64; - let Dict.502 : U64 = CallByName Num.75 Dict.498 Dict.1008; + let Dict.504 : U64 = CallByName Num.51 Dict.498 Dict.1008; let Dict.1007 : U64 = 48i64; - let Dict.503 : U64 = CallByName Num.51 Dict.497 Dict.1007; - let Dict.1006 : U64 = 48i64; - let Dict.1004 : Int1 = CallByName Num.24 Dict.502 Dict.1006; - if Dict.1004 then - jump Dict.927 Dict.499 Dict.500 Dict.501 Dict.496 Dict.503 Dict.502; + let Dict.1005 : Int1 = CallByName Num.24 Dict.503 Dict.1007; + if Dict.1005 then + jump Dict.928 Dict.500 Dict.501 Dict.502 Dict.497 Dict.504 Dict.503; else - let Dict.1003 : U64 = 16i64; - let Dict.978 : Int1 = CallByName Num.24 Dict.502 Dict.1003; - if Dict.978 then - let Dict.1002 : U64 = CallByName Num.70 Dict.500 Dict.499; - let Dict.504 : U64 = CallByName Num.70 Dict.501 Dict.1002; - let Dict.979 : {U64, U64, U64} = CallByName Dict.91 Dict.504 Dict.496 Dict.503 Dict.502; - dec Dict.496; - ret Dict.979; + let Dict.1004 : U64 = 16i64; + let Dict.979 : Int1 = CallByName Num.24 Dict.503 Dict.1004; + if Dict.979 then + let Dict.1003 : U64 = CallByName Num.70 Dict.501 Dict.500; + let Dict.505 : U64 = CallByName Num.70 Dict.502 Dict.1003; + let Dict.980 : {U64, U64, U64} = CallByName Dict.91 Dict.505 Dict.497 Dict.504 Dict.503; + dec Dict.497; + ret Dict.980; else - let Dict.977 : U64 = CallByName Num.70 Dict.500 Dict.499; - let Dict.505 : U64 = CallByName Num.70 Dict.501 Dict.977; - let Dict.976 : U64 = 16i64; - let Dict.975 : U64 = CallByName Num.75 Dict.502 Dict.976; - let Dict.974 : U64 = CallByName Num.51 Dict.975 Dict.503; - let Dict.929 : U64 = CallByName Dict.98 Dict.496 Dict.974; - let Dict.973 : U64 = 8i64; - let Dict.972 : U64 = CallByName Num.75 Dict.502 Dict.973; - let Dict.931 : U64 = CallByName Num.51 Dict.972 Dict.503; - let Dict.930 : U64 = CallByName Dict.98 Dict.496 Dict.931; - dec Dict.496; - let Dict.928 : {U64, U64, U64} = Struct {Dict.929, Dict.930, Dict.505}; - ret Dict.928; + let Dict.978 : U64 = CallByName Num.70 Dict.501 Dict.500; + let Dict.506 : U64 = CallByName Num.70 Dict.502 Dict.978; + let Dict.977 : U64 = 16i64; + let Dict.976 : U64 = CallByName Num.75 Dict.503 Dict.977; + let Dict.975 : U64 = CallByName Num.51 Dict.976 Dict.504; + let Dict.930 : U64 = CallByName Dict.98 Dict.497 Dict.975; + let Dict.974 : U64 = 8i64; + let Dict.973 : U64 = CallByName Num.75 Dict.503 Dict.974; + let Dict.932 : U64 = CallByName Num.51 Dict.973 Dict.504; + let Dict.931 : U64 = CallByName Dict.98 Dict.497 Dict.932; + dec Dict.497; + let Dict.929 : {U64, U64, U64} = Struct {Dict.930, Dict.931, Dict.506}; + ret Dict.929; in inc #Derived_gen.9; - jump Dict.927 #Derived_gen.6 #Derived_gen.7 #Derived_gen.8 #Derived_gen.9 #Derived_gen.10 #Derived_gen.11; + jump Dict.928 #Derived_gen.6 #Derived_gen.7 #Derived_gen.8 #Derived_gen.9 #Derived_gen.10 #Derived_gen.11; procedure Dict.91 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.3): - joinpoint Dict.980 Dict.506 Dict.507 Dict.508 Dict.509: - let Dict.1000 : U64 = CallByName Dict.98 Dict.507 Dict.508; - let Dict.1001 : U64 = CallByName Dict.93; - let Dict.995 : U64 = CallByName Num.70 Dict.1000 Dict.1001; - let Dict.999 : U64 = 8i64; - let Dict.998 : U64 = CallByName Num.51 Dict.508 Dict.999; - let Dict.997 : U64 = CallByName Dict.98 Dict.507 Dict.998; - let Dict.996 : U64 = CallByName Num.70 Dict.997 Dict.506; - let Dict.510 : U64 = CallByName Dict.96 Dict.995 Dict.996; + joinpoint Dict.981 Dict.507 Dict.508 Dict.509 Dict.510: + let Dict.1001 : U64 = CallByName Dict.98 Dict.508 Dict.509; + let Dict.1002 : U64 = CallByName Dict.93; + let Dict.996 : U64 = CallByName Num.70 Dict.1001 Dict.1002; + let Dict.1000 : U64 = 8i64; + let Dict.999 : U64 = CallByName Num.51 Dict.509 Dict.1000; + let Dict.998 : U64 = CallByName Dict.98 Dict.508 Dict.999; + let Dict.997 : U64 = CallByName Num.70 Dict.998 Dict.507; + let Dict.511 : U64 = CallByName Dict.96 Dict.996 Dict.997; + let Dict.995 : U64 = 16i64; + let Dict.512 : U64 = CallByName Num.75 Dict.510 Dict.995; let Dict.994 : U64 = 16i64; - let Dict.511 : U64 = CallByName Num.75 Dict.509 Dict.994; + let Dict.513 : U64 = CallByName Num.51 Dict.509 Dict.994; let Dict.993 : U64 = 16i64; - let Dict.512 : U64 = CallByName Num.51 Dict.508 Dict.993; - let Dict.992 : U64 = 16i64; - let Dict.982 : Int1 = CallByName Num.23 Dict.511 Dict.992; - if Dict.982 then - let Dict.991 : U64 = 16i64; - let Dict.990 : U64 = CallByName Num.75 Dict.511 Dict.991; - let Dict.989 : U64 = CallByName Num.51 Dict.990 Dict.512; - let Dict.984 : U64 = CallByName Dict.98 Dict.507 Dict.989; - let Dict.988 : U64 = 8i64; - let Dict.987 : U64 = CallByName Num.75 Dict.511 Dict.988; - let Dict.986 : U64 = CallByName Num.51 Dict.987 Dict.512; - let Dict.985 : U64 = CallByName Dict.98 Dict.507 Dict.986; - dec Dict.507; - let Dict.983 : {U64, U64, U64} = Struct {Dict.984, Dict.985, Dict.510}; - ret Dict.983; + let Dict.983 : Int1 = CallByName Num.23 Dict.512 Dict.993; + if Dict.983 then + let Dict.992 : U64 = 16i64; + let Dict.991 : U64 = CallByName Num.75 Dict.512 Dict.992; + let Dict.990 : U64 = CallByName Num.51 Dict.991 Dict.513; + let Dict.985 : U64 = CallByName Dict.98 Dict.508 Dict.990; + let Dict.989 : U64 = 8i64; + let Dict.988 : U64 = CallByName Num.75 Dict.512 Dict.989; + let Dict.987 : U64 = CallByName Num.51 Dict.988 Dict.513; + let Dict.986 : U64 = CallByName Dict.98 Dict.508 Dict.987; + dec Dict.508; + let Dict.984 : {U64, U64, U64} = Struct {Dict.985, Dict.986, Dict.511}; + ret Dict.984; else - jump Dict.980 Dict.510 Dict.507 Dict.512 Dict.511; + jump Dict.981 Dict.511 Dict.508 Dict.513 Dict.512; in inc #Derived_gen.1; - jump Dict.980 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3; + jump Dict.981 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3; procedure Dict.92 (): - let Dict.917 : U64 = 11562461410679940143i64; - ret Dict.917; + let Dict.918 : U64 = 11562461410679940143i64; + ret Dict.918; procedure Dict.93 (): - let Dict.913 : U64 = 16646288086500911323i64; - ret Dict.913; + let Dict.914 : U64 = 16646288086500911323i64; + ret Dict.914; procedure Dict.94 (): - let Dict.1026 : U64 = 10285213230658275043i64; - ret Dict.1026; + let Dict.1027 : U64 = 10285213230658275043i64; + ret Dict.1027; procedure Dict.95 (): - let Dict.1016 : U64 = 6384245875588680899i64; - ret Dict.1016; - -procedure Dict.96 (Dict.513, Dict.514): - let Dict.905 : {U64, U64} = CallByName Dict.97 Dict.513 Dict.514; - let Dict.515 : U64 = StructAtIndex 0 Dict.905; - let Dict.516 : U64 = StructAtIndex 1 Dict.905; - let Dict.904 : U64 = CallByName Num.70 Dict.515 Dict.516; - ret Dict.904; - -procedure Dict.97 (Dict.517, Dict.518): - let Dict.909 : U128 = CallByName Num.135 Dict.517; + let Dict.1017 : U64 = 6384245875588680899i64; + ret Dict.1017; + +procedure Dict.96 (Dict.514, Dict.515): + let Dict.906 : {U64, U64} = CallByName Dict.97 Dict.514 Dict.515; + let Dict.516 : U64 = StructAtIndex 0 Dict.906; + let Dict.517 : U64 = StructAtIndex 1 Dict.906; + let Dict.905 : U64 = CallByName Num.70 Dict.516 Dict.517; + ret Dict.905; + +procedure Dict.97 (Dict.518, Dict.519): let Dict.910 : U128 = CallByName Num.135 Dict.518; - let Dict.519 : U128 = CallByName Num.78 Dict.909 Dict.910; - let Dict.520 : U64 = CallByName Num.133 Dict.519; - let Dict.908 : U8 = 64i64; - let Dict.907 : U128 = CallByName Num.74 Dict.519 Dict.908; - let Dict.521 : U64 = CallByName Num.133 Dict.907; - let Dict.906 : {U64, U64} = Struct {Dict.520, Dict.521}; - ret Dict.906; - -procedure Dict.98 (Dict.522, Dict.523): - let Dict.971 : U8 = CallByName Dict.22 Dict.522 Dict.523; - let Dict.524 : U64 = CallByName Num.133 Dict.971; - let Dict.970 : U64 = 1i64; - let Dict.969 : U64 = CallByName Num.51 Dict.523 Dict.970; - let Dict.968 : U8 = CallByName Dict.22 Dict.522 Dict.969; - let Dict.525 : U64 = CallByName Num.133 Dict.968; - let Dict.967 : U64 = 2i64; - let Dict.966 : U64 = CallByName Num.51 Dict.523 Dict.967; - let Dict.965 : U8 = CallByName Dict.22 Dict.522 Dict.966; - let Dict.526 : U64 = CallByName Num.133 Dict.965; - let Dict.964 : U64 = 3i64; - let Dict.963 : U64 = CallByName Num.51 Dict.523 Dict.964; - let Dict.962 : U8 = CallByName Dict.22 Dict.522 Dict.963; - let Dict.527 : U64 = CallByName Num.133 Dict.962; - let Dict.961 : U64 = 4i64; - let Dict.960 : U64 = CallByName Num.51 Dict.523 Dict.961; - let Dict.959 : U8 = CallByName Dict.22 Dict.522 Dict.960; - let Dict.528 : U64 = CallByName Num.133 Dict.959; - let Dict.958 : U64 = 5i64; - let Dict.957 : U64 = CallByName Num.51 Dict.523 Dict.958; - let Dict.956 : U8 = CallByName Dict.22 Dict.522 Dict.957; - let Dict.529 : U64 = CallByName Num.133 Dict.956; - let Dict.955 : U64 = 6i64; - let Dict.954 : U64 = CallByName Num.51 Dict.523 Dict.955; - let Dict.953 : U8 = CallByName Dict.22 Dict.522 Dict.954; - let Dict.530 : U64 = CallByName Num.133 Dict.953; - let Dict.952 : U64 = 7i64; - let Dict.950 : U64 = CallByName Num.51 Dict.523 Dict.952; - let Dict.949 : U8 = CallByName Dict.22 Dict.522 Dict.950; - let Dict.531 : U64 = CallByName Num.133 Dict.949; - let Dict.948 : U8 = 8i64; - let Dict.947 : U64 = CallByName Num.72 Dict.525 Dict.948; - let Dict.532 : U64 = CallByName Num.71 Dict.524 Dict.947; - let Dict.946 : U8 = 16i64; - let Dict.943 : U64 = CallByName Num.72 Dict.526 Dict.946; - let Dict.945 : U8 = 24i64; - let Dict.944 : U64 = CallByName Num.72 Dict.527 Dict.945; - let Dict.533 : U64 = CallByName Num.71 Dict.943 Dict.944; - let Dict.942 : U8 = 32i64; - let Dict.939 : U64 = CallByName Num.72 Dict.528 Dict.942; - let Dict.941 : U8 = 40i64; - let Dict.940 : U64 = CallByName Num.72 Dict.529 Dict.941; - let Dict.534 : U64 = CallByName Num.71 Dict.939 Dict.940; - let Dict.938 : U8 = 48i64; - let Dict.935 : U64 = CallByName Num.72 Dict.530 Dict.938; - let Dict.937 : U8 = 56i64; - let Dict.936 : U64 = CallByName Num.72 Dict.531 Dict.937; - let Dict.535 : U64 = CallByName Num.71 Dict.935 Dict.936; - let Dict.933 : U64 = CallByName Num.71 Dict.532 Dict.533; - let Dict.934 : U64 = CallByName Num.71 Dict.534 Dict.535; - let Dict.932 : U64 = CallByName Num.71 Dict.933 Dict.934; - ret Dict.932; - -procedure Dict.99 (Dict.536, Dict.537): - let Dict.1083 : U8 = CallByName Dict.22 Dict.536 Dict.537; - let Dict.538 : U64 = CallByName Num.133 Dict.1083; - let Dict.1082 : U64 = 1i64; - let Dict.1081 : U64 = CallByName Num.51 Dict.537 Dict.1082; - let Dict.1080 : U8 = CallByName Dict.22 Dict.536 Dict.1081; - let Dict.539 : U64 = CallByName Num.133 Dict.1080; - let Dict.1079 : U64 = 2i64; - let Dict.1078 : U64 = CallByName Num.51 Dict.537 Dict.1079; - let Dict.1077 : U8 = CallByName Dict.22 Dict.536 Dict.1078; - let Dict.540 : U64 = CallByName Num.133 Dict.1077; - let Dict.1076 : U64 = 3i64; - let Dict.1075 : U64 = CallByName Num.51 Dict.537 Dict.1076; - let Dict.1074 : U8 = CallByName Dict.22 Dict.536 Dict.1075; - let Dict.541 : U64 = CallByName Num.133 Dict.1074; - let Dict.1073 : U8 = 8i64; - let Dict.1072 : U64 = CallByName Num.72 Dict.539 Dict.1073; - let Dict.542 : U64 = CallByName Num.71 Dict.538 Dict.1072; - let Dict.1071 : U8 = 16i64; - let Dict.1068 : U64 = CallByName Num.72 Dict.540 Dict.1071; - let Dict.1070 : U8 = 24i64; - let Dict.1069 : U64 = CallByName Num.72 Dict.541 Dict.1070; - let Dict.543 : U64 = CallByName Num.71 Dict.1068 Dict.1069; - let Dict.1067 : U64 = CallByName Num.71 Dict.542 Dict.543; - ret Dict.1067; + let Dict.911 : U128 = CallByName Num.135 Dict.519; + let Dict.520 : U128 = CallByName Num.78 Dict.910 Dict.911; + let Dict.521 : U64 = CallByName Num.133 Dict.520; + let Dict.909 : U8 = 64i64; + let Dict.908 : U128 = CallByName Num.74 Dict.520 Dict.909; + let Dict.522 : U64 = CallByName Num.133 Dict.908; + let Dict.907 : {U64, U64} = Struct {Dict.521, Dict.522}; + ret Dict.907; + +procedure Dict.98 (Dict.523, Dict.524): + let Dict.972 : U8 = CallByName Dict.22 Dict.523 Dict.524; + let Dict.525 : U64 = CallByName Num.133 Dict.972; + let Dict.971 : U64 = 1i64; + let Dict.970 : U64 = CallByName Num.51 Dict.524 Dict.971; + let Dict.969 : U8 = CallByName Dict.22 Dict.523 Dict.970; + let Dict.526 : U64 = CallByName Num.133 Dict.969; + let Dict.968 : U64 = 2i64; + let Dict.967 : U64 = CallByName Num.51 Dict.524 Dict.968; + let Dict.966 : U8 = CallByName Dict.22 Dict.523 Dict.967; + let Dict.527 : U64 = CallByName Num.133 Dict.966; + let Dict.965 : U64 = 3i64; + let Dict.964 : U64 = CallByName Num.51 Dict.524 Dict.965; + let Dict.963 : U8 = CallByName Dict.22 Dict.523 Dict.964; + let Dict.528 : U64 = CallByName Num.133 Dict.963; + let Dict.962 : U64 = 4i64; + let Dict.961 : U64 = CallByName Num.51 Dict.524 Dict.962; + let Dict.960 : U8 = CallByName Dict.22 Dict.523 Dict.961; + let Dict.529 : U64 = CallByName Num.133 Dict.960; + let Dict.959 : U64 = 5i64; + let Dict.958 : U64 = CallByName Num.51 Dict.524 Dict.959; + let Dict.957 : U8 = CallByName Dict.22 Dict.523 Dict.958; + let Dict.530 : U64 = CallByName Num.133 Dict.957; + let Dict.956 : U64 = 6i64; + let Dict.955 : U64 = CallByName Num.51 Dict.524 Dict.956; + let Dict.954 : U8 = CallByName Dict.22 Dict.523 Dict.955; + let Dict.531 : U64 = CallByName Num.133 Dict.954; + let Dict.953 : U64 = 7i64; + let Dict.951 : U64 = CallByName Num.51 Dict.524 Dict.953; + let Dict.950 : U8 = CallByName Dict.22 Dict.523 Dict.951; + let Dict.532 : U64 = CallByName Num.133 Dict.950; + let Dict.949 : U8 = 8i64; + let Dict.948 : U64 = CallByName Num.72 Dict.526 Dict.949; + let Dict.533 : U64 = CallByName Num.71 Dict.525 Dict.948; + let Dict.947 : U8 = 16i64; + let Dict.944 : U64 = CallByName Num.72 Dict.527 Dict.947; + let Dict.946 : U8 = 24i64; + let Dict.945 : U64 = CallByName Num.72 Dict.528 Dict.946; + let Dict.534 : U64 = CallByName Num.71 Dict.944 Dict.945; + let Dict.943 : U8 = 32i64; + let Dict.940 : U64 = CallByName Num.72 Dict.529 Dict.943; + let Dict.942 : U8 = 40i64; + let Dict.941 : U64 = CallByName Num.72 Dict.530 Dict.942; + let Dict.535 : U64 = CallByName Num.71 Dict.940 Dict.941; + let Dict.939 : U8 = 48i64; + let Dict.936 : U64 = CallByName Num.72 Dict.531 Dict.939; + let Dict.938 : U8 = 56i64; + let Dict.937 : U64 = CallByName Num.72 Dict.532 Dict.938; + let Dict.536 : U64 = CallByName Num.71 Dict.936 Dict.937; + let Dict.934 : U64 = CallByName Num.71 Dict.533 Dict.534; + let Dict.935 : U64 = CallByName Num.71 Dict.535 Dict.536; + let Dict.933 : U64 = CallByName Num.71 Dict.934 Dict.935; + ret Dict.933; + +procedure Dict.99 (Dict.537, Dict.538): + let Dict.1084 : U8 = CallByName Dict.22 Dict.537 Dict.538; + let Dict.539 : U64 = CallByName Num.133 Dict.1084; + let Dict.1083 : U64 = 1i64; + let Dict.1082 : U64 = CallByName Num.51 Dict.538 Dict.1083; + let Dict.1081 : U8 = CallByName Dict.22 Dict.537 Dict.1082; + let Dict.540 : U64 = CallByName Num.133 Dict.1081; + let Dict.1080 : U64 = 2i64; + let Dict.1079 : U64 = CallByName Num.51 Dict.538 Dict.1080; + let Dict.1078 : U8 = CallByName Dict.22 Dict.537 Dict.1079; + let Dict.541 : U64 = CallByName Num.133 Dict.1078; + let Dict.1077 : U64 = 3i64; + let Dict.1076 : U64 = CallByName Num.51 Dict.538 Dict.1077; + let Dict.1075 : U8 = CallByName Dict.22 Dict.537 Dict.1076; + let Dict.542 : U64 = CallByName Num.133 Dict.1075; + let Dict.1074 : U8 = 8i64; + let Dict.1073 : U64 = CallByName Num.72 Dict.540 Dict.1074; + let Dict.543 : U64 = CallByName Num.71 Dict.539 Dict.1073; + let Dict.1072 : U8 = 16i64; + let Dict.1069 : U64 = CallByName Num.72 Dict.541 Dict.1072; + let Dict.1071 : U8 = 24i64; + let Dict.1070 : U64 = CallByName Num.72 Dict.542 Dict.1071; + let Dict.544 : U64 = CallByName Num.71 Dict.1069 Dict.1070; + let Dict.1068 : U64 = CallByName Num.71 Dict.543 Dict.544; + ret Dict.1068; procedure Hash.19 (Hash.42, Hash.43): let Hash.75 : List U8 = CallByName Str.12 Hash.43; @@ -1045,7 +1045,7 @@ procedure List.96 (#Derived_gen.56, #Derived_gen.57, #Derived_gen.58, #Derived_g if List.669 then let List.673 : {Str, I64} = CallByName List.66 List.178 List.181; inc List.673; - let List.183 : List {U32, U32} = CallByName Dict.405 List.179 List.673 List.181 List.180; + let List.183 : List {U32, U32} = CallByName Dict.406 List.179 List.673 List.181 List.180; let List.672 : U64 = 1i64; let List.671 : U64 = CallByName Num.51 List.181 List.672; jump List.667 List.178 List.183 List.180 List.671 List.182; From 3eadc03e28a9e05f5e284c598e86f9a9827d4270 Mon Sep 17 00:00:00 2001 From: Agus Zubiaga Date: Fri, 20 Sep 2024 16:19:56 -0300 Subject: [PATCH 17/22] Add failing test for multiline params --- crates/cli/tests/cli_run.rs | 19 +++++++++++++++++++ .../tests/module_params/MultilineParams.roc | 8 ++++++++ .../tests/module_params/multiline_params.roc | 11 +++++++++++ crates/compiler/can/src/pattern.rs | 5 ++++- 4 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 crates/cli/tests/module_params/MultilineParams.roc create mode 100644 crates/cli/tests/module_params/multiline_params.roc diff --git a/crates/cli/tests/cli_run.rs b/crates/cli/tests/cli_run.rs index 1544a888873..a27aa457ab0 100644 --- a/crates/cli/tests/cli_run.rs +++ b/crates/cli/tests/cli_run.rs @@ -922,6 +922,25 @@ mod cli_run { ); } + #[test] + #[cfg_attr(windows, ignore)] + fn module_params_multiline_pattern() { + test_roc_app( + "crates/cli/tests/module_params", + "multiline_params.roc", + &[], + &[], + &[], + indoc!( + r#" + hi + "# + ), + UseValgrind::No, + TestCliCommands::Dev, + ); + } + #[test] #[cfg_attr(windows, ignore)] fn transitive_expects() { diff --git a/crates/cli/tests/module_params/MultilineParams.roc b/crates/cli/tests/module_params/MultilineParams.roc new file mode 100644 index 00000000000..631b88473be --- /dev/null +++ b/crates/cli/tests/module_params/MultilineParams.roc @@ -0,0 +1,8 @@ +module { + sendHttpReq, + getEnvVar +} -> [hi] + +hi : Str +hi = + "hi" diff --git a/crates/cli/tests/module_params/multiline_params.roc b/crates/cli/tests/module_params/multiline_params.roc new file mode 100644 index 00000000000..531721c9258 --- /dev/null +++ b/crates/cli/tests/module_params/multiline_params.roc @@ -0,0 +1,11 @@ +app [main] { + pf: platform "../fixtures/multi-dep-str/platform/main.roc", +} + +import MultilineParams { + sendHttpReq: \_ -> crash "todo", + getEnvVar: \_ -> crash "todo", +} + +main = + MultilineParams.hi \ No newline at end of file diff --git a/crates/compiler/can/src/pattern.rs b/crates/compiler/can/src/pattern.rs index ddd6efda308..ffd097e3ae8 100644 --- a/crates/compiler/can/src/pattern.rs +++ b/crates/compiler/can/src/pattern.rs @@ -914,7 +914,10 @@ pub fn canonicalize_record_destructs<'a>( } }; } - _ => unreachable!("Any other pattern should have given a parse error"), + _ => unreachable!( + "Any other pattern should have given a parse error: {:?}", + loc_pattern.value + ), } } From 3f9e957c9cba8fa5e2b6c15b6926dedabd8434c4 Mon Sep 17 00:00:00 2001 From: Agus Zubiaga Date: Fri, 20 Sep 2024 16:30:59 -0300 Subject: [PATCH 18/22] Extract record destructure desugaring into its own fn --- crates/compiler/can/src/desugar.rs | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/crates/compiler/can/src/desugar.rs b/crates/compiler/can/src/desugar.rs index 3f4872366e4..65599c21783 100644 --- a/crates/compiler/can/src/desugar.rs +++ b/crates/compiler/can/src/desugar.rs @@ -1226,17 +1226,7 @@ fn desugar_pattern<'a>(env: &mut Env<'a>, scope: &mut Scope, pattern: Pattern<'a Apply(tag, desugared_arg_patterns.into_bump_slice()) } RecordDestructure(field_patterns) => { - let mut allocated = Vec::with_capacity_in(field_patterns.len(), env.arena); - for field_pattern in field_patterns.iter() { - let value = desugar_pattern(env, scope, field_pattern.value); - allocated.push(Loc { - value, - region: field_pattern.region, - }); - } - let field_patterns = field_patterns.replace_items(allocated.into_bump_slice()); - - RecordDestructure(field_patterns) + RecordDestructure(desugar_record_destructures(env, scope, field_patterns)) } RequiredField(name, field_pattern) => { RequiredField(name, desugar_loc_pattern(env, scope, field_pattern)) @@ -1274,6 +1264,23 @@ fn desugar_pattern<'a>(env: &mut Env<'a>, scope: &mut Scope, pattern: Pattern<'a } } +pub fn desugar_record_destructures<'a>( + env: &mut Env<'a>, + scope: &mut Scope, + field_patterns: Collection<'a, Loc>>, +) -> Collection<'a, Loc>> { + let mut allocated = Vec::with_capacity_in(field_patterns.len(), env.arena); + for field_pattern in field_patterns.iter() { + let value = desugar_pattern(env, scope, field_pattern.value); + allocated.push(Loc { + value, + region: field_pattern.region, + }); + } + + field_patterns.replace_items(allocated.into_bump_slice()) +} + /// Desugars a `dbg expr` expression into a statement block that prints and returns the /// value produced by `expr`. Essentially: /// ( From 5054c9990edb08982eb99a7aea4e8525d36bf6e3 Mon Sep 17 00:00:00 2001 From: Agus Zubiaga Date: Fri, 20 Sep 2024 16:35:18 -0300 Subject: [PATCH 19/22] Desugar module param patterns before canonicalizing --- crates/compiler/can/src/module.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/compiler/can/src/module.rs b/crates/compiler/can/src/module.rs index 14dc2f827b8..3a45b6ba912 100644 --- a/crates/compiler/can/src/module.rs +++ b/crates/compiler/can/src/module.rs @@ -3,6 +3,7 @@ use std::path::Path; use crate::abilities::{AbilitiesStore, ImplKey, PendingAbilitiesStore, ResolvedImpl}; use crate::annotation::{canonicalize_annotation, AnnotationFor}; use crate::def::{canonicalize_defs, report_unused_imports, Def}; +use crate::desugar::desugar_record_destructures; use crate::env::Env; use crate::expr::{ ClosureData, DbgLookup, Declarations, ExpectLookup, Expr, Output, PendingDerives, @@ -326,13 +327,16 @@ pub fn canonicalize_module_defs<'a>( before_arrow: _, after_arrow: _, }| { + let desugared_patterns = + desugar_record_destructures(&mut env, &mut scope, pattern.value); + let (destructs, _) = canonicalize_record_destructs( &mut env, var_store, &mut scope, &mut output, PatternType::ModuleParams, - &pattern.value, + &desugared_patterns, pattern.region, PermitShadows(false), ); From 2da08be8efbd881bdc3d86e15e0514e5b2ba952b Mon Sep 17 00:00:00 2001 From: Sam Mohr Date: Sat, 21 Sep 2024 04:44:44 -0700 Subject: [PATCH 20/22] Remove old record builder syntax --- crates/compiler/can/src/desugar.rs | 138 +-- crates/compiler/can/src/expr.rs | 44 +- crates/compiler/can/tests/test_can.rs | 188 +--- crates/compiler/fmt/src/annotation.rs | 97 +- crates/compiler/fmt/src/expr.rs | 135 +-- crates/compiler/load/tests/test_reporting.rs | 181 ---- crates/compiler/module/src/called_via.rs | 4 - crates/compiler/parse/src/ast.rs | 98 +- crates/compiler/parse/src/expr.rs | 192 +--- crates/compiler/parse/src/module.rs | 905 ------------------ crates/compiler/parse/src/normalize.rs | 44 +- crates/compiler/parse/src/parser.rs | 3 - crates/compiler/parse/src/type_annotation.rs | 7 +- crates/compiler/problem/src/can.rs | 7 - crates/compiler/test_syntax/tests/test_fmt.rs | 166 +--- crates/language_server/src/analysis/tokens.rs | 26 +- crates/reporting/src/error/canonicalize.rs | 26 - crates/reporting/src/error/parse.rs | 57 -- crates/reporting/src/error/type.rs | 17 +- www/content/tutorial.md | 2 - 20 files changed, 57 insertions(+), 2280 deletions(-) delete mode 100644 crates/compiler/parse/src/module.rs diff --git a/crates/compiler/can/src/desugar.rs b/crates/compiler/can/src/desugar.rs index 3f4872366e4..3ae037c4b05 100644 --- a/crates/compiler/can/src/desugar.rs +++ b/crates/compiler/can/src/desugar.rs @@ -11,8 +11,8 @@ use roc_module::called_via::{BinOp, CalledVia}; use roc_module::ident::ModuleName; use roc_parse::ast::Expr::{self, *}; use roc_parse::ast::{ - AssignedField, Collection, Defs, ModuleImportParams, OldRecordBuilderField, Pattern, - StrLiteral, StrSegment, TypeAnnotation, ValueDef, WhenBranch, + AssignedField, Collection, Defs, ModuleImportParams, Pattern, StrLiteral, StrSegment, + TypeAnnotation, ValueDef, WhenBranch, }; use roc_problem::can::Problem; use roc_region::all::{Loc, Region}; @@ -321,8 +321,6 @@ pub fn desugar_expr<'a>( | MalformedClosure | MalformedSuffixed(..) | PrecedenceConflict { .. } - | MultipleOldRecordBuilders(_) - | UnappliedOldRecordBuilder(_) | EmptyRecordBuilder(_) | SingleFieldRecordBuilder(_) | OptionalFieldInRecordBuilder { .. } @@ -555,10 +553,6 @@ pub fn desugar_expr<'a>( } } } - OldRecordBuilder(_) => env.arena.alloc(Loc { - value: UnappliedOldRecordBuilder(loc_expr), - region: loc_expr.region, - }), RecordBuilder { mapper, fields } => { // NOTE the `mapper` is always a `Var { .. }`, we only desugar it to get rid of // any spaces before/after @@ -853,25 +847,11 @@ pub fn desugar_expr<'a>( } Apply(loc_fn, loc_args, called_via) => { let mut desugared_args = Vec::with_capacity_in(loc_args.len(), env.arena); - let mut builder_apply_exprs = None; for loc_arg in loc_args.iter() { let mut current = loc_arg.value; let arg = loop { match current { - OldRecordBuilder(fields) => { - if builder_apply_exprs.is_some() { - return env.arena.alloc(Loc { - value: MultipleOldRecordBuilders(loc_expr), - region: loc_expr.region, - }); - } - - let builder_arg = old_record_builder_arg(env, loc_arg.region, fields); - builder_apply_exprs = Some(builder_arg.apply_exprs); - - break builder_arg.closure; - } SpaceBefore(expr, _) | SpaceAfter(expr, _) => { current = *expr; } @@ -884,33 +864,14 @@ pub fn desugar_expr<'a>( let desugared_args = desugared_args.into_bump_slice(); - let mut apply: &Loc = env.arena.alloc(Loc { + env.arena.alloc(Loc { value: Apply( desugar_expr(env, scope, loc_fn), desugared_args, *called_via, ), region: loc_expr.region, - }); - - match builder_apply_exprs { - None => {} - - Some(apply_exprs) => { - for expr in apply_exprs { - let desugared_expr = desugar_expr(env, scope, expr); - - let args = std::slice::from_ref(env.arena.alloc(apply)); - - apply = env.arena.alloc(Loc { - value: Apply(desugared_expr, args, CalledVia::OldRecordBuilder), - region: loc_expr.region, - }); - } - } - } - - apply + }) } When(loc_cond_expr, branches) => { let loc_desugared_cond = &*env.arena.alloc(desugar_expr(env, scope, loc_cond_expr)); @@ -1383,97 +1344,6 @@ fn desugar_dbg_stmt<'a>( )) } -struct OldRecordBuilderArg<'a> { - closure: &'a Loc>, - apply_exprs: Vec<'a, &'a Loc>>, -} - -fn old_record_builder_arg<'a>( - env: &mut Env<'a>, - region: Region, - fields: Collection<'a, Loc>>, -) -> OldRecordBuilderArg<'a> { - let mut record_fields = Vec::with_capacity_in(fields.len(), env.arena); - let mut apply_exprs = Vec::with_capacity_in(fields.len(), env.arena); - let mut apply_field_names = Vec::with_capacity_in(fields.len(), env.arena); - - // Build the record that the closure will return and gather apply expressions - - for field in fields.iter() { - let mut current = field.value; - - let new_field = loop { - match current { - OldRecordBuilderField::Value(label, spaces, expr) => { - break AssignedField::RequiredValue(label, spaces, expr) - } - OldRecordBuilderField::ApplyValue(label, _, _, expr) => { - apply_field_names.push(label); - apply_exprs.push(expr); - - let var = env.arena.alloc(Loc { - region: label.region, - value: Expr::Var { - module_name: "", - ident: env.arena.alloc("#".to_owned() + label.value), - }, - }); - - break AssignedField::RequiredValue(label, &[], var); - } - OldRecordBuilderField::LabelOnly(label) => break AssignedField::LabelOnly(label), - OldRecordBuilderField::SpaceBefore(sub_field, _) => { - current = *sub_field; - } - OldRecordBuilderField::SpaceAfter(sub_field, _) => { - current = *sub_field; - } - OldRecordBuilderField::Malformed(malformed) => { - break AssignedField::Malformed(malformed) - } - } - }; - - record_fields.push(Loc { - value: new_field, - region: field.region, - }); - } - - let record_fields = fields.replace_items(record_fields.into_bump_slice()); - - let mut body = env.arena.alloc(Loc { - value: Record(record_fields), - region, - }); - - // Construct the builder's closure - // - // { x: #x, y: #y, z: 3 } - // \#y -> { x: #x, y: #y, z: 3 } - // \#x -> \#y -> { x: #x, y: #y, z: 3 } - - for label in apply_field_names.iter().rev() { - let name = env.arena.alloc("#".to_owned() + label.value); - let ident = roc_parse::ast::Pattern::Identifier { ident: name }; - - let arg_pattern = env.arena.alloc(Loc { - value: ident, - region: label.region, - }); - - body = env.arena.alloc(Loc { - value: Closure(std::slice::from_ref(arg_pattern), body), - region, - }); - } - - OldRecordBuilderArg { - closure: body, - apply_exprs, - } -} - // TODO move this desugaring to canonicalization, so we can use Symbols instead of strings #[inline(always)] fn binop_to_function(binop: BinOp) -> (&'static str, &'static str) { diff --git a/crates/compiler/can/src/expr.rs b/crates/compiler/can/src/expr.rs index 9955a5a833a..18f295bb0fe 100644 --- a/crates/compiler/can/src/expr.rs +++ b/crates/compiler/can/src/expr.rs @@ -1013,11 +1013,8 @@ pub fn canonicalize_expr<'a>( can_defs_with_return(env, var_store, inner_scope, env.arena.alloc(defs), loc_ret) }) } - ast::Expr::OldRecordBuilder(_) => { - internal_error!("Old record builder should have been desugared by now") - } ast::Expr::RecordBuilder { .. } => { - internal_error!("New record builder should have been desugared by now") + internal_error!("Record builder should have been desugared by now") } ast::Expr::Backpassing(_, _, _) => { internal_error!("Backpassing should have been desugared by now") @@ -1356,22 +1353,6 @@ pub fn canonicalize_expr<'a>( use roc_problem::can::RuntimeError::*; (RuntimeError(MalformedSuffixed(region)), Output::default()) } - ast::Expr::MultipleOldRecordBuilders(sub_expr) => { - use roc_problem::can::RuntimeError::*; - - let problem = MultipleOldRecordBuilders(sub_expr.region); - env.problem(Problem::RuntimeError(problem.clone())); - - (RuntimeError(problem), Output::default()) - } - ast::Expr::UnappliedOldRecordBuilder(sub_expr) => { - use roc_problem::can::RuntimeError::*; - - let problem = UnappliedOldRecordBuilder(sub_expr.region); - env.problem(Problem::RuntimeError(problem.clone())); - - (RuntimeError(problem), Output::default()) - } ast::Expr::EmptyRecordBuilder(sub_expr) => { use roc_problem::can::RuntimeError::*; @@ -2552,8 +2533,6 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool { .iter() .all(|loc_field| is_valid_interpolation(&loc_field.value)), ast::Expr::MalformedSuffixed(loc_expr) - | ast::Expr::MultipleOldRecordBuilders(loc_expr) - | ast::Expr::UnappliedOldRecordBuilder(loc_expr) | ast::Expr::EmptyRecordBuilder(loc_expr) | ast::Expr::SingleFieldRecordBuilder(loc_expr) | ast::Expr::OptionalFieldInRecordBuilder(_, loc_expr) @@ -2603,27 +2582,6 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool { | ast::AssignedField::SpaceAfter(_, _) => false, }) } - ast::Expr::OldRecordBuilder(fields) => { - fields.iter().all(|loc_field| match loc_field.value { - ast::OldRecordBuilderField::Value(_label, comments, loc_expr) => { - comments.is_empty() && is_valid_interpolation(&loc_expr.value) - } - ast::OldRecordBuilderField::ApplyValue( - _label, - comments_before, - comments_after, - loc_expr, - ) => { - comments_before.is_empty() - && comments_after.is_empty() - && is_valid_interpolation(&loc_expr.value) - } - ast::OldRecordBuilderField::Malformed(_) - | ast::OldRecordBuilderField::LabelOnly(_) => true, - ast::OldRecordBuilderField::SpaceBefore(_, _) - | ast::OldRecordBuilderField::SpaceAfter(_, _) => false, - }) - } ast::Expr::RecordBuilder { mapper, fields } => { is_valid_interpolation(&mapper.value) && fields.iter().all(|loc_field| match loc_field.value { diff --git a/crates/compiler/can/tests/test_can.rs b/crates/compiler/can/tests/test_can.rs index 724d1f24b1a..8ecc016a426 100644 --- a/crates/compiler/can/tests/test_can.rs +++ b/crates/compiler/can/tests/test_can.rs @@ -19,7 +19,6 @@ mod test_can { use roc_can::expr::{ClosureData, IntValue, Recursive}; use roc_can::pattern::Pattern; use roc_module::called_via::CalledVia; - use roc_module::symbol::Symbol; use roc_problem::can::{CycleEntry, FloatErrorKind, IntErrorKind, Problem, RuntimeError}; use roc_region::all::{Loc, Position, Region}; use roc_types::subs::Variable; @@ -653,101 +652,6 @@ mod test_can { } // RECORD BUILDERS - #[test] - fn old_record_builder_desugar() { - let src = indoc!( - r#" - succeed = \_ -> crash "succeed" - apply = \_ -> crash "get" - - d = 3 - - succeed { - a: 1, - b: <- apply "b", - c: <- apply "c", - d - } - "# - ); - let arena = Bump::new(); - let out = can_expr_with(&arena, test_home(), src); - - assert_eq!(out.problems.len(), 0); - - // Assert that we desugar to: - // - // (apply "c") ((apply "b") (succeed \b -> \c -> { a: 1, b, c, d })) - - // (apply "c") .. - let (apply_c, c_to_b) = simplify_curried_call(&out.loc_expr.value); - assert_apply_call(apply_c, "c", &out.interns); - - // (apply "b") .. - let (apply_b, b_to_succeed) = simplify_curried_call(c_to_b); - assert_apply_call(apply_b, "b", &out.interns); - - // (succeed ..) - let (succeed, b_closure) = simplify_curried_call(b_to_succeed); - - match succeed { - Var(sym, _) => assert_eq!(sym.as_str(&out.interns), "succeed"), - _ => panic!("Not calling succeed: {:?}", succeed), - } - - // \b -> .. - let (b_sym, c_closure) = simplify_builder_closure(b_closure); - - // \c -> .. - let (c_sym, c_body) = simplify_builder_closure(c_closure); - - // { a: 1, b, c, d } - match c_body { - Record { fields, .. } => { - match get_field_expr(fields, "a") { - Num(_, num_str, _, _) => { - assert_eq!(num_str.to_string(), "1"); - } - expr => panic!("a is not a Num: {:?}", expr), - } - - assert_eq!(get_field_var_sym(fields, "b"), b_sym); - assert_eq!(get_field_var_sym(fields, "c"), c_sym); - assert_eq!(get_field_var_sym(fields, "d").as_str(&out.interns), "d"); - } - _ => panic!("Closure body wasn't a Record: {:?}", c_body), - } - } - - fn simplify_curried_call(expr: &Expr) -> (&Expr, &Expr) { - match expr { - LetNonRec(_, loc_expr) => simplify_curried_call(&loc_expr.value), - Call(fun, args, _) => (&fun.1.value, &args[0].1.value), - _ => panic!("Final Expr is not a Call: {:?}", expr), - } - } - - fn assert_apply_call(expr: &Expr, expected: &str, interns: &roc_module::symbol::Interns) { - match simplify_curried_call(expr) { - (Var(sym, _), Str(val)) => { - assert_eq!(sym.as_str(interns), "apply"); - assert_eq!(val.to_string(), expected); - } - call => panic!("Not a valid (get {}) call: {:?}", expected, call), - }; - } - - fn simplify_builder_closure(expr: &Expr) -> (Symbol, &Expr) { - use roc_can::pattern::Pattern::*; - - match expr { - Closure(closure) => match &closure.arguments[0].2.value { - Identifier(sym) => (*sym, &closure.loc_body.value), - pattern => panic!("Not an identifier pattern: {:?}", pattern), - }, - _ => panic!("Not a closure: {:?}", expr), - } - } fn get_field_expr<'a>( fields: &'a roc_collections::SendMap, @@ -769,97 +673,7 @@ mod test_can { } #[test] - fn old_record_builder_field_names_do_not_shadow() { - let src = indoc!( - r#" - succeed = \_ -> crash "succeed" - parse = \_ -> crash "parse" - - number = "42" - - succeed { - number: <- parse number, - raw: number, - } - "# - ); - let arena = Bump::new(); - let out = can_expr_with(&arena, test_home(), src); - - assert_eq!(out.problems.len(), 0); - - let (_, number_to_succeed) = simplify_curried_call(&out.loc_expr.value); - let (_, number_closure) = simplify_curried_call(number_to_succeed); - let (apply_number_sym, record) = simplify_builder_closure(number_closure); - - match record { - Record { fields, .. } => { - assert_eq!(get_field_var_sym(fields, "number"), apply_number_sym); - - match get_field_expr(fields, "raw") { - Var(number_sym, _) => { - assert_ne!(number_sym.ident_id(), apply_number_sym.ident_id()); - assert_eq!(number_sym.as_str(&out.interns), "number") - } - expr => panic!("a is not a Num: {:?}", expr), - } - } - _ => panic!("Closure body wasn't a Record: {:?}", record), - } - } - - #[test] - fn multiple_old_record_builders_error() { - let src = indoc!( - r#" - succeed - { a: <- apply "a" } - { b: <- apply "b" } - "# - ); - let arena = Bump::new(); - let CanExprOut { - problems, loc_expr, .. - } = can_expr_with(&arena, test_home(), src); - - assert_eq!(problems.len(), 1); - assert!(problems.iter().all(|problem| matches!( - problem, - Problem::RuntimeError(roc_problem::can::RuntimeError::MultipleOldRecordBuilders { .. }) - ))); - - assert!(matches!( - loc_expr.value, - Expr::RuntimeError(roc_problem::can::RuntimeError::MultipleOldRecordBuilders { .. }) - )); - } - - #[test] - fn hanging_old_record_builder() { - let src = indoc!( - r#" - { a: <- apply "a" } - "# - ); - let arena = Bump::new(); - let CanExprOut { - problems, loc_expr, .. - } = can_expr_with(&arena, test_home(), src); - - assert_eq!(problems.len(), 1); - assert!(problems.iter().all(|problem| matches!( - problem, - Problem::RuntimeError(roc_problem::can::RuntimeError::UnappliedOldRecordBuilder { .. }) - ))); - - assert!(matches!( - loc_expr.value, - Expr::RuntimeError(roc_problem::can::RuntimeError::UnappliedOldRecordBuilder { .. }) - )); - } - - #[test] - fn new_record_builder_desugar() { + fn record_builder_desugar() { let src = indoc!( r#" map2 = \a, b, combine -> combine a b diff --git a/crates/compiler/fmt/src/annotation.rs b/crates/compiler/fmt/src/annotation.rs index 3e6b18a158c..16efa21795e 100644 --- a/crates/compiler/fmt/src/annotation.rs +++ b/crates/compiler/fmt/src/annotation.rs @@ -5,7 +5,7 @@ use crate::{ }; use roc_parse::ast::{ AbilityImpls, AssignedField, Collection, Expr, ExtractSpaces, ImplementsAbilities, - ImplementsAbility, ImplementsClause, OldRecordBuilderField, Tag, TypeAnnotation, TypeHeader, + ImplementsAbility, ImplementsClause, Tag, TypeAnnotation, TypeHeader, }; use roc_parse::ident::UppercaseIdent; use roc_region::all::Loc; @@ -524,101 +524,6 @@ fn format_assigned_field_help( } } -impl<'a> Formattable for OldRecordBuilderField<'a> { - fn is_multiline(&self) -> bool { - is_multiline_record_builder_field_help(self) - } - - fn format_with_options(&self, buf: &mut Buf, _parens: Parens, newlines: Newlines, indent: u16) { - // we abuse the `Newlines` type to decide between multiline or single-line layout - format_record_builder_field_help(self, buf, indent, newlines == Newlines::Yes); - } -} - -fn is_multiline_record_builder_field_help(afield: &OldRecordBuilderField<'_>) -> bool { - use self::OldRecordBuilderField::*; - - match afield { - Value(_, spaces, ann) => !spaces.is_empty() || ann.value.is_multiline(), - ApplyValue(_, colon_spaces, arrow_spaces, ann) => { - !colon_spaces.is_empty() || !arrow_spaces.is_empty() || ann.value.is_multiline() - } - LabelOnly(_) => false, - SpaceBefore(_, _) | SpaceAfter(_, _) => true, - Malformed(text) => text.chars().any(|c| c == '\n'), - } -} - -fn format_record_builder_field_help( - zelf: &OldRecordBuilderField, - buf: &mut Buf, - indent: u16, - is_multiline: bool, -) { - use self::OldRecordBuilderField::*; - - match zelf { - Value(name, spaces, ann) => { - if is_multiline { - buf.newline(); - } - - buf.indent(indent); - buf.push_str(name.value); - - if !spaces.is_empty() { - fmt_spaces(buf, spaces.iter(), indent); - } - - buf.push(':'); - buf.spaces(1); - ann.value.format(buf, indent); - } - ApplyValue(name, colon_spaces, arrow_spaces, ann) => { - if is_multiline { - buf.newline(); - buf.indent(indent); - } - - buf.push_str(name.value); - - if !colon_spaces.is_empty() { - fmt_spaces(buf, colon_spaces.iter(), indent); - } - - buf.push(':'); - buf.spaces(1); - - if !arrow_spaces.is_empty() { - fmt_spaces(buf, arrow_spaces.iter(), indent); - } - - buf.push_str("<-"); - buf.spaces(1); - ann.value.format(buf, indent); - } - LabelOnly(name) => { - if is_multiline { - buf.newline(); - buf.indent(indent); - } - - buf.push_str(name.value); - } - SpaceBefore(sub_field, spaces) => { - fmt_comments_only(buf, spaces.iter(), NewlineAt::Bottom, indent); - format_record_builder_field_help(sub_field, buf, indent, is_multiline); - } - SpaceAfter(sub_field, spaces) => { - format_record_builder_field_help(sub_field, buf, indent, is_multiline); - fmt_comments_only(buf, spaces.iter(), NewlineAt::Bottom, indent); - } - Malformed(raw) => { - buf.push_str(raw); - } - } -} - impl<'a> Formattable for Tag<'a> { fn is_multiline(&self) -> bool { use self::Tag::*; diff --git a/crates/compiler/fmt/src/expr.rs b/crates/compiler/fmt/src/expr.rs index 62c1e42e6f8..46e004d7f1e 100644 --- a/crates/compiler/fmt/src/expr.rs +++ b/crates/compiler/fmt/src/expr.rs @@ -10,7 +10,7 @@ use crate::Buf; use roc_module::called_via::{self, BinOp}; use roc_parse::ast::{ is_expr_suffixed, AssignedField, Base, Collection, CommentOrNewline, Expr, ExtractSpaces, - OldRecordBuilderField, Pattern, TryTarget, WhenBranch, + Pattern, TryTarget, WhenBranch, }; use roc_parse::ast::{StrLiteral, StrSegment}; use roc_parse::ident::Accessor; @@ -91,8 +91,6 @@ impl<'a> Formattable for Expr<'a> { | PrecedenceConflict(roc_parse::ast::PrecedenceConflict { expr: loc_subexpr, .. }) - | MultipleOldRecordBuilders(loc_subexpr) - | UnappliedOldRecordBuilder(loc_subexpr) | EmptyRecordBuilder(loc_subexpr) | SingleFieldRecordBuilder(loc_subexpr) | OptionalFieldInRecordBuilder(_, loc_subexpr) => loc_subexpr.is_multiline(), @@ -118,7 +116,6 @@ impl<'a> Formattable for Expr<'a> { Record(fields) => is_collection_multiline(fields), Tuple(fields) => is_collection_multiline(fields), RecordUpdate { fields, .. } => is_collection_multiline(fields), - OldRecordBuilder(fields) => is_collection_multiline(fields), RecordBuilder { fields, .. } => is_collection_multiline(fields), } } @@ -244,10 +241,7 @@ impl<'a> Formattable for Expr<'a> { a.extract_spaces().item.is_multiline() && matches!( a.value.extract_spaces().item, - Expr::Tuple(_) - | Expr::List(_) - | Expr::Record(_) - | Expr::OldRecordBuilder(_) + Expr::Tuple(_) | Expr::List(_) | Expr::Record(_) ) && a.extract_spaces().before == [CommentOrNewline::Newline] }) @@ -392,16 +386,6 @@ impl<'a> Formattable for Expr<'a> { assigned_field_to_space_before, ); } - OldRecordBuilder(fields) => { - fmt_record_like( - buf, - None, - *fields, - indent, - format_record_builder_field_multiline, - record_builder_field_to_space_before, - ); - } Closure(loc_patterns, loc_ret) => { fmt_closure(buf, loc_patterns, loc_ret, indent); } @@ -563,8 +547,6 @@ impl<'a> Formattable for Expr<'a> { } MalformedClosure => {} PrecedenceConflict { .. } => {} - MultipleOldRecordBuilders { .. } => {} - UnappliedOldRecordBuilder { .. } => {} EmptyRecordBuilder { .. } => {} SingleFieldRecordBuilder { .. } => {} OptionalFieldInRecordBuilder(_, _) => {} @@ -625,11 +607,7 @@ pub(crate) fn format_sq_literal(buf: &mut Buf, s: &str) { fn is_outdentable(expr: &Expr) -> bool { matches!( expr.extract_spaces().item, - Expr::Tuple(_) - | Expr::List(_) - | Expr::Record(_) - | Expr::OldRecordBuilder(_) - | Expr::Closure(..) + Expr::Tuple(_) | Expr::List(_) | Expr::Record(_) | Expr::Closure(..) ) } @@ -1644,113 +1622,6 @@ fn assigned_field_to_space_before<'a, T>( } } -fn format_record_builder_field_multiline( - buf: &mut Buf, - field: &OldRecordBuilderField, - indent: u16, - separator_prefix: &str, -) { - use self::OldRecordBuilderField::*; - match field { - Value(name, spaces, ann) => { - buf.newline(); - buf.indent(indent); - buf.push_str(name.value); - - if !spaces.is_empty() { - fmt_spaces(buf, spaces.iter(), indent); - buf.indent(indent); - } - - buf.push_str(separator_prefix); - buf.push_str(":"); - - if ann.value.is_multiline() { - buf.newline(); - ann.value.format(buf, indent + INDENT); - } else { - buf.spaces(1); - ann.value.format(buf, indent); - } - - buf.push(','); - } - ApplyValue(name, colon_spaces, arrow_spaces, ann) => { - buf.newline(); - buf.indent(indent); - buf.push_str(name.value); - - if !colon_spaces.is_empty() { - fmt_spaces(buf, colon_spaces.iter(), indent); - buf.indent(indent); - } - - buf.push_str(separator_prefix); - buf.push(':'); - buf.spaces(1); - - if !arrow_spaces.is_empty() { - fmt_spaces(buf, arrow_spaces.iter(), indent); - buf.indent(indent + INDENT); - } - - buf.push_str("<-"); - - if ann.value.is_multiline() { - buf.newline(); - ann.value.format(buf, indent + INDENT); - } else { - buf.spaces(1); - ann.value.format(buf, indent); - } - buf.push(','); - } - LabelOnly(name) => { - buf.newline(); - buf.indent(indent); - buf.push_str(name.value); - buf.push(','); - } - SpaceBefore(sub_field, _spaces) => { - // We have something like that: - // ``` - // # comment - // field, - // ``` - // we'd like to preserve this - - format_record_builder_field_multiline(buf, sub_field, indent, separator_prefix); - } - SpaceAfter(sub_field, spaces) => { - // We have something like that: - // ``` - // field # comment - // , otherfield - // ``` - // we'd like to transform it into: - // ``` - // field, - // # comment - // otherfield - // ``` - format_record_builder_field_multiline(buf, sub_field, indent, separator_prefix); - fmt_comments_only(buf, spaces.iter(), NewlineAt::Top, indent); - } - Malformed(raw) => { - buf.push_str(raw); - } - } -} - -fn record_builder_field_to_space_before<'a>( - field: &'a OldRecordBuilderField<'a>, -) -> Option<(&OldRecordBuilderField<'a>, &'a [CommentOrNewline<'a>])> { - match field { - OldRecordBuilderField::SpaceBefore(sub_field, spaces) => Some((sub_field, spaces)), - _ => None, - } -} - fn sub_expr_requests_parens(expr: &Expr<'_>) -> bool { match expr { Expr::BinOps(left_side, _) => { diff --git a/crates/compiler/load/tests/test_reporting.rs b/crates/compiler/load/tests/test_reporting.rs index 99baf06e159..6d964dcd129 100644 --- a/crates/compiler/load/tests/test_reporting.rs +++ b/crates/compiler/load/tests/test_reporting.rs @@ -4972,30 +4972,6 @@ mod test_reporting { "### ); - test_report!( - record_builder_in_module_params, - indoc!( - r" - import Menu { - echo, - name: <- applyName - } - " - ),@r###" - ── OLD-STYLE RECORD BUILDER IN MODULE PARAMS in ...r_in_module_params/Test.roc ─ - - I was partway through parsing module params, but I got stuck here: - - 4│ import Menu { - 5│ echo, - 6│ name: <- applyName - ^^^^^^^^^^^^^^^^^^ - - This looks like an old-style record builder field, but those are not - allowed in module params. - "### - ); - test_report!( record_update_in_module_params, indoc!( @@ -10661,163 +10637,6 @@ All branches in an `if` must have the same type! // Record Builders - test_report!( - optional_field_in_old_record_builder, - indoc!( - r#" - { - a: <- apply "a", - b, - c ? "optional" - } - "# - ), - @r#" - ── BAD OLD-STYLE RECORD BUILDER in ...nal_field_in_old_record_builder/Test.roc ─ - - I am partway through parsing a record builder, and I found an optional - field: - - 1│ app "test" provides [main] to "./platform" - 2│ - 3│ main = - 4│ { - 5│ a: <- apply "a", - 6│ b, - 7│ c ? "optional" - ^^^^^^^^^^^^^^ - - Optional fields can only appear when you destructure a record. - "# - ); - - test_report!( - record_update_old_builder, - indoc!( - r#" - { rec & - a: <- apply "a", - b: 3 - } - "# - ), - @r#" - ── BAD RECORD UPDATE in tmp/record_update_old_builder/Test.roc ───────────────── - - I am partway through parsing a record update, and I found an old-style - record builder field: - - 1│ app "test" provides [main] to "./platform" - 2│ - 3│ main = - 4│ { rec & - 5│ a: <- apply "a", - ^^^^^^^^^^^^^^^ - - Old-style record builders cannot be updated like records. - "# - ); - - test_report!( - multiple_old_record_builders, - indoc!( - r#" - succeed - { a: <- apply "a" } - { b: <- apply "b" } - "# - ), - @r#" - ── MULTIPLE OLD-STYLE RECORD BUILDERS in /code/proj/Main.roc ─────────────────── - - This function is applied to multiple old-style record builders: - - 4│> succeed - 5│> { a: <- apply "a" } - 6│> { b: <- apply "b" } - - Note: Functions can only take at most one old-style record builder! - - Tip: You can combine them or apply them separately. - "# - ); - - test_report!( - unapplied_old_record_builder, - indoc!( - r#" - { a: <- apply "a" } - "# - ), - @r#" - ── UNAPPLIED OLD-STYLE RECORD BUILDER in /code/proj/Main.roc ─────────────────── - - This old-style record builder was not applied to a function: - - 4│ { a: <- apply "a" } - ^^^^^^^^^^^^^^^^^^^ - - However, we need a function to construct the record. - - Note: Functions must be applied directly. The pipe operator (|>) cannot be used. - "# - ); - - test_report!( - old_record_builder_apply_non_function, - indoc!( - r#" - succeed = \_ -> crash "" - - succeed { - a: <- "a", - } - "# - ), - @r#" - ── TOO MANY ARGS in /code/proj/Main.roc ──────────────────────────────────────── - - This value is not a function, but it was given 1 argument: - - 7│ a: <- "a", - ^^^ - - Tip: Remove <- to assign the field directly. - "# - ); - - // Skipping test because opaque types defined in the same module - // do not fail with the special opaque type error - // - // test_report!( - // record_builder_apply_opaque, - // indoc!( - // r#" - // succeed = \_ -> crash "" - - // Decode := {} - - // get : Str -> Decode - // get = \_ -> @Decode {} - - // succeed { - // a: <- get "a", - // # missing |> apply ^ - // } - // "# - // ), - // @r#" - // ── TOO MANY ARGS in /code/proj/Main.roc ──────────────────────────────────────── - - // This value is an opaque type, so it cannot be called with an argument: - - // 12│ a: <- get "a", - // ^^^^^^^ - - // Hint: Did you mean to apply it to a function first? - // "# - // ); - test_report!( empty_record_builder, indoc!( diff --git a/crates/compiler/module/src/called_via.rs b/crates/compiler/module/src/called_via.rs index e64cbbce385..b1422f67042 100644 --- a/crates/compiler/module/src/called_via.rs +++ b/crates/compiler/module/src/called_via.rs @@ -75,10 +75,6 @@ pub enum CalledVia { /// e.g. "$(first) $(last)" is transformed into Str.concat (Str.concat first " ") last. StringInterpolation, - /// This call is the result of desugaring an old style Record Builder field. - /// e.g. succeed { a <- get "a" } is transformed into (get "a") (succeed \a -> { a }) - OldRecordBuilder, - /// This call is the result of desugaring a map2-based Record Builder field. e.g. /// ```roc /// { Task.parallel <- diff --git a/crates/compiler/parse/src/ast.rs b/crates/compiler/parse/src/ast.rs index 051f4d0cca1..b59fdb591e3 100644 --- a/crates/compiler/parse/src/ast.rs +++ b/crates/compiler/parse/src/ast.rs @@ -456,13 +456,6 @@ pub enum Expr<'a> { Tuple(Collection<'a, &'a Loc>>), - // Record Builders - /// Applicative record builders, e.g. - /// build { - /// foo: <- getData Foo, - /// bar: <- getData Bar, - /// } - OldRecordBuilder(Collection<'a, Loc>>), /// Mapper-based record builders, e.g. /// { Task.parallel <- /// foo: Task.getData Foo, @@ -541,8 +534,6 @@ pub enum Expr<'a> { // Both operators were non-associative, e.g. (True == False == False). // We should tell the author to disambiguate by grouping them with parens. PrecedenceConflict(&'a PrecedenceConflict<'a>), - MultipleOldRecordBuilders(&'a Loc>), - UnappliedOldRecordBuilder(&'a Loc>), EmptyRecordBuilder(&'a Loc>), SingleFieldRecordBuilder(&'a Loc>), OptionalFieldInRecordBuilder(&'a Loc<&'a str>, &'a Loc>), @@ -663,9 +654,6 @@ pub fn is_expr_suffixed(expr: &Expr) -> bool { .iter() .any(|field| is_assigned_value_suffixed(&field.value)), Expr::Tuple(items) => items.iter().any(|x| is_expr_suffixed(&x.value)), - Expr::OldRecordBuilder(items) => items - .iter() - .any(|rbf| is_record_builder_field_suffixed(&rbf.value)), Expr::RecordBuilder { mapper: _, fields } => fields .iter() .any(|field| is_assigned_value_suffixed(&field.value)), @@ -688,8 +676,6 @@ pub fn is_expr_suffixed(expr: &Expr) -> bool { Expr::MalformedClosure => false, Expr::MalformedSuffixed(_) => false, Expr::PrecedenceConflict(_) => false, - Expr::MultipleOldRecordBuilders(_) => false, - Expr::UnappliedOldRecordBuilder(_) => false, Expr::EmptyRecordBuilder(_) => false, Expr::SingleFieldRecordBuilder(_) => false, Expr::OptionalFieldInRecordBuilder(_, _) => false, @@ -717,17 +703,6 @@ fn is_assigned_value_suffixed<'a>(value: &AssignedField<'a, Expr<'a>>) -> bool { } } -fn is_record_builder_field_suffixed(field: &OldRecordBuilderField<'_>) -> bool { - match field { - OldRecordBuilderField::Value(_, _, a) => is_expr_suffixed(&a.value), - OldRecordBuilderField::ApplyValue(_, _, _, a) => is_expr_suffixed(&a.value), - OldRecordBuilderField::LabelOnly(_) => false, - OldRecordBuilderField::SpaceBefore(a, _) => is_record_builder_field_suffixed(a), - OldRecordBuilderField::SpaceAfter(a, _) => is_record_builder_field_suffixed(a), - OldRecordBuilderField::Malformed(_) => false, - } -} - pub fn split_around(items: &[T], target: usize) -> (&[T], &[T]) { let (before, rest) = items.split_at(target); let after = &rest[1..]; @@ -935,26 +910,6 @@ impl<'a, 'b> RecursiveValueDefIter<'a, 'b> { expr_stack.push(&loc_expr.value); } } - OldRecordBuilder(fields) => { - expr_stack.reserve(fields.len()); - for loc_record_builder_field in fields.items { - let mut current_field = loc_record_builder_field.value; - - loop { - use OldRecordBuilderField::*; - - match current_field { - Value(_, _, loc_val) => break expr_stack.push(&loc_val.value), - ApplyValue(_, _, _, loc_val) => { - break expr_stack.push(&loc_val.value) - } - SpaceBefore(next_field, _) => current_field = *next_field, - SpaceAfter(next_field, _) => current_field = *next_field, - LabelOnly(_) | Malformed(_) => break, - } - } - } - } RecordBuilder { mapper: map2, fields, @@ -1039,9 +994,7 @@ impl<'a, 'b> RecursiveValueDefIter<'a, 'b> { | SpaceAfter(expr, _) | ParensAround(expr) => expr_stack.push(expr), - MultipleOldRecordBuilders(loc_expr) - | UnappliedOldRecordBuilder(loc_expr) - | EmptyRecordBuilder(loc_expr) + EmptyRecordBuilder(loc_expr) | SingleFieldRecordBuilder(loc_expr) | OptionalFieldInRecordBuilder(_, loc_expr) => expr_stack.push(&loc_expr.value), @@ -1667,30 +1620,6 @@ impl<'a, Val> AssignedField<'a, Val> { } } -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum OldRecordBuilderField<'a> { - // A field with a value, e.g. `{ name: "blah" }` - Value(Loc<&'a str>, &'a [CommentOrNewline<'a>], &'a Loc>), - - // A field with a function we can apply to build part of the record, e.g. `{ name: <- apply getName }` - ApplyValue( - Loc<&'a str>, - &'a [CommentOrNewline<'a>], - &'a [CommentOrNewline<'a>], - &'a Loc>, - ), - - // A label with no value, e.g. `{ name }` (this is sugar for { name: name }) - LabelOnly(Loc<&'a str>), - - // We preserve this for the formatter; canonicalization ignores it. - SpaceBefore(&'a OldRecordBuilderField<'a>, &'a [CommentOrNewline<'a>]), - SpaceAfter(&'a OldRecordBuilderField<'a>, &'a [CommentOrNewline<'a>]), - - /// A malformed assigned field, which will code gen to a runtime error - Malformed(&'a str), -} - #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum CommentOrNewline<'a> { Newline, @@ -2225,15 +2154,6 @@ impl<'a, Val> Spaceable<'a> for AssignedField<'a, Val> { } } -impl<'a> Spaceable<'a> for OldRecordBuilderField<'a> { - fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { - OldRecordBuilderField::SpaceBefore(self, spaces) - } - fn after(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { - OldRecordBuilderField::SpaceAfter(self, spaces) - } -} - impl<'a> Spaceable<'a> for Tag<'a> { fn before(&'a self, spaces: &'a [CommentOrNewline<'a>]) -> Self { Tag::SpaceBefore(self, spaces) @@ -2536,7 +2456,6 @@ impl<'a> Malformed for Expr<'a> { Record(items) => items.is_malformed(), Tuple(items) => items.is_malformed(), - OldRecordBuilder(items) => items.is_malformed(), RecordBuilder { mapper: map2, fields } => map2.is_malformed() || fields.is_malformed(), Closure(args, body) => args.iter().any(|arg| arg.is_malformed()) || body.is_malformed(), @@ -2560,8 +2479,6 @@ impl<'a> Malformed for Expr<'a> { MalformedClosure | MalformedSuffixed(..) | PrecedenceConflict(_) | - MultipleOldRecordBuilders(_) | - UnappliedOldRecordBuilder(_) | EmptyRecordBuilder(_) | SingleFieldRecordBuilder(_) | OptionalFieldInRecordBuilder(_, _) => true, @@ -2641,19 +2558,6 @@ impl<'a, T: Malformed> Malformed for AssignedField<'a, T> { } } -impl<'a> Malformed for OldRecordBuilderField<'a> { - fn is_malformed(&self) -> bool { - match self { - OldRecordBuilderField::Value(_, _, expr) - | OldRecordBuilderField::ApplyValue(_, _, _, expr) => expr.is_malformed(), - OldRecordBuilderField::LabelOnly(_) => false, - OldRecordBuilderField::SpaceBefore(field, _) - | OldRecordBuilderField::SpaceAfter(field, _) => field.is_malformed(), - OldRecordBuilderField::Malformed(_) => true, - } - } -} - impl<'a> Malformed for Pattern<'a> { fn is_malformed(&self) -> bool { use Pattern::*; diff --git a/crates/compiler/parse/src/expr.rs b/crates/compiler/parse/src/expr.rs index 723eeb14866..20a00f3daa0 100644 --- a/crates/compiler/parse/src/expr.rs +++ b/crates/compiler/parse/src/expr.rs @@ -2,8 +2,8 @@ use crate::ast::{ is_expr_suffixed, AssignedField, Collection, CommentOrNewline, Defs, Expr, ExtractSpaces, Implements, ImplementsAbilities, ImportAlias, ImportAsKeyword, ImportExposingKeyword, ImportedModuleName, IngestedFileAnnotation, IngestedFileImport, ModuleImport, - ModuleImportParams, OldRecordBuilderField, Pattern, Spaceable, Spaced, Spaces, SpacesBefore, - TryTarget, TypeAnnotation, TypeDef, TypeHeader, ValueDef, + ModuleImportParams, Pattern, Spaceable, Spaced, Spaces, SpacesBefore, TryTarget, + TypeAnnotation, TypeDef, TypeHeader, ValueDef, }; use crate::blankspace::{ loc_space0_e, require_newline_or_eof, space0_after_e, space0_around_ee, space0_before_e, @@ -925,15 +925,11 @@ fn import_params<'a>() -> impl Parser<'a, ModuleImportParams<'a>, EImportParams< .fields .map_items_result(arena, |loc_field| { match loc_field.value.to_assigned_field(arena) { - Ok(AssignedField::IgnoredValue(_, _, _)) => Err(( + AssignedField::IgnoredValue(_, _, _) => Err(( MadeProgress, EImportParams::RecordIgnoredFieldFound(loc_field.region), )), - Ok(field) => Ok(Loc::at(loc_field.region, field)), - Err(FoundApplyValue) => Err(( - MadeProgress, - EImportParams::RecordApplyFound(loc_field.region), - )), + field => Ok(Loc::at(loc_field.region, field)), } })?; @@ -2179,8 +2175,6 @@ fn expr_to_pattern_help<'a>(arena: &'a Bump, expr: &Expr<'a>) -> Result(arena: &'a Bump, expr: &Expr<'a>) -> Result return Err(()), Expr::Str(string) => Pattern::StrLiteral(string), @@ -3390,38 +3383,12 @@ pub enum RecordField<'a> { LabelOnly(Loc<&'a str>), SpaceBefore(&'a RecordField<'a>, &'a [CommentOrNewline<'a>]), SpaceAfter(&'a RecordField<'a>, &'a [CommentOrNewline<'a>]), - ApplyValue( - Loc<&'a str>, - &'a [CommentOrNewline<'a>], - &'a [CommentOrNewline<'a>], - &'a Loc>, - ), } #[derive(Debug)] pub struct FoundApplyValue; -#[derive(Debug)] -pub enum NotOldBuilderFieldValue { - FoundOptionalValue, - FoundIgnoredValue, -} - impl<'a> RecordField<'a> { - fn is_apply_value(&self) -> bool { - let mut current = self; - - loop { - match current { - RecordField::ApplyValue(_, _, _, _) => break true, - RecordField::SpaceBefore(field, _) | RecordField::SpaceAfter(field, _) => { - current = *field; - } - _ => break false, - } - } - } - fn is_ignored_value(&self) -> bool { let mut current = self; @@ -3436,74 +3403,34 @@ impl<'a> RecordField<'a> { } } - pub fn to_assigned_field( - self, - arena: &'a Bump, - ) -> Result>, FoundApplyValue> { + pub fn to_assigned_field(self, arena: &'a Bump) -> AssignedField<'a, Expr<'a>> { use AssignedField::*; match self { RecordField::RequiredValue(loc_label, spaces, loc_expr) => { - Ok(RequiredValue(loc_label, spaces, loc_expr)) + RequiredValue(loc_label, spaces, loc_expr) } RecordField::OptionalValue(loc_label, spaces, loc_expr) => { - Ok(OptionalValue(loc_label, spaces, loc_expr)) + OptionalValue(loc_label, spaces, loc_expr) } RecordField::IgnoredValue(loc_label, spaces, loc_expr) => { - Ok(IgnoredValue(loc_label, spaces, loc_expr)) + IgnoredValue(loc_label, spaces, loc_expr) } - RecordField::LabelOnly(loc_label) => Ok(LabelOnly(loc_label)), - - RecordField::ApplyValue(_, _, _, _) => Err(FoundApplyValue), + RecordField::LabelOnly(loc_label) => LabelOnly(loc_label), RecordField::SpaceBefore(field, spaces) => { - let assigned_field = field.to_assigned_field(arena)?; + let assigned_field = field.to_assigned_field(arena); - Ok(SpaceBefore(arena.alloc(assigned_field), spaces)) + SpaceBefore(arena.alloc(assigned_field), spaces) } RecordField::SpaceAfter(field, spaces) => { - let assigned_field = field.to_assigned_field(arena)?; + let assigned_field = field.to_assigned_field(arena); - Ok(SpaceAfter(arena.alloc(assigned_field), spaces)) - } - } - } - - fn to_builder_field( - self, - arena: &'a Bump, - ) -> Result, NotOldBuilderFieldValue> { - use OldRecordBuilderField::*; - - match self { - RecordField::RequiredValue(loc_label, spaces, loc_expr) => { - Ok(Value(loc_label, spaces, loc_expr)) - } - - RecordField::OptionalValue(_, _, _) => Err(NotOldBuilderFieldValue::FoundOptionalValue), - - RecordField::IgnoredValue(_, _, _) => Err(NotOldBuilderFieldValue::FoundIgnoredValue), - - RecordField::LabelOnly(loc_label) => Ok(LabelOnly(loc_label)), - - RecordField::ApplyValue(loc_label, colon_spaces, arrow_spaces, loc_expr) => { - Ok(ApplyValue(loc_label, colon_spaces, arrow_spaces, loc_expr)) - } - - RecordField::SpaceBefore(field, spaces) => { - let builder_field = field.to_builder_field(arena)?; - - Ok(SpaceBefore(arena.alloc(builder_field), spaces)) - } - - RecordField::SpaceAfter(field, spaces) => { - let builder_field = field.to_builder_field(arena)?; - - Ok(SpaceAfter(arena.alloc(builder_field), spaces)) + SpaceAfter(arena.alloc(assigned_field), spaces) } } } @@ -3557,14 +3484,10 @@ pub fn record_field<'a>() -> impl Parser<'a, RecordField<'a>, ERecord<'a>> { match field_data { Either::First((loc_label, (spaces, opt_loc_val))) => { match opt_loc_val { - Some(Either::First((_, RecordFieldExpr::Value(loc_val)))) => { + Some(Either::First((_, loc_val))) => { RequiredValue(loc_label, spaces, arena.alloc(loc_val)) } - Some(Either::First((_, RecordFieldExpr::Apply(arrow_spaces, loc_val)))) => { - ApplyValue(loc_label, spaces, arrow_spaces, arena.alloc(loc_val)) - } - Some(Either::Second((_, loc_val))) => { OptionalValue(loc_label, spaces, arena.alloc(loc_val)) } @@ -3591,34 +3514,17 @@ pub fn record_field<'a>() -> impl Parser<'a, RecordField<'a>, ERecord<'a>> { ) } -enum RecordFieldExpr<'a> { - Apply(&'a [CommentOrNewline<'a>], Loc>), - Value(Loc>), -} - -fn record_field_expr<'a>() -> impl Parser<'a, RecordFieldExpr<'a>, ERecord<'a>> { +fn record_field_expr<'a>() -> impl Parser<'a, Loc>, ERecord<'a>> { map_with_arena( - and( - spaces(), - either( - and( - two_bytes(b'<', b'-', ERecord::Arrow), - spaces_before(specialize_err_ref(ERecord::Expr, loc_expr(false))), - ), - specialize_err_ref(ERecord::Expr, loc_expr(false)), - ), - ), - |arena: &'a bumpalo::Bump, (spaces, either)| match either { - Either::First((_, loc_expr)) => RecordFieldExpr::Apply(spaces, loc_expr), - Either::Second(loc_expr) => RecordFieldExpr::Value({ - if spaces.is_empty() { - loc_expr - } else { - arena - .alloc(loc_expr.value) - .with_spaces_before(spaces, loc_expr.region) - } - }), + and(spaces(), specialize_err_ref(ERecord::Expr, loc_expr(false))), + |arena: &'a bumpalo::Bump, (spaces, loc_expr)| { + if spaces.is_empty() { + loc_expr + } else { + arena + .alloc(loc_expr.value) + .with_spaces_before(spaces, loc_expr.region) + } }, ) } @@ -3686,13 +3592,11 @@ fn record_literal_help<'a>() -> impl Parser<'a, Expr<'a>, EExpr<'a>> { record_update_help(arena, update, record.fields) } Some((mapper, RecordHelpPrefix::Mapper)) => { - new_record_builder_help(arena, mapper, record.fields) + record_builder_help(arena, mapper, record.fields) } None => { let special_field_found = record.fields.iter().find_map(|field| { - if field.value.is_apply_value() { - Some(old_record_builder_help(arena, record.fields)) - } else if field.value.is_ignored_value() { + if field.value.is_ignored_value() { Some(Err(EExpr::RecordUpdateIgnoredField(field.region))) } else { None @@ -3701,7 +3605,7 @@ fn record_literal_help<'a>() -> impl Parser<'a, Expr<'a>, EExpr<'a>> { special_field_found.unwrap_or_else(|| { let fields = record.fields.map_items(arena, |loc_field| { - loc_field.map(|field| field.to_assigned_field(arena).unwrap()) + loc_field.map(|field| field.to_assigned_field(arena)) }); Ok(Expr::Record(fields)) @@ -3728,14 +3632,13 @@ fn record_update_help<'a>( ) -> Result, EExpr<'a>> { let result = fields.map_items_result(arena, |loc_field| { match loc_field.value.to_assigned_field(arena) { - Ok(AssignedField::IgnoredValue(_, _, _)) => { + AssignedField::IgnoredValue(_, _, _) => { Err(EExpr::RecordUpdateIgnoredField(loc_field.region)) } - Ok(builder_field) => Ok(Loc { + builder_field => Ok(Loc { region: loc_field.region, value: builder_field, }), - Err(FoundApplyValue) => Err(EExpr::RecordUpdateOldBuilderField(loc_field.region)), } }); @@ -3745,19 +3648,18 @@ fn record_update_help<'a>( }) } -fn new_record_builder_help<'a>( +fn record_builder_help<'a>( arena: &'a Bump, mapper: Loc>, fields: Collection<'a, Loc>>, ) -> Result, EExpr<'a>> { let result = fields.map_items_result(arena, |loc_field| { - match loc_field.value.to_assigned_field(arena) { - Ok(builder_field) => Ok(Loc { - region: loc_field.region, - value: builder_field, - }), - Err(FoundApplyValue) => Err(EExpr::RecordBuilderOldBuilderField(loc_field.region)), - } + let builder_field = loc_field.value.to_assigned_field(arena); + + Ok(Loc { + region: loc_field.region, + value: builder_field, + }) }); result.map(|fields| Expr::RecordBuilder { @@ -3766,28 +3668,6 @@ fn new_record_builder_help<'a>( }) } -fn old_record_builder_help<'a>( - arena: &'a Bump, - fields: Collection<'a, Loc>>, -) -> Result, EExpr<'a>> { - let result = fields.map_items_result(arena, |loc_field| { - match loc_field.value.to_builder_field(arena) { - Ok(builder_field) => Ok(Loc { - region: loc_field.region, - value: builder_field, - }), - Err(NotOldBuilderFieldValue::FoundOptionalValue) => { - Err(EExpr::OptionalValueInOldRecordBuilder(loc_field.region)) - } - Err(NotOldBuilderFieldValue::FoundIgnoredValue) => { - Err(EExpr::IgnoredValueInOldRecordBuilder(loc_field.region)) - } - } - }); - - result.map(Expr::OldRecordBuilder) -} - fn apply_expr_access_chain<'a>( arena: &'a Bump, value: Expr<'a>, diff --git a/crates/compiler/parse/src/module.rs b/crates/compiler/parse/src/module.rs deleted file mode 100644 index 899ec154e2f..00000000000 --- a/crates/compiler/parse/src/module.rs +++ /dev/null @@ -1,905 +0,0 @@ -use crate::ast::{Collection, CommentOrNewline, Defs, Header, Module, Spaced, Spaces}; -use crate::blankspace::{space0_around_ee, space0_before_e, space0_e}; -use crate::expr::merge_spaces; -use crate::header::{ - package_entry, package_name, AppHeader, ExposedName, ExposesKeyword, HostedHeader, - ImportsCollection, ImportsEntry, ImportsKeyword, ImportsKeywordItem, Keyword, KeywordItem, - ModuleHeader, ModuleName, ModuleParams, PackageEntry, PackageHeader, PackagesKeyword, - PlatformHeader, PlatformRequires, ProvidesKeyword, ProvidesTo, RequiresKeyword, To, ToKeyword, - TypedIdent, -}; -use crate::ident::{self, lowercase_ident, unqualified_ident, UppercaseIdent}; -use crate::parser::Progress::{self, *}; -use crate::parser::{ - and, backtrackable, byte, collection_trailing_sep_e, increment_min_indent, loc, map, - map_with_arena, optional, reset_min_indent, skip_first, skip_second, specialize_err, succeed, - two_bytes, zero_or_more, EExposes, EHeader, EImports, EPackages, EParams, EProvides, ERequires, - ETypedIdent, Parser, SourceError, SpaceProblem, SyntaxError, -}; -use crate::pattern::record_pattern_fields; -use crate::state::State; -use crate::string_literal::{self, parse_str_literal}; -use crate::type_annotation; -use roc_region::all::{Loc, Position, Region}; - -fn end_of_file<'a>() -> impl Parser<'a, (), SyntaxError<'a>> { - |_arena, state: State<'a>, _min_indent: u32| { - if state.has_reached_end() { - Ok((NoProgress, (), state)) - } else { - Err((NoProgress, SyntaxError::NotEndOfFile(state.pos()))) - } - } -} - -pub fn parse_module_defs<'a>( - arena: &'a bumpalo::Bump, - state: State<'a>, - defs: Defs<'a>, -) -> Result, SyntaxError<'a>> { - let min_indent = 0; - match crate::expr::parse_top_level_defs(arena, state.clone(), defs) { - Ok((_, defs, state)) => match end_of_file().parse(arena, state, min_indent) { - Ok(_) => Ok(defs), - Err((_, fail)) => Err(fail), - }, - Err((_, fail)) => Err(SyntaxError::Expr(fail, state.pos())), - } -} - -pub fn parse_header<'a>( - arena: &'a bumpalo::Bump, - state: State<'a>, -) -> Result<(Module<'a>, State<'a>), SourceError<'a, EHeader<'a>>> { - let min_indent = 0; - match header().parse(arena, state.clone(), min_indent) { - Ok((_, module, state)) => Ok((module, state)), - Err((_, fail)) => Err(SourceError::new(fail, &state)), - } -} - -pub fn header<'a>() -> impl Parser<'a, Module<'a>, EHeader<'a>> { - use crate::parser::keyword; - - record!(Module { - comments: space0_e(EHeader::IndentStart), - header: one_of![ - map( - skip_first( - keyword("module", EHeader::Start), - increment_min_indent(module_header()) - ), - Header::Module - ), - map( - skip_first( - keyword("interface", EHeader::Start), - increment_min_indent(interface_header()) - ), - Header::Module - ), - map( - skip_first( - keyword("app", EHeader::Start), - increment_min_indent(one_of![app_header(), old_app_header()]) - ), - Header::App - ), - map( - skip_first( - keyword("package", EHeader::Start), - increment_min_indent(one_of![package_header(), old_package_header()]) - ), - Header::Package - ), - map( - skip_first( - keyword("platform", EHeader::Start), - increment_min_indent(platform_header()) - ), - Header::Platform - ), - map( - skip_first( - keyword("hosted", EHeader::Start), - increment_min_indent(hosted_header()) - ), - Header::Hosted - ), - ] - }) -} - -#[inline(always)] -fn module_header<'a>() -> impl Parser<'a, ModuleHeader<'a>, EHeader<'a>> { - record!(ModuleHeader { - after_keyword: space0_e(EHeader::IndentStart), - params: optional(specialize_err(EHeader::Params, module_params())), - exposes: specialize_err(EHeader::Exposes, exposes_list()), - interface_imports: succeed(None) - }) - .trace("module_header") -} - -fn module_params<'a>() -> impl Parser<'a, ModuleParams<'a>, EParams<'a>> { - record!(ModuleParams { - params: specialize_err(EParams::Pattern, record_pattern_fields()), - before_arrow: skip_second( - space0_e(EParams::BeforeArrow), - loc(two_bytes(b'-', b'>', EParams::Arrow)) - ), - after_arrow: space0_e(EParams::AfterArrow), - }) -} - -// TODO does this need to be a macro? -macro_rules! merge_n_spaces { - ($arena:expr, $($slice:expr),*) => { - { - let mut merged = bumpalo::collections::Vec::with_capacity_in(0 $(+ $slice.len())*, $arena); - $(merged.extend_from_slice($slice);)* - merged.into_bump_slice() - } - }; -} - -/// Parse old interface headers so we can format them into module headers -#[inline(always)] -fn interface_header<'a>() -> impl Parser<'a, ModuleHeader<'a>, EHeader<'a>> { - let after_keyword = map_with_arena( - and( - skip_second( - space0_e(EHeader::IndentStart), - loc(module_name_help(EHeader::ModuleName)), - ), - specialize_err(EHeader::Exposes, exposes_kw()), - ), - |arena: &'a bumpalo::Bump, - (before_name, kw): (&'a [CommentOrNewline<'a>], Spaces<'a, ExposesKeyword>)| { - merge_n_spaces!(arena, before_name, kw.before, kw.after) - }, - ); - - record!(ModuleHeader { - after_keyword: after_keyword, - params: succeed(None), - exposes: specialize_err(EHeader::Exposes, exposes_list()).trace("exposes_list"), - interface_imports: map( - specialize_err(EHeader::Imports, imports()), - imports_none_if_empty - ) - .trace("imports"), - }) - .trace("interface_header") -} - -fn imports_none_if_empty(value: ImportsKeywordItem<'_>) -> Option> { - if value.item.is_empty() { - None - } else { - Some(value) - } -} - -#[inline(always)] -fn hosted_header<'a>() -> impl Parser<'a, HostedHeader<'a>, EHeader<'a>> { - record!(HostedHeader { - before_name: space0_e(EHeader::IndentStart), - name: loc(module_name_help(EHeader::ModuleName)), - exposes: specialize_err(EHeader::Exposes, exposes_values_kw()), - imports: specialize_err(EHeader::Imports, imports()), - }) - .trace("hosted_header") -} - -fn chomp_module_name(buffer: &[u8]) -> Result<&str, Progress> { - use encode_unicode::CharExt; - - let mut chomped = 0; - - if let Ok((first_letter, width)) = char::from_utf8_slice_start(&buffer[chomped..]) { - if first_letter.is_uppercase() { - chomped += width; - } else { - return Err(Progress::NoProgress); - } - } - - while let Ok((ch, width)) = char::from_utf8_slice_start(&buffer[chomped..]) { - // After the first character, only these are allowed: - // - // * Unicode alphabetic chars - you might include `鹏` if that's clear to your readers - // * ASCII digits - e.g. `1` but not `¾`, both of which pass .is_numeric() - // * A '.' separating module parts - if ch.is_alphabetic() || ch.is_ascii_digit() { - chomped += width; - } else if ch == '.' { - chomped += width; - - if let Ok((first_letter, width)) = char::from_utf8_slice_start(&buffer[chomped..]) { - if first_letter.is_uppercase() { - chomped += width; - } else if first_letter == '{' { - // the .{ starting a `Foo.{ bar, baz }` importing clauses - chomped -= width; - break; - } else { - return Err(Progress::MadeProgress); - } - } - } else { - // we're done - break; - } - } - - let name = unsafe { std::str::from_utf8_unchecked(&buffer[..chomped]) }; - - Ok(name) -} - -#[inline(always)] -fn module_name<'a>() -> impl Parser<'a, ModuleName<'a>, ()> { - |_, mut state: State<'a>, _min_indent: u32| match chomp_module_name(state.bytes()) { - Ok(name) => { - let width = name.len(); - state = state.advance(width); - - Ok((MadeProgress, ModuleName::new(name), state)) - } - Err(progress) => Err((progress, ())), - } -} - -#[inline(always)] -fn app_header<'a>() -> impl Parser<'a, AppHeader<'a>, EHeader<'a>> { - record!(AppHeader { - before_provides: space0_e(EHeader::IndentStart), - provides: specialize_err(EHeader::Exposes, exposes_list()), - before_packages: space0_e(EHeader::IndentStart), - packages: specialize_err(EHeader::Packages, loc(packages_collection())), - old_imports: succeed(None), - old_provides_to_new_package: succeed(None), - }) - .trace("app_header") -} - -struct OldAppHeader<'a> { - pub before_name: &'a [CommentOrNewline<'a>], - pub packages: Option>>, - pub imports: Option>>, - pub provides: ProvidesTo<'a>, -} - -type OldAppPackages<'a> = - KeywordItem<'a, PackagesKeyword, Collection<'a, Loc>>>>; - -#[inline(always)] -fn old_app_header<'a>() -> impl Parser<'a, AppHeader<'a>, EHeader<'a>> { - let old = record!(OldAppHeader { - before_name: skip_second( - space0_e(EHeader::IndentStart), - loc(crate::parser::specialize_err( - EHeader::AppName, - string_literal::parse_str_literal() - )) - ), - packages: optional(specialize_err(EHeader::Packages, loc(packages()))), - imports: optional(specialize_err(EHeader::Imports, imports())), - provides: specialize_err(EHeader::Provides, provides_to()), - }); - - map_with_arena(old, |arena: &'a bumpalo::Bump, old: OldAppHeader<'a>| { - let mut before_packages: &'a [CommentOrNewline] = &[]; - - let packages = match old.packages { - Some(packages) => { - before_packages = merge_spaces( - arena, - packages.value.keyword.before, - packages.value.keyword.after, - ); - - if let To::ExistingPackage(platform_shorthand) = old.provides.to.value { - packages.map(|coll| { - coll.item.map_items(arena, |loc_spaced_pkg| { - if loc_spaced_pkg.value.item().shorthand == platform_shorthand { - loc_spaced_pkg.map(|spaced_pkg| { - spaced_pkg.map(arena, |pkg| { - let mut new_pkg = *pkg; - new_pkg.platform_marker = Some(merge_spaces( - arena, - old.provides.to_keyword.before, - old.provides.to_keyword.after, - )); - new_pkg - }) - }) - } else { - *loc_spaced_pkg - } - }) - }) - } else { - packages.map(|kw| kw.item) - } - } - None => Loc { - region: Region::zero(), - value: Collection::empty(), - }, - }; - - let provides = match old.provides.types { - Some(types) => { - let mut combined_items = bumpalo::collections::Vec::with_capacity_in( - old.provides.entries.items.len() + types.items.len(), - arena, - ); - - combined_items.extend_from_slice(old.provides.entries.items); - - for loc_spaced_type_ident in types.items { - combined_items.push(loc_spaced_type_ident.map(|spaced_type_ident| { - spaced_type_ident.map(arena, |type_ident| { - ExposedName::new(From::from(*type_ident)) - }) - })); - } - - let value_comments = old.provides.entries.final_comments(); - let type_comments = types.final_comments(); - - let mut combined_comments = bumpalo::collections::Vec::with_capacity_in( - value_comments.len() + type_comments.len(), - arena, - ); - combined_comments.extend_from_slice(value_comments); - combined_comments.extend_from_slice(type_comments); - - Collection::with_items_and_comments( - arena, - combined_items.into_bump_slice(), - combined_comments.into_bump_slice(), - ) - } - None => old.provides.entries, - }; - - AppHeader { - before_provides: merge_spaces( - arena, - old.before_name, - old.provides.provides_keyword.before, - ), - provides, - before_packages: merge_spaces( - arena, - before_packages, - old.provides.provides_keyword.after, - ), - packages, - old_imports: old.imports.and_then(imports_none_if_empty), - old_provides_to_new_package: match old.provides.to.value { - To::NewPackage(new_pkg) => Some(new_pkg), - To::ExistingPackage(_) => None, - }, - } - }) -} - -#[inline(always)] -fn package_header<'a>() -> impl Parser<'a, PackageHeader<'a>, EHeader<'a>> { - record!(PackageHeader { - before_exposes: space0_e(EHeader::IndentStart), - exposes: specialize_err(EHeader::Exposes, exposes_module_collection()), - before_packages: space0_e(EHeader::IndentStart), - packages: specialize_err(EHeader::Packages, loc(packages_collection())), - }) - .trace("package_header") -} - -#[derive(Debug, Clone, PartialEq)] -struct OldPackageHeader<'a> { - before_name: &'a [CommentOrNewline<'a>], - exposes: KeywordItem<'a, ExposesKeyword, Collection<'a, Loc>>>>, - packages: - Loc>>>>>, -} - -#[inline(always)] -fn old_package_header<'a>() -> impl Parser<'a, PackageHeader<'a>, EHeader<'a>> { - map_with_arena( - record!(OldPackageHeader { - before_name: skip_second( - space0_e(EHeader::IndentStart), - specialize_err(EHeader::PackageName, package_name()) - ), - exposes: specialize_err(EHeader::Exposes, exposes_modules()), - packages: specialize_err(EHeader::Packages, loc(packages())), - }), - |arena: &'a bumpalo::Bump, old: OldPackageHeader<'a>| { - let before_exposes = merge_n_spaces!( - arena, - old.before_name, - old.exposes.keyword.before, - old.exposes.keyword.after - ); - let before_packages = merge_spaces( - arena, - old.packages.value.keyword.before, - old.packages.value.keyword.after, - ); - - PackageHeader { - before_exposes, - exposes: old.exposes.item, - before_packages, - packages: old.packages.map(|kw| kw.item), - } - }, - ) - .trace("old_package_header") -} - -#[inline(always)] -fn platform_header<'a>() -> impl Parser<'a, PlatformHeader<'a>, EHeader<'a>> { - record!(PlatformHeader { - before_name: space0_e(EHeader::IndentStart), - name: loc(specialize_err(EHeader::PlatformName, package_name())), - requires: specialize_err(EHeader::Requires, requires()), - exposes: specialize_err(EHeader::Exposes, exposes_modules()), - packages: specialize_err(EHeader::Packages, packages()), - imports: specialize_err(EHeader::Imports, imports()), - provides: specialize_err(EHeader::Provides, provides_exposed()), - }) - .trace("platform_header") -} - -fn provides_to_package<'a>() -> impl Parser<'a, To<'a>, EProvides<'a>> { - one_of![ - specialize_err( - |_, pos| EProvides::Identifier(pos), - map(lowercase_ident(), To::ExistingPackage) - ), - specialize_err(EProvides::Package, map(package_name(), To::NewPackage)) - ] -} - -#[inline(always)] -fn provides_to<'a>() -> impl Parser<'a, ProvidesTo<'a>, EProvides<'a>> { - record!(ProvidesTo { - provides_keyword: spaces_around_keyword( - ProvidesKeyword, - EProvides::Provides, - EProvides::IndentProvides, - EProvides::IndentListStart - ), - entries: collection_trailing_sep_e( - byte(b'[', EProvides::ListStart), - exposes_entry(EProvides::Identifier), - byte(b',', EProvides::ListEnd), - byte(b']', EProvides::ListEnd), - Spaced::SpaceBefore - ), - types: optional(backtrackable(provides_types())), - to_keyword: spaces_around_keyword( - ToKeyword, - EProvides::To, - EProvides::IndentTo, - EProvides::IndentListStart - ), - to: loc(provides_to_package()), - }) - .trace("provides_to") -} - -fn provides_exposed<'a>() -> impl Parser< - 'a, - KeywordItem<'a, ProvidesKeyword, Collection<'a, Loc>>>>, - EProvides<'a>, -> { - record!(KeywordItem { - keyword: spaces_around_keyword( - ProvidesKeyword, - EProvides::Provides, - EProvides::IndentProvides, - EProvides::IndentListStart - ), - item: collection_trailing_sep_e( - byte(b'[', EProvides::ListStart), - exposes_entry(EProvides::Identifier), - byte(b',', EProvides::ListEnd), - byte(b']', EProvides::ListEnd), - Spaced::SpaceBefore - ), - }) -} - -#[inline(always)] -fn provides_types<'a>( -) -> impl Parser<'a, Collection<'a, Loc>>>, EProvides<'a>> { - skip_first( - // We only support spaces here, not newlines, because this is not intended - // to be the design forever. Someday it will hopefully work like Elm, - // where platform authors can provide functions like Browser.sandbox which - // present an API based on ordinary-looking type variables. - zero_or_more(byte( - b' ', - // HACK: If this errors, EProvides::Provides is not an accurate reflection - // of what went wrong. However, this is both skipped and zero_or_more, - // so this error should never be visible to anyone in practice! - EProvides::Provides, - )), - collection_trailing_sep_e( - byte(b'{', EProvides::ListStart), - provides_type_entry(EProvides::Identifier), - byte(b',', EProvides::ListEnd), - byte(b'}', EProvides::ListEnd), - Spaced::SpaceBefore, - ), - ) -} - -fn provides_type_entry<'a, F, E>( - to_expectation: F, -) -> impl Parser<'a, Loc>>, E> -where - F: Fn(Position) -> E, - F: Copy, - E: 'a, -{ - loc(map( - specialize_err(move |_, pos| to_expectation(pos), ident::uppercase()), - Spaced::Item, - )) -} - -fn exposes_entry<'a, F, E>( - to_expectation: F, -) -> impl Parser<'a, Loc>>, E> -where - F: Fn(Position) -> E, - F: Copy, - E: 'a, -{ - loc(map( - specialize_err(move |_, pos| to_expectation(pos), unqualified_ident()), - |n| Spaced::Item(ExposedName::new(n)), - )) -} - -#[inline(always)] -fn requires<'a>( -) -> impl Parser<'a, KeywordItem<'a, RequiresKeyword, PlatformRequires<'a>>, ERequires<'a>> { - record!(KeywordItem { - keyword: spaces_around_keyword( - RequiresKeyword, - ERequires::Requires, - ERequires::IndentRequires, - ERequires::IndentListStart - ), - item: platform_requires(), - }) -} - -#[inline(always)] -fn platform_requires<'a>() -> impl Parser<'a, PlatformRequires<'a>, ERequires<'a>> { - record!(PlatformRequires { - rigids: skip_second(requires_rigids(), space0_e(ERequires::ListStart)), - signature: requires_typed_ident() - }) -} - -#[inline(always)] -fn requires_rigids<'a>( -) -> impl Parser<'a, Collection<'a, Loc>>>, ERequires<'a>> { - collection_trailing_sep_e( - byte(b'{', ERequires::ListStart), - specialize_err( - |_, pos| ERequires::Rigid(pos), - loc(map(ident::uppercase(), Spaced::Item)), - ), - byte(b',', ERequires::ListEnd), - byte(b'}', ERequires::ListEnd), - Spaced::SpaceBefore, - ) -} - -#[inline(always)] -fn requires_typed_ident<'a>() -> impl Parser<'a, Loc>>, ERequires<'a>> { - skip_first( - byte(b'{', ERequires::ListStart), - skip_second( - reset_min_indent(space0_around_ee( - specialize_err(ERequires::TypedIdent, loc(typed_ident())), - ERequires::ListStart, - ERequires::ListEnd, - )), - byte(b'}', ERequires::ListStart), - ), - ) -} - -#[inline(always)] -fn exposes_values_kw<'a>() -> impl Parser< - 'a, - KeywordItem<'a, ExposesKeyword, Collection<'a, Loc>>>>, - EExposes, -> { - record!(KeywordItem { - keyword: exposes_kw(), - item: exposes_list() - }) -} - -#[inline(always)] -fn exposes_kw<'a>() -> impl Parser<'a, Spaces<'a, ExposesKeyword>, EExposes> { - spaces_around_keyword( - ExposesKeyword, - EExposes::Exposes, - EExposes::IndentExposes, - EExposes::IndentListStart, - ) -} - -#[inline(always)] -fn exposes_list<'a>() -> impl Parser<'a, Collection<'a, Loc>>>, EExposes> -{ - collection_trailing_sep_e( - byte(b'[', EExposes::ListStart), - exposes_entry(EExposes::Identifier), - byte(b',', EExposes::ListEnd), - byte(b']', EExposes::ListEnd), - Spaced::SpaceBefore, - ) -} - -pub fn spaces_around_keyword<'a, K: Keyword, E>( - keyword_item: K, - expectation: fn(Position) -> E, - indent_problem1: fn(Position) -> E, - indent_problem2: fn(Position) -> E, -) -> impl Parser<'a, Spaces<'a, K>, E> -where - E: 'a + SpaceProblem, -{ - map( - and( - skip_second( - // parse any leading space before the keyword - backtrackable(space0_e(indent_problem1)), - // parse the keyword - crate::parser::keyword(K::KEYWORD, expectation), - ), - // parse the trailing space - space0_e(indent_problem2), - ), - move |(before, after)| Spaces { - before, - item: keyword_item, - after, - }, - ) -} - -#[inline(always)] -fn exposes_modules<'a>() -> impl Parser< - 'a, - KeywordItem<'a, ExposesKeyword, Collection<'a, Loc>>>>, - EExposes, -> { - record!(KeywordItem { - keyword: spaces_around_keyword( - ExposesKeyword, - EExposes::Exposes, - EExposes::IndentExposes, - EExposes::IndentListStart - ), - item: exposes_module_collection(), - }) -} - -fn exposes_module_collection<'a>( -) -> impl Parser<'a, Collection<'a, Loc>>>, EExposes> { - collection_trailing_sep_e( - byte(b'[', EExposes::ListStart), - exposes_module(EExposes::Identifier), - byte(b',', EExposes::ListEnd), - byte(b']', EExposes::ListEnd), - Spaced::SpaceBefore, - ) -} - -fn exposes_module<'a, F, E>( - to_expectation: F, -) -> impl Parser<'a, Loc>>, E> -where - F: Fn(Position) -> E, - F: Copy, - E: 'a, -{ - loc(map( - specialize_err(move |_, pos| to_expectation(pos), module_name()), - Spaced::Item, - )) -} - -#[inline(always)] -fn packages<'a>() -> impl Parser< - 'a, - KeywordItem<'a, PackagesKeyword, Collection<'a, Loc>>>>, - EPackages<'a>, -> { - record!(KeywordItem { - keyword: packages_kw(), - item: packages_collection() - }) -} - -#[inline(always)] -fn packages_kw<'a>() -> impl Parser<'a, Spaces<'a, PackagesKeyword>, EPackages<'a>> { - spaces_around_keyword( - PackagesKeyword, - EPackages::Packages, - EPackages::IndentPackages, - EPackages::IndentListStart, - ) -} - -#[inline(always)] -fn packages_collection<'a>( -) -> impl Parser<'a, Collection<'a, Loc>>>, EPackages<'a>> { - collection_trailing_sep_e( - byte(b'{', EPackages::ListStart), - specialize_err(EPackages::PackageEntry, loc(package_entry())), - byte(b',', EPackages::ListEnd), - byte(b'}', EPackages::ListEnd), - Spaced::SpaceBefore, - ) -} - -fn imports<'a>() -> impl Parser< - 'a, - KeywordItem<'a, ImportsKeyword, Collection<'a, Loc>>>>, - EImports, -> { - record!(KeywordItem { - keyword: spaces_around_keyword( - ImportsKeyword, - EImports::Imports, - EImports::IndentImports, - EImports::IndentListStart - ), - item: collection_trailing_sep_e( - byte(b'[', EImports::ListStart), - loc(imports_entry()), - byte(b',', EImports::ListEnd), - byte(b']', EImports::ListEnd), - Spaced::SpaceBefore - ) - }) - .trace("imports") -} - -#[inline(always)] -pub fn typed_ident<'a>() -> impl Parser<'a, Spaced<'a, TypedIdent<'a>>, ETypedIdent<'a>> { - // e.g. - // - // printLine : Str -> Task {} * - map( - and( - and( - loc(specialize_err( - |_, pos| ETypedIdent::Identifier(pos), - lowercase_ident(), - )), - space0_e(ETypedIdent::IndentHasType), - ), - skip_first( - byte(b':', ETypedIdent::HasType), - space0_before_e( - specialize_err( - ETypedIdent::Type, - reset_min_indent(type_annotation::located(true)), - ), - ETypedIdent::IndentType, - ), - ), - ), - |((ident, spaces_before_colon), ann)| { - Spaced::Item(TypedIdent { - ident, - spaces_before_colon, - ann, - }) - }, - ) -} - -fn shortname<'a>() -> impl Parser<'a, &'a str, EImports> { - specialize_err(|_, pos| EImports::Shorthand(pos), lowercase_ident()) -} - -pub fn module_name_help<'a, F, E>(to_expectation: F) -> impl Parser<'a, ModuleName<'a>, E> -where - F: Fn(Position) -> E, - E: 'a, - F: 'a, -{ - specialize_err(move |_, pos| to_expectation(pos), module_name()) -} - -#[inline(always)] -fn imports_entry<'a>() -> impl Parser<'a, Spaced<'a, ImportsEntry<'a>>, EImports> { - type Temp<'a> = ( - (Option<&'a str>, ModuleName<'a>), - Option>>>>, - ); - - let spaced_import = |((opt_shortname, module_name), opt_values): Temp<'a>| { - let exposed_values = opt_values.unwrap_or_else(Collection::empty); - - let entry = match opt_shortname { - Some(shortname) => ImportsEntry::Package(shortname, module_name, exposed_values), - - None => ImportsEntry::Module(module_name, exposed_values), - }; - - Spaced::Item(entry) - }; - - one_of!( - map( - and( - and( - // e.g. `pf.` - optional(backtrackable(skip_second( - shortname(), - byte(b'.', EImports::ShorthandDot) - ))), - // e.g. `Task` - module_name_help(EImports::ModuleName) - ), - // e.g. `.{ Task, after}` - optional(skip_first( - byte(b'.', EImports::ExposingDot), - collection_trailing_sep_e( - byte(b'{', EImports::SetStart), - exposes_entry(EImports::Identifier), - byte(b',', EImports::SetEnd), - byte(b'}', EImports::SetEnd), - Spaced::SpaceBefore - ) - )) - ), - spaced_import - ) - .trace("normal_import"), - map( - and( - and( - // e.g. "filename" - // TODO: str literal allows for multiline strings. We probably don't want that for file names. - specialize_err(|_, pos| EImports::StrLiteral(pos), parse_str_literal()), - // e.g. as - and( - and( - space0_e(EImports::AsKeyword), - two_bytes(b'a', b's', EImports::AsKeyword) - ), - space0_e(EImports::AsKeyword) - ) - ), - // e.g. file : Str - specialize_err(|_, pos| EImports::TypedIdent(pos), typed_ident()) - ), - |((file_name, _), typed_ident)| { - // TODO: look at blacking block strings during parsing. - Spaced::Item(ImportsEntry::IngestedFile(file_name, typed_ident)) - } - ) - .trace("ingest_file_import") - ) - .trace("imports_entry") -} diff --git a/crates/compiler/parse/src/normalize.rs b/crates/compiler/parse/src/normalize.rs index 8561279b8f6..a1def6c6776 100644 --- a/crates/compiler/parse/src/normalize.rs +++ b/crates/compiler/parse/src/normalize.rs @@ -8,9 +8,9 @@ use crate::{ AbilityImpls, AbilityMember, AssignedField, Collection, Defs, Expr, FullAst, Header, Implements, ImplementsAbilities, ImplementsAbility, ImplementsClause, ImportAlias, ImportAsKeyword, ImportExposingKeyword, ImportedModuleName, IngestedFileAnnotation, - IngestedFileImport, ModuleImport, ModuleImportParams, OldRecordBuilderField, Pattern, - PatternAs, Spaced, Spaces, SpacesBefore, StrLiteral, StrSegment, Tag, TypeAnnotation, - TypeDef, TypeHeader, ValueDef, WhenBranch, + IngestedFileImport, ModuleImport, ModuleImportParams, Pattern, PatternAs, Spaced, Spaces, + SpacesBefore, StrLiteral, StrSegment, Tag, TypeAnnotation, TypeDef, TypeHeader, ValueDef, + WhenBranch, }, header::{ AppHeader, ExposedName, ExposesKeyword, HostedHeader, ImportsEntry, ImportsKeyword, @@ -562,30 +562,6 @@ impl<'a, T: Normalize<'a> + Copy + std::fmt::Debug> Normalize<'a> for AssignedFi } } -impl<'a> Normalize<'a> for OldRecordBuilderField<'a> { - fn normalize(&self, arena: &'a Bump) -> Self { - match *self { - OldRecordBuilderField::Value(a, _, c) => OldRecordBuilderField::Value( - a.normalize(arena), - &[], - arena.alloc(c.normalize(arena)), - ), - OldRecordBuilderField::ApplyValue(a, _, _, c) => OldRecordBuilderField::ApplyValue( - a.normalize(arena), - &[], - &[], - arena.alloc(c.normalize(arena)), - ), - OldRecordBuilderField::LabelOnly(a) => { - OldRecordBuilderField::LabelOnly(a.normalize(arena)) - } - OldRecordBuilderField::Malformed(a) => OldRecordBuilderField::Malformed(a), - OldRecordBuilderField::SpaceBefore(a, _) => a.normalize(arena), - OldRecordBuilderField::SpaceAfter(a, _) => a.normalize(arena), - } - } -} - impl<'a> Normalize<'a> for StrLiteral<'a> { fn normalize(&self, arena: &'a Bump) -> Self { match *self { @@ -738,7 +714,6 @@ impl<'a> Normalize<'a> for Expr<'a> { fields: fields.normalize(arena), }, Expr::Record(a) => Expr::Record(a.normalize(arena)), - Expr::OldRecordBuilder(a) => Expr::OldRecordBuilder(a.normalize(arena)), Expr::RecordBuilder { mapper, fields } => Expr::RecordBuilder { mapper: arena.alloc(mapper.normalize(arena)), fields: fields.normalize(arena), @@ -817,12 +792,6 @@ impl<'a> Normalize<'a> for Expr<'a> { Expr::SpaceBefore(a, _) => a.normalize(arena), Expr::SpaceAfter(a, _) => a.normalize(arena), Expr::SingleQuote(a) => Expr::Num(a), - Expr::MultipleOldRecordBuilders(a) => { - Expr::MultipleOldRecordBuilders(arena.alloc(a.normalize(arena))) - } - Expr::UnappliedOldRecordBuilder(a) => { - Expr::UnappliedOldRecordBuilder(arena.alloc(a.normalize(arena))) - } Expr::EmptyRecordBuilder(a) => { Expr::EmptyRecordBuilder(arena.alloc(a.normalize(arena))) } @@ -1092,12 +1061,6 @@ impl<'a> Normalize<'a> for EExpr<'a> { EExpr::Record(inner_err, _pos) => { EExpr::Record(inner_err.normalize(arena), Position::zero()) } - EExpr::OptionalValueInOldRecordBuilder(_pos) => { - EExpr::OptionalValueInOldRecordBuilder(Region::zero()) - } - EExpr::IgnoredValueInOldRecordBuilder(_pos) => { - EExpr::OptionalValueInOldRecordBuilder(Region::zero()) - } EExpr::Str(inner_err, _pos) => EExpr::Str(inner_err.normalize(arena), Position::zero()), EExpr::Number(inner_err, _pos) => EExpr::Number(inner_err.clone(), Position::zero()), EExpr::List(inner_err, _pos) => { @@ -1331,7 +1294,6 @@ impl<'a> Normalize<'a> for EImportParams<'a> { EImportParams::Record(inner_err.normalize(arena), Position::zero()) } EImportParams::RecordUpdateFound(_) => EImportParams::RecordUpdateFound(Region::zero()), - EImportParams::RecordApplyFound(_) => EImportParams::RecordApplyFound(Region::zero()), EImportParams::RecordIgnoredFieldFound(_) => { EImportParams::RecordIgnoredFieldFound(Region::zero()) } diff --git a/crates/compiler/parse/src/parser.rs b/crates/compiler/parse/src/parser.rs index a5e0900a66f..71ebcf647b5 100644 --- a/crates/compiler/parse/src/parser.rs +++ b/crates/compiler/parse/src/parser.rs @@ -344,8 +344,6 @@ pub enum EExpr<'a> { InParens(EInParens<'a>, Position), Record(ERecord<'a>, Position), - OptionalValueInOldRecordBuilder(Region), - IgnoredValueInOldRecordBuilder(Region), RecordUpdateOldBuilderField(Region), RecordUpdateIgnoredField(Region), RecordBuilderOldBuilderField(Region), @@ -551,7 +549,6 @@ pub enum EImportParams<'a> { Record(ERecord<'a>, Position), RecordUpdateFound(Region), RecordBuilderFound(Region), - RecordApplyFound(Region), RecordIgnoredFieldFound(Region), Space(BadInputError, Position), } diff --git a/crates/compiler/parse/src/type_annotation.rs b/crates/compiler/parse/src/type_annotation.rs index 2802a902e26..03714e8ea77 100644 --- a/crates/compiler/parse/src/type_annotation.rs +++ b/crates/compiler/parse/src/type_annotation.rs @@ -5,7 +5,7 @@ use crate::ast::{ use crate::blankspace::{ space0_around_ee, space0_before_e, space0_before_optional_after, space0_e, }; -use crate::expr::{record_field, FoundApplyValue}; +use crate::expr::record_field; use crate::ident::{lowercase_ident, lowercase_ident_keyword_e}; use crate::keyword; use crate::parser::{ @@ -565,11 +565,10 @@ fn parse_implements_ability<'a>() -> impl Parser<'a, ImplementsAbility<'a>, ETyp fn ability_impl_field<'a>() -> impl Parser<'a, AssignedField<'a, Expr<'a>>, ERecord<'a>> { then(record_field(), move |arena, state, _, field| { match field.to_assigned_field(arena) { - Ok(AssignedField::IgnoredValue(_, _, _)) => { + AssignedField::IgnoredValue(_, _, _) => { Err((MadeProgress, ERecord::Field(state.pos()))) } - Ok(assigned_field) => Ok((MadeProgress, assigned_field, state)), - Err(FoundApplyValue) => Err((MadeProgress, ERecord::Field(state.pos()))), + assigned_field => Ok((MadeProgress, assigned_field, state)), } }) } diff --git a/crates/compiler/problem/src/can.rs b/crates/compiler/problem/src/can.rs index 5c6383eb875..31af6a39aa9 100644 --- a/crates/compiler/problem/src/can.rs +++ b/crates/compiler/problem/src/can.rs @@ -427,8 +427,6 @@ impl Problem { | Problem::RuntimeError(RuntimeError::EmptySingleQuote(region)) | Problem::RuntimeError(RuntimeError::MultipleCharsInSingleQuote(region)) | Problem::RuntimeError(RuntimeError::DegenerateBranch(region)) - | Problem::RuntimeError(RuntimeError::MultipleOldRecordBuilders(region)) - | Problem::RuntimeError(RuntimeError::UnappliedOldRecordBuilder(region)) | Problem::RuntimeError(RuntimeError::EmptyRecordBuilder(region)) | Problem::RuntimeError(RuntimeError::SingleFieldRecordBuilder(region)) | Problem::RuntimeError(RuntimeError::OptionalFieldInRecordBuilder { @@ -686,9 +684,6 @@ pub enum RuntimeError { DegenerateBranch(Region), - MultipleOldRecordBuilders(Region), - UnappliedOldRecordBuilder(Region), - EmptyRecordBuilder(Region), SingleFieldRecordBuilder(Region), OptionalFieldInRecordBuilder { @@ -739,8 +734,6 @@ impl RuntimeError { | RuntimeError::DegenerateBranch(region) | RuntimeError::InvalidInterpolation(region) | RuntimeError::InvalidHexadecimal(region) - | RuntimeError::MultipleOldRecordBuilders(region) - | RuntimeError::UnappliedOldRecordBuilder(region) | RuntimeError::EmptyRecordBuilder(region) | RuntimeError::SingleFieldRecordBuilder(region) | RuntimeError::OptionalFieldInRecordBuilder { diff --git a/crates/compiler/test_syntax/tests/test_fmt.rs b/crates/compiler/test_syntax/tests/test_fmt.rs index ace412cf3ad..a6349f2c8b6 100644 --- a/crates/compiler/test_syntax/tests/test_fmt.rs +++ b/crates/compiler/test_syntax/tests/test_fmt.rs @@ -1986,7 +1986,7 @@ mod test_fmt { } #[test] - fn new_record_builder() { + fn record_builder() { expr_formats_same(indoc!( r" { shoes <- leftShoe: nothing } @@ -2077,170 +2077,6 @@ mod test_fmt { ); } - #[test] - fn old_record_builder() { - expr_formats_same(indoc!( - r#" - { a: 1, b: <- get "b" |> batch, c: <- get "c" |> batch, d } - "# - )); - - expr_formats_to( - indoc!( - r#" - { a: 1, b: <- get "b" |> batch, c:<- get "c" |> batch } - "# - ), - indoc!( - r#" - { a: 1, b: <- get "b" |> batch, c: <- get "c" |> batch } - "# - ), - ); - - expr_formats_same(indoc!( - r#" - { - a: 1, - b: <- get "b" |> batch, - c: <- get "c" |> batch, - d, - } - "# - )); - - expr_formats_to( - indoc!( - r#" - { a: 1, b: <- get "b" |> batch, - c: <- get "c" |> batch, d } - "# - ), - indoc!( - r#" - { - a: 1, - b: <- get "b" |> batch, - c: <- get "c" |> batch, - d, - } - "# - ), - ); - } - - #[test] - fn multiline_record_builder_field() { - expr_formats_to( - indoc!( - r#" - succeed { - a: <- get "a" |> map (\x -> x * 2) - |> batch, - b: <- get "b" |> batch, - c: items - |> List.map \x -> x * 2 - } - "# - ), - indoc!( - r#" - succeed { - a: <- - get "a" - |> map (\x -> x * 2) - |> batch, - b: <- get "b" |> batch, - c: - items - |> List.map \x -> x * 2, - } - "# - ), - ); - - expr_formats_same(indoc!( - r#" - succeed { - a: # I like to comment in weird places - <- get "a" |> batch, - b: <- get "b" |> batch, - } - "# - )); - - expr_formats_same(indoc!( - r#" - succeed { - a: - # I like to comment in weird places - <- get "a" |> batch, - b: <- get "b" |> batch, - } - "# - )); - } - - #[test] - fn outdentable_record_builders() { - expr_formats_to( - indoc!( - r#" - succeed { a: <- get "a" |> batch, - b: <- get "b" |> batch, - } - "# - ), - indoc!( - r#" - succeed { - a: <- get "a" |> batch, - b: <- get "b" |> batch, - } - "# - ), - ); - - expr_formats_to( - indoc!( - r#" - succeed - { - a: <- get "a" |> batch, - b: <- get "b" |> batch, - } - "# - ), - indoc!( - r#" - succeed { - a: <- get "a" |> batch, - b: <- get "b" |> batch, - } - "# - ), - ); - } - - #[test] - fn can_format_multiple_record_builders() { - expr_formats_to( - indoc!( - r#" - succeed { a: <- get "a" } - { b: <- get "b" } - "# - ), - indoc!( - r#" - succeed - { a: <- get "a" } - { b: <- get "b" } - "# - ), - ); - } - #[test] fn final_comments_in_records() { expr_formats_same(indoc!( diff --git a/crates/language_server/src/analysis/tokens.rs b/crates/language_server/src/analysis/tokens.rs index b923712f4f5..10918316ec7 100644 --- a/crates/language_server/src/analysis/tokens.rs +++ b/crates/language_server/src/analysis/tokens.rs @@ -6,9 +6,8 @@ use roc_module::called_via::{BinOp, UnaryOp}; use roc_parse::{ ast::{ AbilityImpls, AbilityMember, AssignedField, Collection, Defs, Expr, Header, Implements, - ImplementsAbilities, ImplementsAbility, ImplementsClause, OldRecordBuilderField, Pattern, - PatternAs, Spaced, StrLiteral, Tag, TypeAnnotation, TypeDef, TypeHeader, ValueDef, - WhenBranch, + ImplementsAbilities, ImplementsAbility, ImplementsClause, Pattern, PatternAs, Spaced, + StrLiteral, Tag, TypeAnnotation, TypeDef, TypeHeader, ValueDef, WhenBranch, }, header::{ AppHeader, ExposedName, HostedHeader, ImportsEntry, ModuleHeader, ModuleName, ModuleParams, @@ -672,7 +671,6 @@ impl IterTokens for Loc> { .collect_in(arena), Expr::Record(rcd) => rcd.iter_tokens(arena), Expr::Tuple(tup) => tup.iter_tokens(arena), - Expr::OldRecordBuilder(rb) => rb.iter_tokens(arena), Expr::RecordBuilder { mapper, fields } => (mapper.iter_tokens(arena).into_iter()) .chain(fields.iter().flat_map(|f| f.iter_tokens(arena))) .collect_in(arena), @@ -724,8 +722,6 @@ impl IterTokens for Loc> { Loc::at(region, *e).iter_tokens(arena) } Expr::ParensAround(e) => Loc::at(region, *e).iter_tokens(arena), - Expr::MultipleOldRecordBuilders(e) => e.iter_tokens(arena), - Expr::UnappliedOldRecordBuilder(e) => e.iter_tokens(arena), Expr::EmptyRecordBuilder(e) => e.iter_tokens(arena), Expr::SingleFieldRecordBuilder(e) => e.iter_tokens(arena), Expr::OptionalFieldInRecordBuilder(_name, e) => e.iter_tokens(arena), @@ -748,24 +744,6 @@ impl IterTokens for Loc> { } } -impl IterTokens for Loc> { - fn iter_tokens<'a>(&self, arena: &'a Bump) -> BumpVec<'a, Loc> { - match self.value { - OldRecordBuilderField::Value(field, _, e) - | OldRecordBuilderField::ApplyValue(field, _, _, e) => field_token(field.region, arena) - .into_iter() - .chain(e.iter_tokens(arena)) - .collect_in(arena), - OldRecordBuilderField::LabelOnly(field) => field_token(field.region, arena), - OldRecordBuilderField::SpaceBefore(rbf, _) - | OldRecordBuilderField::SpaceAfter(rbf, _) => { - Loc::at(self.region, *rbf).iter_tokens(arena) - } - OldRecordBuilderField::Malformed(_) => bumpvec![in arena;], - } - } -} - impl IterTokens for &WhenBranch<'_> { fn iter_tokens<'a>(&self, arena: &'a Bump) -> BumpVec<'a, Loc> { let WhenBranch { diff --git a/crates/reporting/src/error/canonicalize.rs b/crates/reporting/src/error/canonicalize.rs index efbd05994f7..7e60ea07294 100644 --- a/crates/reporting/src/error/canonicalize.rs +++ b/crates/reporting/src/error/canonicalize.rs @@ -2488,32 +2488,6 @@ fn pretty_runtime_error<'b>( title = "DEGENERATE BRANCH"; } - RuntimeError::MultipleOldRecordBuilders(region) => { - let tip = alloc - .tip() - .append(alloc.reflow("You can combine them or apply them separately.")); - - doc = alloc.stack([ - alloc.reflow("This function is applied to multiple old-style record builders:"), - alloc.region(lines.convert_region(region), severity), - alloc.note("Functions can only take at most one old-style record builder!"), - tip, - ]); - - title = "MULTIPLE OLD-STYLE RECORD BUILDERS"; - } - RuntimeError::UnappliedOldRecordBuilder(region) => { - doc = alloc.stack([ - alloc.reflow("This old-style record builder was not applied to a function:"), - alloc.region(lines.convert_region(region), severity), - alloc.reflow("However, we need a function to construct the record."), - alloc.note( - "Functions must be applied directly. The pipe operator (|>) cannot be used.", - ), - ]); - - title = "UNAPPLIED OLD-STYLE RECORD BUILDER"; - } RuntimeError::EmptyRecordBuilder(region) => { doc = alloc.stack([ alloc.reflow("This record builder has no fields:"), diff --git a/crates/reporting/src/error/parse.rs b/crates/reporting/src/error/parse.rs index 79e83a7e189..20ec3cce560 100644 --- a/crates/reporting/src/error/parse.rs +++ b/crates/reporting/src/error/parse.rs @@ -545,46 +545,6 @@ fn to_expr_report<'a>( to_record_report(alloc, lines, filename, erecord, *pos, start) } - EExpr::OptionalValueInOldRecordBuilder(region) => { - let surroundings = Region::new(start, region.end()); - let region = lines.convert_region(*region); - - let doc = alloc.stack([ - alloc.reflow( - r"I am partway through parsing a record builder, and I found an optional field:", - ), - alloc.region_with_subregion(lines.convert_region(surroundings), region, severity), - alloc.reflow("Optional fields can only appear when you destructure a record."), - ]); - - Report { - filename, - doc, - title: "BAD OLD-STYLE RECORD BUILDER".to_string(), - severity, - } - } - - EExpr::RecordUpdateOldBuilderField(region) => { - let surroundings = Region::new(start, region.end()); - let region = lines.convert_region(*region); - - let doc = alloc.stack([ - alloc.reflow( - r"I am partway through parsing a record update, and I found an old-style record builder field:", - ), - alloc.region_with_subregion(lines.convert_region(surroundings), region, severity), - alloc.reflow("Old-style record builders cannot be updated like records."), - ]); - - Report { - filename, - doc, - title: "BAD RECORD UPDATE".to_string(), - severity, - } - } - EExpr::Space(error, pos) => to_space_report(alloc, lines, filename, error, *pos), &EExpr::Number(ENumber::End, pos) => { @@ -1550,23 +1510,6 @@ fn to_import_report<'a>( Params(EImportParams::Record(problem, pos), _) => { to_record_report(alloc, lines, filename, problem, *pos, start) } - Params(EImportParams::RecordApplyFound(region), _) => { - let surroundings = Region::new(start, region.end()); - let region = lines.convert_region(*region); - - let doc = alloc.stack([ - alloc.reflow("I was partway through parsing module params, but I got stuck here:"), - alloc.region_with_subregion(lines.convert_region(surroundings), region, severity), - alloc.reflow("This looks like an old-style record builder field, but those are not allowed in module params."), - ]); - - Report { - filename, - doc, - title: "OLD-STYLE RECORD BUILDER IN MODULE PARAMS".to_string(), - severity, - } - } Params(EImportParams::RecordIgnoredFieldFound(region), _) => { let surroundings = Region::new(start, region.end()); let region = lines.convert_region(*region); diff --git a/crates/reporting/src/error/type.rs b/crates/reporting/src/error/type.rs index 9256289ab98..23fed78a231 100644 --- a/crates/reporting/src/error/type.rs +++ b/crates/reporting/src/error/type.rs @@ -1238,14 +1238,7 @@ fn to_expr_report<'b>( ), ]), alloc.region(lines.convert_region(expr_region), severity), - match called_via { - CalledVia::OldRecordBuilder => { - alloc.hint("Did you mean to apply it to a function first?") - }, - _ => { - alloc.reflow("I can't call an opaque type because I don't know what it is! Maybe you meant to unwrap it first?") - } - } + alloc.reflow("I can't call an opaque type because I don't know what it is! Maybe you meant to unwrap it first?"), ]), Other => alloc.stack([ alloc.concat([ @@ -1261,14 +1254,6 @@ fn to_expr_report<'b>( ]), alloc.region(lines.convert_region(expr_region), severity), match called_via { - CalledVia::OldRecordBuilder => { - alloc.concat([ - alloc.tip(), - alloc.reflow("Remove "), - alloc.backpassing_arrow(), - alloc.reflow(" to assign the field directly.") - ]) - } CalledVia::RecordBuilder => { alloc.concat([ alloc.note(""), diff --git a/www/content/tutorial.md b/www/content/tutorial.md index a282b47e7c9..9532fc1b655 100644 --- a/www/content/tutorial.md +++ b/www/content/tutorial.md @@ -2311,8 +2311,6 @@ expect If you want to see other examples of using record builders, look at the [Record Builder Example](https://www.roc-lang.org/examples/RecordBuilder/README.html) for a moderately-sized example or the [Arg.Builder](https://github.com/roc-lang/basic-cli/blob/main/platform/Arg/Builder.roc) module in our `basic-cli` platform for a complex example. -_Note: This syntax replaces the old `field: <- value` record builder syntax using applicative functors because it is much simpler to understand and use. The old syntax will be removed soon._ - ### [Reserved Keywords](#reserved-keywords) {#reserved-keywords} These are reserved keywords in Roc. You can't choose any of them as names, except as record field names. From cef2c8ae875633963064f75fb9fdbc2a22ebefc8 Mon Sep 17 00:00:00 2001 From: Ayaz <20735482+ayazhafiz@users.noreply.github.com> Date: Sat, 21 Sep 2024 09:50:17 -0400 Subject: [PATCH 21/22] Update build.rs Signed-off-by: Ayaz <20735482+ayazhafiz@users.noreply.github.com> --- crates/compiler/gen_llvm/src/llvm/build.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index fa3c51a4582..79cc09f19e4 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -2915,14 +2915,16 @@ fn list_literal<'a, 'ctx>( let list_length = elems.len(); let list_length_intval = env.ptr_int().const_int(list_length as _, false); - // Anything that requires refcounting contains nested pointers. - // Nested pointers in globals will break the surgical linker. - // For now, block them from being constants. let is_refcounted = layout_interner.contains_refcounted(element_layout); - // NOTE: we should be able to create a constant of records, but these literals are only primitives. let is_all_constant = elems.iter().all(|e| e.is_literal()); if is_all_constant && !is_refcounted { + // Build a global literal in-place instead of GEPing and storing individual elements. + // Exceptions: + // - Anything that is refcounted has nested pointers, + // and nested pointers in globals will break the surgical linker. + // Ignore such cases for now. + let element_width = layout_interner.stack_size(element_layout); let alignment = layout_interner @@ -2938,7 +2940,6 @@ fn list_literal<'a, 'ctx>( assert!(refcount_slot_elements > 0); - // There must be a generic way to do this, but types here are making me duplicate code. let global = if element_type.is_int_type() { let element_type = element_type.into_int_type(); let mut bytes = Vec::with_capacity_in(refcount_slot_elements + data_bytes, env.arena); @@ -2990,10 +2991,9 @@ fn list_literal<'a, 'ctx>( global.set_unnamed_addr(true); global.set_linkage(inkwell::module::Linkage::Private); - // Currently, morphic will break if we use the global directly. - // It will attempt to update the global in place. - // This is invalid due to putting the global in the read only section. - // For now, eagerly copy the global into a new allocation with unique refcount. + // Refcount the global itself in a new allocation. + // Necessary because morphic MAY attempt to update the global in-place, which is + // illegal if the global is in the read-only section. let with_rc_ptr = global.as_pointer_value(); let const_data_ptr = unsafe { From 568343f2e7d9850bd987afae9cd268e681172c2d Mon Sep 17 00:00:00 2001 From: Anton-4 <17049058+Anton-4@users.noreply.github.com> Date: Sun, 22 Sep 2024 16:43:37 +0200 Subject: [PATCH 22/22] Update tutorial _ Support for e.g. `RunErr : _` got removed 4 months ago. [More context](https://roc.zulipchat.com/#narrow/stream/231634-beginners/topic/.E2.9C.94.20Type.20alias.20definitions.20may.20not.20use.20inferred.20types/near/472047806). Signed-off-by: Anton-4 <17049058+Anton-4@users.noreply.github.com> --- www/content/tutorial.md | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/www/content/tutorial.md b/www/content/tutorial.md index 9532fc1b655..2524d006a30 100644 --- a/www/content/tutorial.md +++ b/www/content/tutorial.md @@ -1807,22 +1807,6 @@ This is a useful technique to use when we don't want to write out a bunch of err - If we're using an editor that supports it, hovering over the `_` might display the inferred type that goes there. - We can put an obviously wrong type in there (e.g. replace the `{}` with `Str`, which is totally wrong) and look at the compiler error to see what it inferred as the correct type. -We can also use `_` in type aliases, to express that two types are the same without annotating either of them. For example: - -```roc -RunErr : _ -``` - -```roc -run : Task {} RunErr -``` - -```roc -handleErr : RunErr -> [Exit I32 Str] -``` - -Of course, we could also choose not to use `_` at all and populate the `RunErr` type alias with the full list of errors that could happen in our `run` task. All of these are totally reasonable stylistic choices, depending on how you prefer the code to look. They all compile to exactly the same thing, and have the same runtime characteristics. - ### [The ! suffix](#the-!-suffix) {#the-!-suffix} The `!` suffix operator is syntax sugar for the `Task.await` function, which has this type: