mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-02 19:32:17 +00:00
Merge branch 'roc-lang:main' into list-update
This commit is contained in:
commit
c22a9ef8b5
28 changed files with 307 additions and 305 deletions
44
Cargo.lock
generated
44
Cargo.lock
generated
|
@ -612,17 +612,6 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "confy"
|
||||
version = "0.5.1"
|
||||
source = "git+https://github.com/rust-cli/confy#d5abd6cce9b936130832cfb4e1ed8afd7e1c488b"
|
||||
dependencies = [
|
||||
"directories",
|
||||
"serde",
|
||||
"serde_yaml",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "console"
|
||||
version = "0.15.5"
|
||||
|
@ -1035,15 +1024,6 @@ dependencies = [
|
|||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "directories"
|
||||
version = "4.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f51c5d4ddabd36886dd3e1438cb358cdcb0d7c499cb99cb4ac2e38e18b5cb210"
|
||||
dependencies = [
|
||||
"dirs-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-next"
|
||||
version = "2.0.0"
|
||||
|
@ -1054,17 +1034,6 @@ dependencies = [
|
|||
"dirs-sys-next",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys-next"
|
||||
version = "0.1.2"
|
||||
|
@ -3395,7 +3364,6 @@ dependencies = [
|
|||
"bytemuck",
|
||||
"cgmath",
|
||||
"colored",
|
||||
"confy",
|
||||
"copypasta",
|
||||
"fs_extra",
|
||||
"futures",
|
||||
|
@ -4286,18 +4254,6 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_yaml"
|
||||
version = "0.8.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"ryu",
|
||||
"serde",
|
||||
"yaml-rust",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serial_test"
|
||||
version = "1.0.0"
|
||||
|
|
|
@ -84,7 +84,6 @@ capstone = { version = "0.11.0", default-features = false }
|
|||
cgmath = "0.18.0"
|
||||
clap = { version = "4.2.7", default-features = false, features = ["std", "color", "suggestions", "help", "usage", "error-context"] }
|
||||
colored = "2.0.0"
|
||||
confy = { git = 'https://github.com/rust-cli/confy', features = ["yaml_conf"], default-features = false }
|
||||
console_error_panic_hook = "0.1.7"
|
||||
const_format = { version = "0.2.30", features = ["const_generics"] }
|
||||
copypasta = "0.8.2"
|
||||
|
|
|
@ -44,6 +44,8 @@ pub const RocDec = extern struct {
|
|||
return ret;
|
||||
}
|
||||
|
||||
// TODO: If Str.toDec eventually supports more error types, return errors here.
|
||||
// For now, just return null which will give the default error.
|
||||
pub fn fromStr(roc_str: RocStr) ?RocDec {
|
||||
if (roc_str.isEmpty()) {
|
||||
return null;
|
||||
|
@ -79,7 +81,8 @@ pub const RocDec = extern struct {
|
|||
|
||||
var after_str_len = (length - 1) - pi;
|
||||
if (after_str_len > decimal_places) {
|
||||
@panic("TODO runtime exception for too many decimal places!");
|
||||
// TODO: runtime exception for too many decimal places!
|
||||
return null;
|
||||
}
|
||||
var diff_decimal_places = decimal_places - after_str_len;
|
||||
|
||||
|
@ -96,7 +99,8 @@ pub const RocDec = extern struct {
|
|||
var result: i128 = undefined;
|
||||
var overflowed = @mulWithOverflow(i128, before, one_point_zero_i128, &result);
|
||||
if (overflowed) {
|
||||
@panic("TODO runtime exception for overflow!");
|
||||
// TODO: runtime exception for overflow!
|
||||
return null;
|
||||
}
|
||||
before_val_i128 = result;
|
||||
}
|
||||
|
@ -107,7 +111,8 @@ pub const RocDec = extern struct {
|
|||
var result: i128 = undefined;
|
||||
var overflowed = @addWithOverflow(i128, before, after, &result);
|
||||
if (overflowed) {
|
||||
@panic("TODO runtime exception for overflow!");
|
||||
// TODO: runtime exception for overflow!
|
||||
return null;
|
||||
}
|
||||
break :blk .{ .num = result };
|
||||
} else {
|
||||
|
@ -184,7 +189,7 @@ pub const RocDec = extern struct {
|
|||
position += 1;
|
||||
|
||||
const trailing_zeros: u6 = count_trailing_zeros_base10(num);
|
||||
if (trailing_zeros == decimal_places) {
|
||||
if (trailing_zeros >= decimal_places) {
|
||||
// add just a single zero if all decimal digits are zero
|
||||
str_bytes[position] = '0';
|
||||
position += 1;
|
||||
|
@ -851,6 +856,14 @@ test "fromStr: .123.1" {
|
|||
try expectEqual(dec, null);
|
||||
}
|
||||
|
||||
test "toStr: 100.00" {
|
||||
var dec: RocDec = .{ .num = 100000000000000000000 };
|
||||
var res_roc_str = dec.toStr();
|
||||
|
||||
const res_slice: []const u8 = "100.0"[0..];
|
||||
try expectEqualSlices(u8, res_slice, res_roc_str.asSlice());
|
||||
}
|
||||
|
||||
test "toStr: 123.45" {
|
||||
var dec: RocDec = .{ .num = 123450000000000000000 };
|
||||
var res_roc_str = dec.toStr();
|
||||
|
|
|
@ -95,7 +95,7 @@ Dict k v := {
|
|||
# TODO: define Eq and Hash that are unordered. Only if value has hash/eq?
|
||||
metadata : List I8,
|
||||
dataIndices : List Nat,
|
||||
data : List (T k v),
|
||||
data : List (k, v),
|
||||
size : Nat,
|
||||
} | k has Hash & Eq
|
||||
has [
|
||||
|
@ -175,12 +175,12 @@ single = \k, v ->
|
|||
## |> Dict.insert 2 "Two"
|
||||
## |> Dict.insert 3 "Three"
|
||||
## |> Dict.insert 4 "Four"
|
||||
## |> Bool.isEq (Dict.fromList [T 1 "One", T 2 "Two", T 3 "Three", T 4 "Four"])
|
||||
## |> Bool.isEq (Dict.fromList [(1, "One"), (2, "Two"), (3, "Three"), (4, "Four")])
|
||||
## ```
|
||||
fromList : List (T k v) -> Dict k v | k has Hash & Eq
|
||||
fromList : List (k, v) -> Dict k v | k has Hash & Eq
|
||||
fromList = \data ->
|
||||
# TODO: make this efficient. Should just set data and then set all indicies in the hashmap.
|
||||
List.walk data (empty {}) (\dict, T k v -> insert dict k v)
|
||||
List.walk data (empty {}) (\dict, (k, v) -> insert dict k v)
|
||||
|
||||
## Returns the number of values in the dictionary.
|
||||
## ```
|
||||
|
@ -238,7 +238,7 @@ clear = \@Dict { metadata, dataIndices, data } ->
|
|||
## ```
|
||||
walk : Dict k v, state, (state, k, v -> state) -> state | k has Hash & Eq
|
||||
walk = \@Dict { data }, initialState, transform ->
|
||||
List.walk data initialState (\state, T k v -> transform state k v)
|
||||
List.walk data initialState (\state, (k, v) -> transform state k v)
|
||||
|
||||
## Same as [Dict.walk], except you can stop walking early.
|
||||
##
|
||||
|
@ -270,7 +270,7 @@ walk = \@Dict { data }, initialState, transform ->
|
|||
## ```
|
||||
walkUntil : Dict k v, state, (state, k, v -> [Continue state, Break state]) -> state | k has Hash & Eq
|
||||
walkUntil = \@Dict { data }, initialState, transform ->
|
||||
List.walkUntil data initialState (\state, T k v -> transform state k v)
|
||||
List.walkUntil data initialState (\state, (k, v) -> transform state k v)
|
||||
|
||||
## Get the value for a given key. If there is a value for the specified key it
|
||||
## will return [Ok value], otherwise return [Err KeyNotFound].
|
||||
|
@ -296,7 +296,7 @@ get = \@Dict { metadata, dataIndices, data }, key ->
|
|||
when findIndexHelper metadata dataIndices data h2Key key probe 0 is
|
||||
Ok index ->
|
||||
dataIndex = listGetUnsafe dataIndices index
|
||||
(T _ v) = listGetUnsafe data dataIndex
|
||||
(_, v) = listGetUnsafe data dataIndex
|
||||
|
||||
Ok v
|
||||
|
||||
|
@ -353,7 +353,7 @@ insert = \@Dict { metadata, dataIndices, data, size }, key, value ->
|
|||
@Dict {
|
||||
metadata,
|
||||
dataIndices,
|
||||
data: List.set data dataIndex (T key value),
|
||||
data: List.set data dataIndex (key, value),
|
||||
size,
|
||||
}
|
||||
|
||||
|
@ -447,9 +447,9 @@ update = \dict, key, alter ->
|
|||
## |> Dict.insert 3 "Three"
|
||||
## |> Dict.insert 4 "Four"
|
||||
## |> Dict.toList
|
||||
## |> Bool.isEq [T 1 "One", T 2 "Two", T 3 "Three", T 4 "Four"]
|
||||
## |> Bool.isEq [(1, "One"), (2, "Two"), (3, "Three"), (4, "Four")]
|
||||
## ```
|
||||
toList : Dict k v -> List (T k v) | k has Hash & Eq
|
||||
toList : Dict k v -> List (k, v) | k has Hash & Eq
|
||||
toList = \@Dict { data } ->
|
||||
data
|
||||
|
||||
|
@ -466,7 +466,7 @@ toList = \@Dict { data } ->
|
|||
## ```
|
||||
keys : Dict k v -> List k | k has Hash & Eq
|
||||
keys = \@Dict { data } ->
|
||||
List.map data (\T k _ -> k)
|
||||
List.map data (\(k, _) -> k)
|
||||
|
||||
## Returns the values of a dictionary as a [List].
|
||||
## This requires allocating a temporary [List], prefer using [Dict.toList] or [Dict.walk] instead.
|
||||
|
@ -481,7 +481,7 @@ keys = \@Dict { data } ->
|
|||
## ```
|
||||
values : Dict k v -> List v | k has Hash & Eq
|
||||
values = \@Dict { data } ->
|
||||
List.map data (\T _ v -> v)
|
||||
List.map data (\(_, v) -> v)
|
||||
|
||||
## Combine two dictionaries by keeping the [union](https://en.wikipedia.org/wiki/Union_(set_theory))
|
||||
## of all the key-value pairs. This means that all the key-value pairs in
|
||||
|
@ -567,7 +567,7 @@ removeAll = \xs, ys ->
|
|||
|
||||
swapAndUpdateDataIndex : Dict k v, Nat, Nat -> Dict k v | k has Hash & Eq
|
||||
swapAndUpdateDataIndex = \@Dict { metadata, dataIndices, data, size }, removedIndex, lastIndex ->
|
||||
(T key _) = listGetUnsafe data lastIndex
|
||||
(key, _) = listGetUnsafe data lastIndex
|
||||
hashKey =
|
||||
createLowLevelHasher PseudoRandSeed
|
||||
|> Hash.hash key
|
||||
|
@ -603,7 +603,7 @@ insertNotFoundHelper = \@Dict { metadata, dataIndices, data, size }, key, value,
|
|||
probe = newProbe h1Key (div8 (List.len metadata))
|
||||
index = nextEmptyOrDeletedHelper metadata probe 0
|
||||
dataIndex = List.len data
|
||||
nextData = List.append data (T key value)
|
||||
nextData = List.append data (key, value)
|
||||
|
||||
@Dict {
|
||||
metadata: List.set metadata index h2Key,
|
||||
|
@ -629,7 +629,7 @@ nextEmptyOrDeletedHelper = \metadata, probe, offset ->
|
|||
|
||||
# TODO: investigate if this needs to be split into more specific helper functions.
|
||||
# There is a chance that returning specific sub-info like the value would be faster.
|
||||
findIndexHelper : List I8, List Nat, List (T k v), I8, k, Probe, Nat -> Result Nat [NotFound] | k has Hash & Eq
|
||||
findIndexHelper : List I8, List Nat, List (k, v), I8, k, Probe, Nat -> Result Nat [NotFound] | k has Hash & Eq
|
||||
findIndexHelper = \metadata, dataIndices, data, h2Key, key, probe, offset ->
|
||||
# For finding a value, we must search past all deleted element tombstones.
|
||||
index = Num.addWrap (mul8 probe.slotIndex) offset
|
||||
|
@ -642,7 +642,7 @@ findIndexHelper = \metadata, dataIndices, data, h2Key, key, probe, offset ->
|
|||
else if md == h2Key then
|
||||
# Potentially matching slot, check if the key is a match.
|
||||
dataIndex = listGetUnsafe dataIndices index
|
||||
(T k _) = listGetUnsafe data dataIndex
|
||||
(k, _) = listGetUnsafe data dataIndex
|
||||
|
||||
if k == key then
|
||||
# We have a match, return its index.
|
||||
|
@ -687,7 +687,7 @@ rehash = \@Dict { metadata, dataIndices, data, size } ->
|
|||
|
||||
rehashHelper newDict metadata dataIndices data 0
|
||||
|
||||
rehashHelper : Dict k v, List I8, List Nat, List (T k v), Nat -> Dict k v | k has Hash & Eq
|
||||
rehashHelper : Dict k v, List I8, List Nat, List (k, v), Nat -> Dict k v | k has Hash & Eq
|
||||
rehashHelper = \dict, oldMetadata, oldDataIndices, oldData, index ->
|
||||
when List.get oldMetadata index is
|
||||
Ok md ->
|
||||
|
@ -695,7 +695,7 @@ rehashHelper = \dict, oldMetadata, oldDataIndices, oldData, index ->
|
|||
if md >= 0 then
|
||||
# We have an actual element here
|
||||
dataIndex = listGetUnsafe oldDataIndices index
|
||||
(T k _) = listGetUnsafe oldData dataIndex
|
||||
(k, _) = listGetUnsafe oldData dataIndex
|
||||
|
||||
insertForRehash dict k dataIndex
|
||||
else
|
||||
|
@ -731,8 +731,6 @@ emptySlot = -128
|
|||
deletedSlot : I8
|
||||
deletedSlot = -2
|
||||
|
||||
T k v : [T k v]
|
||||
|
||||
# Capacity must be a power of 2.
|
||||
# We still will use slots of 8 even though this version has no true slots.
|
||||
# We just move an element at a time.
|
||||
|
@ -869,7 +867,7 @@ expect
|
|||
|
||||
expect
|
||||
dict =
|
||||
fromList [T 1u8 1u8, T 2 2, T 3 3]
|
||||
fromList [(1u8, 1u8), (2, 2), (3, 3)]
|
||||
|> remove 1
|
||||
|> remove 3
|
||||
|
||||
|
@ -877,7 +875,7 @@ expect
|
|||
|
||||
expect
|
||||
list =
|
||||
fromList [T 1u8 1u8, T 2u8 2u8, T 3 3]
|
||||
fromList [(1u8, 1u8), (2u8, 2u8), (3, 3)]
|
||||
|> remove 1
|
||||
|> insert 0 0
|
||||
|> remove 3
|
||||
|
|
|
@ -3115,7 +3115,6 @@ fn update<'a>(
|
|||
&mut layout_interner,
|
||||
module_id,
|
||||
ident_ids,
|
||||
state.target_info,
|
||||
&mut state.procedures,
|
||||
);
|
||||
|
||||
|
|
|
@ -15,11 +15,10 @@ use bumpalo::collections::CollectIn;
|
|||
|
||||
use roc_module::low_level::LowLevel;
|
||||
use roc_module::symbol::{IdentIds, ModuleId, Symbol};
|
||||
use roc_target::TargetInfo;
|
||||
|
||||
use crate::ir::{
|
||||
BranchInfo, Call, CallType, Expr, JoinPointId, Literal, ModifyRc, Proc, ProcLayout, Stmt,
|
||||
UpdateModeId,
|
||||
BranchInfo, Call, CallType, Expr, JoinPointId, ListLiteralElement, Literal, ModifyRc, Proc,
|
||||
ProcLayout, Stmt, UpdateModeId,
|
||||
};
|
||||
use crate::layout::{
|
||||
Builtin, InLayout, Layout, LayoutInterner, LayoutRepr, STLayoutInterner, UnionLayout,
|
||||
|
@ -27,7 +26,7 @@ use crate::layout::{
|
|||
|
||||
use bumpalo::Bump;
|
||||
|
||||
use roc_collections::{MutMap, MutSet};
|
||||
use roc_collections::MutMap;
|
||||
|
||||
/**
|
||||
Try to find increments of symbols followed by decrements of the symbol they were indexed out of (their parent).
|
||||
|
@ -38,12 +37,10 @@ pub fn specialize_drops<'a, 'i>(
|
|||
layout_interner: &'i mut STLayoutInterner<'a>,
|
||||
home: ModuleId,
|
||||
ident_ids: &'i mut IdentIds,
|
||||
target_info: TargetInfo,
|
||||
procs: &mut MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>,
|
||||
) {
|
||||
for ((_symbol, proc_layout), proc) in procs.iter_mut() {
|
||||
let mut environment =
|
||||
DropSpecializationEnvironment::new(arena, home, proc_layout.result, target_info);
|
||||
let mut environment = DropSpecializationEnvironment::new(arena, home, proc_layout.result);
|
||||
specialize_drops_proc(arena, layout_interner, ident_ids, &mut environment, proc);
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +101,7 @@ fn specialize_drops_stmt<'a, 'i>(
|
|||
_ => unreachable!("List get should have two arguments"),
|
||||
};
|
||||
|
||||
environment.add_list_child(*structure, *binding, index);
|
||||
environment.add_list_child_symbol(*structure, *binding, index);
|
||||
|
||||
alloc_let_with_continuation!(environment)
|
||||
}
|
||||
|
@ -114,9 +111,18 @@ fn specialize_drops_stmt<'a, 'i>(
|
|||
RC::NoRc => alloc_let_with_continuation!(environment),
|
||||
// We probably should not pass the increments to the continuation.
|
||||
RC::Rc | RC::Uknown => {
|
||||
let mut new_environment = environment.clone_without_incremented();
|
||||
let incremented_symbols = environment.incremented_symbols.drain();
|
||||
|
||||
alloc_let_with_continuation!(&mut new_environment)
|
||||
let new_stmt = alloc_let_with_continuation!(environment);
|
||||
|
||||
// The new_environment might have inserted increments that were set to 0 before. We need to add th
|
||||
for (symbol, increment) in incremented_symbols.map.into_iter() {
|
||||
environment
|
||||
.incremented_symbols
|
||||
.insert_count(symbol, increment);
|
||||
}
|
||||
|
||||
new_stmt
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
|
@ -127,16 +133,62 @@ fn specialize_drops_stmt<'a, 'i>(
|
|||
// the parent might be deallocated before the function can use it.
|
||||
// Thus forget everything about any increments.
|
||||
|
||||
let mut new_environment = environment.clone_without_incremented();
|
||||
let incremented_symbols = environment.incremented_symbols.drain();
|
||||
|
||||
alloc_let_with_continuation!(&mut new_environment)
|
||||
let new_stmt = alloc_let_with_continuation!(environment);
|
||||
|
||||
// The new_environment might have inserted increments that were set to 0 before. We need to add th
|
||||
for (symbol, increment) in incremented_symbols.map.into_iter() {
|
||||
environment
|
||||
.incremented_symbols
|
||||
.insert_count(symbol, increment);
|
||||
}
|
||||
|
||||
new_stmt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Expr::Tag { tag_id, .. } => {
|
||||
Expr::Tag {
|
||||
tag_id,
|
||||
arguments: children,
|
||||
..
|
||||
} => {
|
||||
environment.symbol_tag.insert(*binding, *tag_id);
|
||||
|
||||
for (index, child) in children.iter().enumerate() {
|
||||
environment.add_union_child(*binding, *child, *tag_id, index as u64);
|
||||
}
|
||||
|
||||
alloc_let_with_continuation!(environment)
|
||||
}
|
||||
Expr::Struct(children) => {
|
||||
for (index, child) in children.iter().enumerate() {
|
||||
environment.add_struct_child(*binding, *child, index as u64);
|
||||
}
|
||||
|
||||
alloc_let_with_continuation!(environment)
|
||||
}
|
||||
Expr::ExprBox { symbol: child } => {
|
||||
environment.add_box_child(*binding, *child);
|
||||
|
||||
alloc_let_with_continuation!(environment)
|
||||
}
|
||||
Expr::Array {
|
||||
elems: children, ..
|
||||
} => {
|
||||
for (index, child) in
|
||||
children
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(index, child)| match child {
|
||||
ListLiteralElement::Literal(_) => None,
|
||||
ListLiteralElement::Symbol(s) => Some((index, s)),
|
||||
})
|
||||
{
|
||||
environment.add_list_child(*binding, *child, index as u64);
|
||||
}
|
||||
|
||||
alloc_let_with_continuation!(environment)
|
||||
}
|
||||
Expr::StructAtIndex {
|
||||
|
@ -188,13 +240,10 @@ fn specialize_drops_stmt<'a, 'i>(
|
|||
}
|
||||
alloc_let_with_continuation!(environment)
|
||||
}
|
||||
Expr::Struct(_)
|
||||
| Expr::RuntimeErrorFunction(_)
|
||||
| Expr::ExprBox { .. }
|
||||
Expr::RuntimeErrorFunction(_)
|
||||
| Expr::NullPointer
|
||||
| Expr::GetTagId { .. }
|
||||
| Expr::EmptyArray
|
||||
| Expr::Array { .. } => {
|
||||
| Expr::EmptyArray => {
|
||||
// Does nothing relevant to drop specialization. So we can just continue.
|
||||
alloc_let_with_continuation!(environment)
|
||||
}
|
||||
|
@ -283,10 +332,12 @@ fn specialize_drops_stmt<'a, 'i>(
|
|||
};
|
||||
|
||||
// Find the lowest symbol count for each symbol in each branch, and update the environment to match.
|
||||
for (symbol, count) in environment.incremented_symbols.iter_mut() {
|
||||
for (symbol, count) in environment.incremented_symbols.map.iter_mut() {
|
||||
let consumed = branch_envs
|
||||
.iter()
|
||||
.map(|branch_env| branch_env.incremented_symbols.get(symbol).unwrap_or(&0))
|
||||
.map(|branch_env| {
|
||||
branch_env.incremented_symbols.map.get(symbol).unwrap_or(&0)
|
||||
})
|
||||
.min()
|
||||
.unwrap();
|
||||
|
||||
|
@ -300,10 +351,14 @@ fn specialize_drops_stmt<'a, 'i>(
|
|||
let symbol_differences =
|
||||
environment
|
||||
.incremented_symbols
|
||||
.map
|
||||
.iter()
|
||||
.filter_map(|(symbol, count)| {
|
||||
let branch_count =
|
||||
$branch_env.incremented_symbols.get(symbol).unwrap_or(&0);
|
||||
let branch_count = $branch_env
|
||||
.incremented_symbols
|
||||
.map
|
||||
.get(symbol)
|
||||
.unwrap_or(&0);
|
||||
|
||||
match branch_count - count {
|
||||
0 => None,
|
||||
|
@ -338,11 +393,6 @@ fn specialize_drops_stmt<'a, 'i>(
|
|||
(info.clone(), new_branch)
|
||||
};
|
||||
|
||||
// Remove all 0 counts as cleanup.
|
||||
environment
|
||||
.incremented_symbols
|
||||
.retain(|_, count| *count > 0);
|
||||
|
||||
arena.alloc(Stmt::Switch {
|
||||
cond_symbol: *cond_symbol,
|
||||
cond_layout: *cond_layout,
|
||||
|
@ -354,10 +404,12 @@ fn specialize_drops_stmt<'a, 'i>(
|
|||
Stmt::Ret(symbol) => arena.alloc(Stmt::Ret(*symbol)),
|
||||
Stmt::Refcounting(rc, continuation) => match rc {
|
||||
ModifyRc::Inc(symbol, count) => {
|
||||
let any = environment.any_incremented(symbol);
|
||||
let inc_before = environment.incremented_symbols.contains(symbol);
|
||||
|
||||
// Add a symbol for every increment performed.
|
||||
environment.add_incremented(*symbol, *count);
|
||||
environment
|
||||
.incremented_symbols
|
||||
.insert_count(*symbol, *count);
|
||||
|
||||
let new_continuation = specialize_drops_stmt(
|
||||
arena,
|
||||
|
@ -367,12 +419,17 @@ fn specialize_drops_stmt<'a, 'i>(
|
|||
continuation,
|
||||
);
|
||||
|
||||
if any {
|
||||
if inc_before {
|
||||
// There were increments before this one, best to let the first one do the increments.
|
||||
// Or there are no increments left, so we can just continue.
|
||||
new_continuation
|
||||
} else {
|
||||
match environment.get_incremented(symbol) {
|
||||
match environment
|
||||
.incremented_symbols
|
||||
.map
|
||||
.remove(symbol)
|
||||
.unwrap_or(0)
|
||||
{
|
||||
// This is the first increment, but all increments are consumed. So don't insert any.
|
||||
0 => new_continuation,
|
||||
// We still need to do some increments.
|
||||
|
@ -393,7 +450,7 @@ fn specialize_drops_stmt<'a, 'i>(
|
|||
// dec a
|
||||
// dec b
|
||||
|
||||
if environment.pop_incremented(symbol) {
|
||||
if environment.incremented_symbols.pop(symbol) {
|
||||
// This decremented symbol was incremented before, so we can remove it.
|
||||
specialize_drops_stmt(
|
||||
arena,
|
||||
|
@ -411,10 +468,10 @@ fn specialize_drops_stmt<'a, 'i>(
|
|||
// As a might get dropped as a result of the decrement of b.
|
||||
let mut incremented_children = {
|
||||
let mut todo_children = bumpalo::vec![in arena; *symbol];
|
||||
let mut incremented_children = MutSet::default();
|
||||
let mut incremented_children = CountingMap::new();
|
||||
|
||||
while let Some(child) = todo_children.pop() {
|
||||
if environment.pop_incremented(&child) {
|
||||
if environment.incremented_symbols.pop(&child) {
|
||||
incremented_children.insert(child);
|
||||
} else {
|
||||
todo_children.extend(environment.get_children(&child));
|
||||
|
@ -485,8 +542,10 @@ fn specialize_drops_stmt<'a, 'i>(
|
|||
};
|
||||
|
||||
// Add back the increments for the children to the environment.
|
||||
for child_symbol in incremented_children.iter() {
|
||||
environment.add_incremented(*child_symbol, 1)
|
||||
for (child_symbol, symbol_count) in incremented_children.map.into_iter() {
|
||||
environment
|
||||
.incremented_symbols
|
||||
.insert_count(child_symbol, symbol_count)
|
||||
}
|
||||
|
||||
updated_stmt
|
||||
|
@ -565,7 +624,8 @@ fn specialize_drops_stmt<'a, 'i>(
|
|||
body,
|
||||
remainder,
|
||||
} => {
|
||||
let mut new_environment = environment.clone_without_incremented();
|
||||
let mut new_environment = environment.clone();
|
||||
new_environment.incremented_symbols.clear();
|
||||
|
||||
for param in parameters.iter() {
|
||||
new_environment.add_symbol_layout(param.symbol, param.layout);
|
||||
|
@ -604,7 +664,7 @@ fn specialize_struct<'a, 'i>(
|
|||
environment: &mut DropSpecializationEnvironment<'a>,
|
||||
symbol: &Symbol,
|
||||
struct_layout: &'a [InLayout],
|
||||
incremented_children: &mut MutSet<Child>,
|
||||
incremented_children: &mut CountingMap<Child>,
|
||||
continuation: &'a Stmt<'a>,
|
||||
) -> &'a Stmt<'a> {
|
||||
match environment.struct_children.get(symbol) {
|
||||
|
@ -620,7 +680,7 @@ fn specialize_struct<'a, 'i>(
|
|||
|
||||
for (index, _layout) in struct_layout.iter().enumerate() {
|
||||
for (child, _i) in children_clone.iter().filter(|(_, i)| *i == index as u64) {
|
||||
let removed = incremented_children.remove(child);
|
||||
let removed = incremented_children.pop(child);
|
||||
index_symbols.insert(index, (*child, removed));
|
||||
|
||||
if removed {
|
||||
|
@ -693,7 +753,7 @@ fn specialize_union<'a, 'i>(
|
|||
environment: &mut DropSpecializationEnvironment<'a>,
|
||||
symbol: &Symbol,
|
||||
union_layout: UnionLayout<'a>,
|
||||
incremented_children: &mut MutSet<Child>,
|
||||
incremented_children: &mut CountingMap<Child>,
|
||||
continuation: &'a Stmt<'a>,
|
||||
) -> &'a Stmt<'a> {
|
||||
let current_tag = environment.symbol_tag.get(symbol).copied();
|
||||
|
@ -736,7 +796,7 @@ fn specialize_union<'a, 'i>(
|
|||
{
|
||||
debug_assert_eq!(tag, *t);
|
||||
|
||||
let removed = incremented_children.remove(child);
|
||||
let removed = incremented_children.pop(child);
|
||||
index_symbols.insert(index, (*child, removed));
|
||||
|
||||
if removed {
|
||||
|
@ -898,14 +958,14 @@ fn specialize_boxed<'a, 'i>(
|
|||
layout_interner: &'i mut STLayoutInterner<'a>,
|
||||
ident_ids: &'i mut IdentIds,
|
||||
environment: &mut DropSpecializationEnvironment<'a>,
|
||||
incremented_children: &mut MutSet<Child>,
|
||||
incremented_children: &mut CountingMap<Child>,
|
||||
symbol: &Symbol,
|
||||
continuation: &'a Stmt<'a>,
|
||||
) -> &'a Stmt<'a> {
|
||||
let removed = match incremented_children.iter().next() {
|
||||
Some(s) => {
|
||||
let removed = match incremented_children.map.iter().next() {
|
||||
Some((s, _)) => {
|
||||
let s = *s;
|
||||
incremented_children.remove(&s);
|
||||
incremented_children.pop(&s);
|
||||
Some(s)
|
||||
}
|
||||
None => None,
|
||||
|
@ -924,23 +984,20 @@ fn specialize_boxed<'a, 'i>(
|
|||
*symbol,
|
||||
// If the symbol is unique:
|
||||
// - free the box
|
||||
|_, _, _| {
|
||||
|_, _, continuation| {
|
||||
arena.alloc(Stmt::Refcounting(
|
||||
// TODO can be replaced by free if ever added to the IR.
|
||||
ModifyRc::DecRef(*symbol),
|
||||
new_continuation,
|
||||
continuation,
|
||||
))
|
||||
},
|
||||
// If the symbol is not unique:
|
||||
// - increment the child
|
||||
// - decref the box
|
||||
|_, _, _| {
|
||||
|_, _, continuation| {
|
||||
arena.alloc(Stmt::Refcounting(
|
||||
ModifyRc::Inc(s, 1),
|
||||
arena.alloc(Stmt::Refcounting(
|
||||
ModifyRc::DecRef(*symbol),
|
||||
new_continuation,
|
||||
)),
|
||||
arena.alloc(Stmt::Refcounting(ModifyRc::DecRef(*symbol), continuation)),
|
||||
))
|
||||
},
|
||||
new_continuation,
|
||||
|
@ -958,7 +1015,7 @@ fn specialize_list<'a, 'i>(
|
|||
layout_interner: &'i mut STLayoutInterner<'a>,
|
||||
ident_ids: &'i mut IdentIds,
|
||||
environment: &mut DropSpecializationEnvironment<'a>,
|
||||
incremented_children: &mut MutSet<Child>,
|
||||
incremented_children: &mut CountingMap<Child>,
|
||||
symbol: &Symbol,
|
||||
item_layout: InLayout,
|
||||
continuation: &'a Stmt<'a>,
|
||||
|
@ -993,7 +1050,7 @@ fn specialize_list<'a, 'i>(
|
|||
for (child, i) in children_clone.iter().filter(|(_child, i)| *i == index) {
|
||||
debug_assert!(length > *i);
|
||||
|
||||
let removed = incremented_children.remove(child);
|
||||
let removed = incremented_children.pop(child);
|
||||
index_symbols.insert(index, (*child, removed));
|
||||
|
||||
if removed {
|
||||
|
@ -1214,7 +1271,6 @@ struct DropSpecializationEnvironment<'a> {
|
|||
arena: &'a Bump,
|
||||
home: ModuleId,
|
||||
layout: InLayout<'a>,
|
||||
target_info: TargetInfo,
|
||||
|
||||
symbol_layouts: MutMap<Symbol, InLayout<'a>>,
|
||||
|
||||
|
@ -1231,7 +1287,7 @@ struct DropSpecializationEnvironment<'a> {
|
|||
list_children: MutMap<Parent, Vec<'a, (Child, Index)>>,
|
||||
|
||||
// Keeps track of all incremented symbols.
|
||||
incremented_symbols: MutMap<Symbol, u64>,
|
||||
incremented_symbols: CountingMap<Symbol>,
|
||||
|
||||
// Map containing the current known tag of a layout.
|
||||
symbol_tag: MutMap<Symbol, Tag>,
|
||||
|
@ -1244,42 +1300,23 @@ struct DropSpecializationEnvironment<'a> {
|
|||
}
|
||||
|
||||
impl<'a> DropSpecializationEnvironment<'a> {
|
||||
fn new(arena: &'a Bump, home: ModuleId, layout: InLayout<'a>, target_info: TargetInfo) -> Self {
|
||||
fn new(arena: &'a Bump, home: ModuleId, layout: InLayout<'a>) -> Self {
|
||||
Self {
|
||||
arena,
|
||||
home,
|
||||
layout,
|
||||
target_info,
|
||||
symbol_layouts: MutMap::default(),
|
||||
struct_children: MutMap::default(),
|
||||
union_children: MutMap::default(),
|
||||
box_children: MutMap::default(),
|
||||
list_children: MutMap::default(),
|
||||
incremented_symbols: MutMap::default(),
|
||||
incremented_symbols: CountingMap::new(),
|
||||
symbol_tag: MutMap::default(),
|
||||
symbol_index: MutMap::default(),
|
||||
list_length: MutMap::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn clone_without_incremented(&self) -> Self {
|
||||
Self {
|
||||
arena: self.arena,
|
||||
home: self.home,
|
||||
layout: self.layout,
|
||||
target_info: self.target_info,
|
||||
symbol_layouts: self.symbol_layouts.clone(),
|
||||
struct_children: self.struct_children.clone(),
|
||||
union_children: self.union_children.clone(),
|
||||
box_children: self.box_children.clone(),
|
||||
list_children: self.list_children.clone(),
|
||||
incremented_symbols: MutMap::default(),
|
||||
symbol_tag: self.symbol_tag.clone(),
|
||||
symbol_index: self.symbol_index.clone(),
|
||||
list_length: self.list_length.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn create_symbol<'i>(&self, ident_ids: &'i mut IdentIds, debug_name: &str) -> Symbol {
|
||||
let ident_id = ident_ids.add_str(debug_name);
|
||||
Symbol::new(self.home, ident_id)
|
||||
|
@ -1316,12 +1353,16 @@ impl<'a> DropSpecializationEnvironment<'a> {
|
|||
.push(child);
|
||||
}
|
||||
|
||||
fn add_list_child(&mut self, parent: Parent, child: Child, index: &Symbol) {
|
||||
if let Some(index) = self.symbol_index.get(index) {
|
||||
fn add_list_child(&mut self, parent: Parent, child: Child, index: u64) {
|
||||
self.list_children
|
||||
.entry(parent)
|
||||
.or_insert_with(|| Vec::new_in(self.arena))
|
||||
.push((child, *index));
|
||||
.push((child, index));
|
||||
}
|
||||
|
||||
fn add_list_child_symbol(&mut self, parent: Parent, child: Child, index: &Symbol) {
|
||||
if let Some(index) = self.symbol_index.get(index) {
|
||||
self.add_list_child(parent, child, *index)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1346,39 +1387,6 @@ impl<'a> DropSpecializationEnvironment<'a> {
|
|||
|
||||
res
|
||||
}
|
||||
|
||||
/**
|
||||
Add a symbol for every increment performed.
|
||||
*/
|
||||
fn add_incremented(&mut self, symbol: Symbol, count: u64) {
|
||||
self.incremented_symbols
|
||||
.entry(symbol)
|
||||
.and_modify(|c| *c += count)
|
||||
.or_insert(count);
|
||||
}
|
||||
|
||||
fn any_incremented(&self, symbol: &Symbol) -> bool {
|
||||
self.incremented_symbols.contains_key(symbol)
|
||||
}
|
||||
|
||||
/**
|
||||
Return the amount of times a symbol still has to be incremented.
|
||||
Accounting for later consumtion and removal of the increment.
|
||||
*/
|
||||
fn get_incremented(&mut self, symbol: &Symbol) -> u64 {
|
||||
self.incremented_symbols.remove(symbol).unwrap_or(0)
|
||||
}
|
||||
|
||||
fn pop_incremented(&mut self, symbol: &Symbol) -> bool {
|
||||
match self.incremented_symbols.get_mut(symbol) {
|
||||
Some(0) => false,
|
||||
Some(c) => {
|
||||
*c -= 1;
|
||||
true
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1490,3 +1498,59 @@ fn low_level_no_rc(lowlevel: &LowLevel) -> RC {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Map that contains a count for each key.
|
||||
/// Keys with a count of 0 are kept around, so that it can be seen that they were once present.
|
||||
#[derive(Clone)]
|
||||
struct CountingMap<K> {
|
||||
map: MutMap<K, u64>,
|
||||
}
|
||||
|
||||
impl<K> CountingMap<K>
|
||||
where
|
||||
K: Eq + std::hash::Hash + Clone,
|
||||
{
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
map: MutMap::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn insert(&mut self, key: K) {
|
||||
self.insert_count(key, 1);
|
||||
}
|
||||
|
||||
fn insert_count(&mut self, key: K, count: u64) {
|
||||
self.map
|
||||
.entry(key)
|
||||
.and_modify(|c| *c += count)
|
||||
.or_insert(count);
|
||||
}
|
||||
|
||||
fn pop(&mut self, key: &K) -> bool {
|
||||
match self.map.get_mut(key) {
|
||||
Some(0) => false,
|
||||
Some(c) => {
|
||||
*c -= 1;
|
||||
true
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn contains(&self, symbol: &K) -> bool {
|
||||
self.map.contains_key(symbol)
|
||||
}
|
||||
|
||||
fn drain(&mut self) -> Self {
|
||||
let res = self.clone();
|
||||
for (_, v) in self.map.iter_mut() {
|
||||
*v = 0;
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn clear(&mut self) {
|
||||
self.map.clear();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
procedure Dict.1 (Dict.547):
|
||||
let Dict.556 : List {[], []} = Array [];
|
||||
let Dict.563 : U64 = 0i64;
|
||||
let Dict.564 : U64 = 8i64;
|
||||
let Dict.557 : List U64 = CallByName List.11 Dict.563 Dict.564;
|
||||
let Dict.560 : I8 = CallByName Dict.37;
|
||||
let Dict.561 : U64 = 8i64;
|
||||
let Dict.558 : List I8 = CallByName List.11 Dict.560 Dict.561;
|
||||
let Dict.559 : U64 = 0i64;
|
||||
let Dict.555 : {List {[], []}, List U64, List I8, U64} = Struct {Dict.556, Dict.557, Dict.558, Dict.559};
|
||||
ret Dict.555;
|
||||
procedure Dict.1 (Dict.537):
|
||||
let Dict.546 : List {[], []} = Array [];
|
||||
let Dict.553 : U64 = 0i64;
|
||||
let Dict.554 : U64 = 8i64;
|
||||
let Dict.547 : List U64 = CallByName List.11 Dict.553 Dict.554;
|
||||
let Dict.550 : I8 = CallByName Dict.36;
|
||||
let Dict.551 : U64 = 8i64;
|
||||
let Dict.548 : List I8 = CallByName List.11 Dict.550 Dict.551;
|
||||
let Dict.549 : U64 = 0i64;
|
||||
let Dict.545 : {List {[], []}, List U64, List I8, U64} = Struct {Dict.546, Dict.547, Dict.548, Dict.549};
|
||||
ret Dict.545;
|
||||
|
||||
procedure Dict.37 ():
|
||||
let Dict.562 : I8 = -128i64;
|
||||
ret Dict.562;
|
||||
procedure Dict.36 ():
|
||||
let Dict.552 : I8 = -128i64;
|
||||
ret Dict.552;
|
||||
|
||||
procedure Dict.4 (Dict.553):
|
||||
let Dict.99 : U64 = StructAtIndex 3 Dict.553;
|
||||
let #Derived_gen.2 : List {[], []} = StructAtIndex 0 Dict.553;
|
||||
procedure Dict.4 (Dict.543):
|
||||
let Dict.97 : U64 = StructAtIndex 3 Dict.543;
|
||||
let #Derived_gen.2 : List {[], []} = StructAtIndex 0 Dict.543;
|
||||
dec #Derived_gen.2;
|
||||
let #Derived_gen.1 : List U64 = StructAtIndex 1 Dict.553;
|
||||
let #Derived_gen.1 : List U64 = StructAtIndex 1 Dict.543;
|
||||
dec #Derived_gen.1;
|
||||
let #Derived_gen.0 : List I8 = StructAtIndex 2 Dict.553;
|
||||
let #Derived_gen.0 : List I8 = StructAtIndex 2 Dict.543;
|
||||
dec #Derived_gen.0;
|
||||
ret Dict.99;
|
||||
ret Dict.97;
|
||||
|
||||
procedure List.11 (List.115, List.116):
|
||||
let List.495 : List I8 = CallByName List.68 List.116;
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
procedure Test.0 ():
|
||||
let Test.2 : Str = "value";
|
||||
let Test.3 : {Str, Str} = Struct {Test.2, Test.2};
|
||||
dec Test.2;
|
||||
let Test.4 : Str = "result";
|
||||
ret Test.4;
|
|
@ -697,8 +697,8 @@ procedure Json.25 (Json.183):
|
|||
let Json.1906 : List U8 = CallByName List.8 Json.1907 Json.1908;
|
||||
ret Json.1906;
|
||||
else
|
||||
let Json.1948 : U64 = StructAtIndex 0 Json.186;
|
||||
inc Json.184;
|
||||
let Json.1948 : U64 = StructAtIndex 0 Json.186;
|
||||
let Json.1947 : {List U8, List U8} = CallByName List.52 Json.184 Json.1948;
|
||||
let Json.210 : List U8 = StructAtIndex 0 Json.1947;
|
||||
let Json.212 : List U8 = StructAtIndex 1 Json.1947;
|
||||
|
|
|
@ -623,8 +623,8 @@ procedure Json.25 (Json.183):
|
|||
let Json.1532 : List U8 = CallByName List.8 Json.1533 Json.1534;
|
||||
ret Json.1532;
|
||||
else
|
||||
let Json.1574 : U64 = StructAtIndex 0 Json.186;
|
||||
inc Json.184;
|
||||
let Json.1574 : U64 = StructAtIndex 0 Json.186;
|
||||
let Json.1573 : {List U8, List U8} = CallByName List.52 Json.184 Json.1574;
|
||||
let Json.210 : List U8 = StructAtIndex 0 Json.1573;
|
||||
let Json.212 : List U8 = StructAtIndex 1 Json.1573;
|
||||
|
|
|
@ -630,8 +630,8 @@ procedure Json.25 (Json.183):
|
|||
let Json.1532 : List U8 = CallByName List.8 Json.1533 Json.1534;
|
||||
ret Json.1532;
|
||||
else
|
||||
let Json.1574 : U64 = StructAtIndex 0 Json.186;
|
||||
inc Json.184;
|
||||
let Json.1574 : U64 = StructAtIndex 0 Json.186;
|
||||
let Json.1573 : {List U8, List U8} = CallByName List.52 Json.184 Json.1574;
|
||||
let Json.210 : List U8 = StructAtIndex 0 Json.1573;
|
||||
let Json.212 : List U8 = StructAtIndex 1 Json.1573;
|
||||
|
|
|
@ -118,8 +118,8 @@ procedure Json.25 (Json.183):
|
|||
let Json.1179 : List U8 = CallByName List.8 Json.1180 Json.1181;
|
||||
ret Json.1179;
|
||||
else
|
||||
let Json.1221 : U64 = StructAtIndex 0 Json.186;
|
||||
inc Json.184;
|
||||
let Json.1221 : U64 = StructAtIndex 0 Json.186;
|
||||
let Json.1220 : {List U8, List U8} = CallByName List.52 Json.184 Json.1221;
|
||||
let Json.210 : List U8 = StructAtIndex 0 Json.1220;
|
||||
let Json.212 : List U8 = StructAtIndex 1 Json.1220;
|
||||
|
|
|
@ -147,8 +147,8 @@ procedure Json.25 (Json.183):
|
|||
let Json.1220 : List U8 = CallByName List.8 Json.1221 Json.1222;
|
||||
ret Json.1220;
|
||||
else
|
||||
let Json.1262 : U64 = StructAtIndex 0 Json.186;
|
||||
inc Json.184;
|
||||
let Json.1262 : U64 = StructAtIndex 0 Json.186;
|
||||
let Json.1261 : {List U8, List U8} = CallByName List.52 Json.184 Json.1262;
|
||||
let Json.210 : List U8 = StructAtIndex 0 Json.1261;
|
||||
let Json.212 : List U8 = StructAtIndex 1 Json.1261;
|
||||
|
|
|
@ -150,8 +150,8 @@ procedure Json.25 (Json.183):
|
|||
let Json.1220 : List U8 = CallByName List.8 Json.1221 Json.1222;
|
||||
ret Json.1220;
|
||||
else
|
||||
let Json.1262 : U64 = StructAtIndex 0 Json.186;
|
||||
inc Json.184;
|
||||
let Json.1262 : U64 = StructAtIndex 0 Json.186;
|
||||
let Json.1261 : {List U8, List U8} = CallByName List.52 Json.184 Json.1262;
|
||||
let Json.210 : List U8 = StructAtIndex 0 Json.1261;
|
||||
let Json.212 : List U8 = StructAtIndex 1 Json.1261;
|
||||
|
|
|
@ -179,8 +179,8 @@ procedure Json.60 (Json.540):
|
|||
let Json.1336 : U8 = GetTagId Json.1327;
|
||||
let Json.1337 : Int1 = lowlevel Eq Json.1335 Json.1336;
|
||||
if Json.1337 then
|
||||
let Json.542 : U64 = UnionAtIndex (Id 2) (Index 0) Json.1327;
|
||||
inc Json.540;
|
||||
let Json.542 : U64 = UnionAtIndex (Id 2) (Index 0) Json.1327;
|
||||
let Json.1329 : List U8 = CallByName List.29 Json.540 Json.542;
|
||||
let Json.1332 : U64 = 0i64;
|
||||
let Json.1331 : {U64, U64} = Struct {Json.542, Json.1332};
|
||||
|
@ -532,18 +532,15 @@ procedure Json.68 ():
|
|||
procedure Json.69 (Json.1467):
|
||||
joinpoint Json.1197 Json.1165:
|
||||
let Json.599 : List U8 = StructAtIndex 0 Json.1165;
|
||||
inc Json.599;
|
||||
inc 4 Json.599;
|
||||
let Json.600 : List U8 = StructAtIndex 1 Json.1165;
|
||||
let Json.1315 : U64 = 0i64;
|
||||
let Json.601 : [C {}, C U8] = CallByName List.2 Json.599 Json.1315;
|
||||
let Json.1314 : U64 = 1i64;
|
||||
inc Json.599;
|
||||
let Json.602 : [C {}, C U8] = CallByName List.2 Json.599 Json.1314;
|
||||
let Json.1313 : U64 = 2i64;
|
||||
inc Json.599;
|
||||
let Json.603 : List U8 = CallByName List.29 Json.599 Json.1313;
|
||||
let Json.1312 : U64 = 6i64;
|
||||
inc Json.599;
|
||||
let Json.604 : List U8 = CallByName List.29 Json.599 Json.1312;
|
||||
let Json.1198 : {[C {}, C U8], [C {}, C U8]} = Struct {Json.601, Json.602};
|
||||
joinpoint Json.1277:
|
||||
|
@ -832,7 +829,7 @@ procedure Test.3 ():
|
|||
let Test.7 : Str = "Roc";
|
||||
let Test.6 : [C [C List U8, C ], C Str] = TagId(1) Test.7;
|
||||
let Test.5 : Int1 = CallByName Bool.11 Test.1 Test.6;
|
||||
dec Test.6;
|
||||
dec Test.7;
|
||||
expect Test.5;
|
||||
dec Test.0;
|
||||
dec Test.1;
|
||||
|
|
|
@ -153,8 +153,8 @@ procedure Json.60 (Json.540):
|
|||
let Json.1336 : U8 = GetTagId Json.1327;
|
||||
let Json.1337 : Int1 = lowlevel Eq Json.1335 Json.1336;
|
||||
if Json.1337 then
|
||||
let Json.542 : U64 = UnionAtIndex (Id 2) (Index 0) Json.1327;
|
||||
inc Json.540;
|
||||
let Json.542 : U64 = UnionAtIndex (Id 2) (Index 0) Json.1327;
|
||||
let Json.1329 : List U8 = CallByName List.29 Json.540 Json.542;
|
||||
let Json.1332 : U64 = 0i64;
|
||||
let Json.1331 : {U64, U64} = Struct {Json.542, Json.1332};
|
||||
|
@ -506,18 +506,15 @@ procedure Json.68 ():
|
|||
procedure Json.69 (Json.1467):
|
||||
joinpoint Json.1197 Json.1165:
|
||||
let Json.599 : List U8 = StructAtIndex 0 Json.1165;
|
||||
inc Json.599;
|
||||
inc 4 Json.599;
|
||||
let Json.600 : List U8 = StructAtIndex 1 Json.1165;
|
||||
let Json.1315 : U64 = 0i64;
|
||||
let Json.601 : [C {}, C U8] = CallByName List.2 Json.599 Json.1315;
|
||||
let Json.1314 : U64 = 1i64;
|
||||
inc Json.599;
|
||||
let Json.602 : [C {}, C U8] = CallByName List.2 Json.599 Json.1314;
|
||||
let Json.1313 : U64 = 2i64;
|
||||
inc Json.599;
|
||||
let Json.603 : List U8 = CallByName List.29 Json.599 Json.1313;
|
||||
let Json.1312 : U64 = 6i64;
|
||||
inc Json.599;
|
||||
let Json.604 : List U8 = CallByName List.29 Json.599 Json.1312;
|
||||
let Json.1198 : {[C {}, C U8], [C {}, C U8]} = Struct {Json.601, Json.602};
|
||||
joinpoint Json.1277:
|
||||
|
@ -865,7 +862,7 @@ procedure Test.12 ():
|
|||
let Test.16 : {List U8, I64} = Struct {Test.17, Test.18};
|
||||
let Test.15 : [C Str, C {List U8, I64}] = TagId(1) Test.16;
|
||||
let Test.14 : Int1 = CallByName Bool.11 Test.10 Test.15;
|
||||
dec Test.15;
|
||||
dec Test.16;
|
||||
expect Test.14;
|
||||
dec Test.10;
|
||||
let Test.13 : {} = Struct {};
|
||||
|
|
|
@ -5,7 +5,8 @@ procedure Test.0 ():
|
|||
let Test.9 : U64 = 1i64;
|
||||
let Test.10 : Int1 = lowlevel Eq Test.8 Test.9;
|
||||
if Test.10 then
|
||||
dec Test.1;
|
||||
dec Test.11;
|
||||
decref Test.1;
|
||||
let Test.3 : Str = "B";
|
||||
ret Test.3;
|
||||
else
|
||||
|
|
|
@ -5,7 +5,7 @@ procedure Test.0 ():
|
|||
let Test.2 : [<rnu><null>, C *self] = TagId(0) Test.13;
|
||||
let Test.10 : U8 = 1i64;
|
||||
let Test.11 : U8 = GetTagId Test.2;
|
||||
dec Test.2;
|
||||
joinpoint #Derived_gen.0:
|
||||
let Test.12 : Int1 = lowlevel Eq Test.10 Test.11;
|
||||
if Test.12 then
|
||||
let Test.8 : I64 = 0i64;
|
||||
|
@ -13,3 +13,12 @@ procedure Test.0 ():
|
|||
else
|
||||
let Test.9 : I64 = 1i64;
|
||||
ret Test.9;
|
||||
in
|
||||
let #Derived_gen.1 : Int1 = lowlevel RefCountIsUnique Test.2;
|
||||
if #Derived_gen.1 then
|
||||
dec Test.13;
|
||||
decref Test.2;
|
||||
jump #Derived_gen.0;
|
||||
else
|
||||
decref Test.2;
|
||||
jump #Derived_gen.0;
|
||||
|
|
|
@ -30,6 +30,15 @@ procedure Test.0 ():
|
|||
let Test.16 : Str = "";
|
||||
let Test.15 : [<r>C List *self, C Str] = TagId(1) Test.16;
|
||||
let Test.13 : Int1 = CallByName Bool.11 Test.14 Test.15;
|
||||
dec Test.15;
|
||||
joinpoint #Derived_gen.0:
|
||||
dec Test.14;
|
||||
ret Test.13;
|
||||
in
|
||||
let #Derived_gen.1 : Int1 = lowlevel RefCountIsUnique Test.15;
|
||||
if #Derived_gen.1 then
|
||||
dec Test.16;
|
||||
decref Test.15;
|
||||
jump #Derived_gen.0;
|
||||
else
|
||||
decref Test.15;
|
||||
jump #Derived_gen.0;
|
||||
|
|
|
@ -45,10 +45,9 @@ procedure Num.22 (#Attr.2, #Attr.3):
|
|||
|
||||
procedure Test.1 (Test.2):
|
||||
let Test.28 : U64 = 0i64;
|
||||
inc Test.2;
|
||||
inc 2 Test.2;
|
||||
let Test.26 : [C {}, C I64] = CallByName List.2 Test.2 Test.28;
|
||||
let Test.27 : U64 = 0i64;
|
||||
inc Test.2;
|
||||
let Test.25 : [C {}, C I64] = CallByName List.2 Test.2 Test.27;
|
||||
let Test.8 : {[C {}, C I64], [C {}, C I64]} = Struct {Test.25, Test.26};
|
||||
joinpoint Test.22:
|
||||
|
|
|
@ -44,9 +44,8 @@ procedure Num.22 (#Attr.2, #Attr.3):
|
|||
ret Num.283;
|
||||
|
||||
procedure Test.1 (Test.2, Test.3, Test.4):
|
||||
inc Test.4;
|
||||
inc 2 Test.4;
|
||||
let Test.29 : [C {}, C I64] = CallByName List.2 Test.4 Test.3;
|
||||
inc Test.4;
|
||||
let Test.28 : [C {}, C I64] = CallByName List.2 Test.4 Test.2;
|
||||
let Test.13 : {[C {}, C I64], [C {}, C I64]} = Struct {Test.28, Test.29};
|
||||
joinpoint Test.25:
|
||||
|
|
|
@ -136,8 +136,8 @@ procedure Json.25 (Json.183):
|
|||
let Json.1223 : List U8 = CallByName List.8 Json.1224 Json.1225;
|
||||
ret Json.1223;
|
||||
else
|
||||
let Json.1265 : U64 = StructAtIndex 0 Json.186;
|
||||
inc Json.184;
|
||||
let Json.1265 : U64 = StructAtIndex 0 Json.186;
|
||||
let Json.1264 : {List U8, List U8} = CallByName List.52 Json.184 Json.1265;
|
||||
let Json.210 : List U8 = StructAtIndex 0 Json.1264;
|
||||
let Json.212 : List U8 = StructAtIndex 1 Json.1264;
|
||||
|
|
|
@ -3050,3 +3050,19 @@ fn specialize_after_match() {
|
|||
"#
|
||||
)
|
||||
}
|
||||
|
||||
#[mono_test]
|
||||
fn drop_specialize_after_struct() {
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" provides [main] to "./platform"
|
||||
|
||||
Tuple a b : { left : a, right : b }
|
||||
|
||||
main =
|
||||
v = "value"
|
||||
t = { left: v, right: v }
|
||||
"result"
|
||||
"#
|
||||
)
|
||||
}
|
||||
|
|
|
@ -7,12 +7,6 @@ edition.workspace = true
|
|||
license.workspace = true
|
||||
version.workspace = true
|
||||
|
||||
[package.metadata.cargo-udeps.ignore]
|
||||
# confy is currently unused but should not be removed
|
||||
normal = ["confy"]
|
||||
#development = []
|
||||
#build = []
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
|
@ -40,7 +34,6 @@ bumpalo.workspace = true
|
|||
bytemuck.workspace = true
|
||||
cgmath.workspace = true
|
||||
colored.workspace = true
|
||||
confy.workspace = true
|
||||
copypasta.workspace = true
|
||||
fs_extra.workspace = true
|
||||
futures.workspace = true
|
||||
|
|
|
@ -23,7 +23,6 @@ rustPlatform.buildRustPackage {
|
|||
cargoLock = {
|
||||
lockFile = ./Cargo.lock;
|
||||
outputHashes = {
|
||||
"confy-0.5.1" = "sha256-KML/uoze2djsFhYk488QAtauethDaC+0aZ3q56yAhuY=";
|
||||
"criterion-0.3.5" = "sha256-+FibPQGiR45g28xCHcM0pMN+C+Q8gO8206Wb5fiTy+k=";
|
||||
"inkwell-0.1.0" = "sha256-1kpvY3naS33B99nuu5ZYhb7mdddAyG+DkbUl/RG1Ptg=";
|
||||
"plotters-0.3.1" = "sha256-noy/RSjoEPZZbOJTZw1yxGcX5S+2q/7mxnUrzDyxOFw=";
|
||||
|
|
|
@ -21,7 +21,6 @@ page_size = "0.4.2"
|
|||
roc_std = { path = "../../../../crates/roc_std" }
|
||||
cgmath = "0.18.0"
|
||||
colored = "2.0.0"
|
||||
confy = { git = 'https://github.com/rust-cli/confy', features = ["yaml_conf"], default-features = false }
|
||||
copypasta = "0.7.1"
|
||||
fs_extra = "1.2.0"
|
||||
futures = "0.3.17"
|
||||
|
@ -38,12 +37,6 @@ wgpu = { git = "https://github.com/gfx-rs/wgpu", rev = "0545e36" }
|
|||
wgpu_glyph = { git = "https://github.com/Anton-4/wgpu_glyph", rev = "257d109" }
|
||||
winit = "0.26.1"
|
||||
|
||||
[package.metadata.cargo-udeps.ignore]
|
||||
# confy is currently unused but should not be removed
|
||||
normal = ["confy"]
|
||||
#development = []
|
||||
#build = []
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ page_size = "0.4.2"
|
|||
roc_std = { path = "../../../crates/roc_std" }
|
||||
cgmath = "0.18.0"
|
||||
colored = "2.0.0"
|
||||
confy = { git = 'https://github.com/rust-cli/confy', features = ["yaml_conf"], default-features = false }
|
||||
copypasta = "0.7.1"
|
||||
fs_extra = "1.2.0"
|
||||
futures = "0.3.17"
|
||||
|
@ -39,12 +38,6 @@ wgpu = { git = "https://github.com/gfx-rs/wgpu", rev = "0545e36" }
|
|||
wgpu_glyph = { git = "https://github.com/Anton-4/wgpu_glyph", rev = "257d109" }
|
||||
winit = "0.26.1"
|
||||
|
||||
[package.metadata.cargo-udeps.ignore]
|
||||
# confy is currently unused but should not be removed
|
||||
normal = ["confy"]
|
||||
#development = []
|
||||
#build = []
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
|
|
|
@ -656,49 +656,11 @@ nextNodeId = \rendered ->
|
|||
eqRenderedTree : RenderedTree state, RenderedTree state -> Bool
|
||||
eqRenderedTree = \a, b ->
|
||||
(a.root == b.root)
|
||||
&& eqRenderedNodes a.nodes b.nodes
|
||||
&& (a.nodes == b.nodes)
|
||||
&& (List.len a.handlers == List.len b.handlers)
|
||||
&& (a.deletedNodeCache == b.deletedNodeCache)
|
||||
&& (a.deletedHandlerCache == b.deletedHandlerCache)
|
||||
|
||||
eqRenderedNodes : List (Result RenderedNode [DeletedNode]), List (Result RenderedNode [DeletedNode]) -> Bool
|
||||
eqRenderedNodes = \a, b ->
|
||||
List.map2 a b Tuple
|
||||
|> List.all
|
||||
(\t ->
|
||||
when t is
|
||||
Tuple (Ok x) (Ok y) -> eqRenderedNode x y
|
||||
Tuple (Err x) (Err y) -> x == y
|
||||
_ -> Bool.false)
|
||||
|
||||
eqRenderedNode : RenderedNode, RenderedNode -> Bool
|
||||
eqRenderedNode = \a, b ->
|
||||
when { a, b } is
|
||||
{ a: RenderedNone, b: RenderedNone } ->
|
||||
Bool.true
|
||||
|
||||
{ a: RenderedText aStr, b: RenderedText bStr } ->
|
||||
aStr == bStr
|
||||
|
||||
{ a: RenderedElement aName aAttrs aChildren, b: RenderedElement bName bAttrs bChildren } ->
|
||||
(aName == bName)
|
||||
&& (aChildren == bChildren) # good enough for testing!
|
||||
&& eqRenderedAttrs aAttrs bAttrs
|
||||
|
||||
_ -> Bool.false
|
||||
|
||||
eqRenderedAttrs : RenderedAttributes, RenderedAttributes -> Bool
|
||||
eqRenderedAttrs = \a, b ->
|
||||
eqAttrDict a.eventListeners b.eventListeners
|
||||
&& eqAttrDict a.htmlAttrs b.htmlAttrs
|
||||
&& eqAttrDict a.domProps b.domProps
|
||||
&& eqAttrDict a.styles b.styles
|
||||
|
||||
eqAttrDict : Dict Str v, Dict Str v -> Bool | v has Eq
|
||||
eqAttrDict = \a, b ->
|
||||
Dict.keys a
|
||||
|> List.all \k -> Dict.get a k == Dict.get b k
|
||||
|
||||
# indexNodes
|
||||
expect
|
||||
html : Html {}
|
||||
|
@ -713,12 +675,12 @@ expect
|
|||
expected = {
|
||||
nodes: [
|
||||
RenderedText "Roc",
|
||||
RenderedElement "a" { emptyRenderedAttrs & htmlAttrs: Dict.fromList [T "href" "https://www.roc-lang.org/"] } [0],
|
||||
RenderedElement "a" { emptyRenderedAttrs & htmlAttrs: Dict.fromList [("href", "https://www.roc-lang.org/")] } [0],
|
||||
],
|
||||
siblingIds: [1],
|
||||
}
|
||||
|
||||
(List.map2 actual.nodes expected.nodes eqRenderedNode |> List.walk Bool.true Bool.and)
|
||||
(actual.nodes == expected.nodes)
|
||||
&& (actual.siblingIds == expected.siblingIds)
|
||||
|
||||
# diff
|
||||
|
@ -822,7 +784,7 @@ expect
|
|||
Ok (RenderedText "The app"),
|
||||
Ok (RenderedElement "h1" emptyRenderedAttrs [0]),
|
||||
Ok (RenderedText "The answer is 42"),
|
||||
Ok (RenderedElement "div" { emptyRenderedAttrs & eventListeners: Dict.fromList [T "click" { accessors: [], handlerId: 0 }] } [2]),
|
||||
Ok (RenderedElement "div" { emptyRenderedAttrs & eventListeners: Dict.fromList [("click", { accessors: [], handlerId: 0 })] } [2]),
|
||||
Ok (RenderedElement "body" emptyRenderedAttrs [1, 3]),
|
||||
],
|
||||
deletedNodeCache: [],
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue