remove dict/set lowlevels

This commit is contained in:
Folkert 2022-07-13 11:24:07 +02:00
parent 79f8ae4e69
commit 8e21fdcb04
No known key found for this signature in database
GPG Key ID: 1F17F6FFD112B97C
9 changed files with 7 additions and 520 deletions

View File

@ -733,31 +733,6 @@ fn call_spec(
}
match op {
DictWalk { xs, state } => {
let dict = env.symbols[xs];
let state = env.symbols[state];
let loop_body = |builder: &mut FuncDefBuilder, block, state| {
let bag = builder.add_get_tuple_field(block, dict, DICT_BAG_INDEX)?;
let element = builder.add_bag_get(block, bag)?;
let key = builder.add_get_tuple_field(block, element, 0)?;
let val = builder.add_get_tuple_field(block, element, 1)?;
let new_state = call_function!(builder, block, [state, key, val]);
Ok(new_state)
};
let state_layout = argument_layouts[0];
let state_type =
layout_spec(builder, &state_layout, &WhenRecursive::Unreachable)?;
let init_state = state;
add_loop(builder, block, state_type, init_state, loop_body)
}
ListMap { xs } => {
let list = env.symbols[xs];
@ -1001,7 +976,7 @@ fn lowlevel_spec(
// just dream up a unit value
builder.add_make_tuple(block, &[])
}
ListLen | DictSize => {
ListLen => {
// TODO should this touch the heap cell?
// just dream up a unit value
builder.add_make_tuple(block, &[])
@ -1087,47 +1062,6 @@ fn lowlevel_spec(
builder.add_make_tuple(block, &[byte_index, string, is_ok, problem_code])
}
DictEmpty => match layout {
Layout::Builtin(Builtin::Dict(key_layout, value_layout)) => {
let key_id = layout_spec(builder, key_layout, &WhenRecursive::Unreachable)?;
let value_id = layout_spec(builder, value_layout, &WhenRecursive::Unreachable)?;
new_dict(builder, block, key_id, value_id)
}
_ => unreachable!("empty array does not have a list layout"),
},
DictGetUnsafe => {
// NOTE DictGetUnsafe returns a { flag: Bool, value: v }
// when the flag is True, the value is found and defined;
// otherwise it is not and `Dict.get` should return `Err ...`
let dict = env.symbols[&arguments[0]];
let key = env.symbols[&arguments[1]];
// indicate that we use the key
builder.add_recursive_touch(block, key)?;
let bag = builder.add_get_tuple_field(block, dict, DICT_BAG_INDEX)?;
let cell = builder.add_get_tuple_field(block, dict, DICT_CELL_INDEX)?;
let _unit = builder.add_touch(block, cell)?;
builder.add_bag_get(block, bag)
}
DictInsert => {
let dict = env.symbols[&arguments[0]];
let key = env.symbols[&arguments[1]];
let value = env.symbols[&arguments[2]];
let key_value = builder.add_make_tuple(block, &[key, value])?;
let bag = builder.add_get_tuple_field(block, dict, DICT_BAG_INDEX)?;
let cell = builder.add_get_tuple_field(block, dict, DICT_CELL_INDEX)?;
let _unit = builder.add_update(block, update_mode_var, cell)?;
builder.add_bag_insert(block, bag, key_value)?;
with_new_heap_cell(builder, block, bag)
}
_other => {
// println!("missing {:?}", _other);
// TODO overly pessimstic
@ -1512,18 +1446,10 @@ fn builtin_spec(
use Builtin::*;
match builtin {
Dict(_, _) => todo!(),
Int(_) | Bool => builder.add_tuple_type(&[]),
Decimal | Float(_) => builder.add_tuple_type(&[]),
Str => str_type(builder),
Dict(key_layout, value_layout) => {
let value_type = layout_spec_help(builder, value_layout, when_recursive)?;
let key_type = layout_spec_help(builder, key_layout, when_recursive)?;
let element_type = builder.add_tuple_type(&[key_type, value_type])?;
let cell = builder.add_heap_cell_type();
let bag = builder.add_bag_type(element_type)?;
builder.add_tuple_type(&[cell, bag])
}
Set(key_layout) => {
let value_type = builder.add_tuple_type(&[])?;
let key_type = layout_spec_help(builder, key_layout, when_recursive)?;
@ -1560,9 +1486,6 @@ fn static_list_type<TC: TypeContext>(builder: &mut TC) -> Result<TypeId> {
const LIST_CELL_INDEX: u32 = 0;
const LIST_BAG_INDEX: u32 = 1;
const DICT_CELL_INDEX: u32 = LIST_CELL_INDEX;
const DICT_BAG_INDEX: u32 = LIST_BAG_INDEX;
#[allow(dead_code)]
const BOX_CELL_INDEX: u32 = LIST_CELL_INDEX;
const BOX_VALUE_INDEX: u32 = LIST_BAG_INDEX;
@ -1584,17 +1507,6 @@ fn new_list(builder: &mut FuncDefBuilder, block: BlockId, element_type: TypeId)
with_new_heap_cell(builder, block, bag)
}
fn new_dict(
builder: &mut FuncDefBuilder,
block: BlockId,
key_type: TypeId,
value_type: TypeId,
) -> Result<ValueId> {
let element_type = builder.add_tuple_type(&[key_type, value_type])?;
let bag = builder.add_empty_bag(block, element_type)?;
with_new_heap_cell(builder, block, bag)
}
fn new_static_string(builder: &mut FuncDefBuilder, block: BlockId) -> Result<ValueId> {
let module = MOD_APP;

View File

@ -58,18 +58,6 @@ macro_rules! map_symbol_to_lowlevel_and_arity {
Symbol::NUM_DIV_FRAC => Some(lowlevel_2(Symbol::NUM_DIV_FRAC, LowLevel::NumDivUnchecked, var_store)),
Symbol::NUM_DIV_TRUNC => Some(lowlevel_2(Symbol::NUM_DIV_TRUNC, LowLevel::NumDivUnchecked, var_store)),
Symbol::DICT_EMPTY => Some(dict_empty(Symbol::DICT_EMPTY, var_store)),
Symbol::SET_UNION => Some(lowlevel_2(Symbol::SET_UNION, LowLevel::DictUnion, var_store)),
Symbol::SET_DIFFERENCE => Some(lowlevel_2(Symbol::SET_DIFFERENCE, LowLevel::DictDifference, var_store)),
Symbol::SET_INTERSECTION => Some(lowlevel_2(Symbol::SET_INTERSECTION, LowLevel::DictIntersection, var_store)),
Symbol::SET_TO_LIST => Some(lowlevel_1(Symbol::SET_TO_LIST, LowLevel::DictKeys, var_store)),
Symbol::SET_REMOVE => Some(lowlevel_2(Symbol::SET_REMOVE, LowLevel::DictRemove, var_store)),
Symbol::SET_INSERT => Some(set_insert(Symbol::SET_INSERT, var_store)),
Symbol::SET_EMPTY => Some(set_empty(Symbol::SET_EMPTY, var_store)),
Symbol::SET_SINGLE => Some(set_single(Symbol::SET_SINGLE, var_store)),
_ => None,
}
}
@ -94,7 +82,6 @@ macro_rules! map_symbol_to_lowlevel_and_arity {
LowLevel::NumToIntChecked => unreachable!(),
LowLevel::NumToFloatChecked => unreachable!(),
LowLevel::NumDivUnchecked => unreachable!(),
LowLevel::DictEmpty => unreachable!(),
// these are used internally and not tied to a symbol
LowLevel::Hash => unimplemented!(),
@ -156,21 +143,6 @@ map_symbol_to_lowlevel_and_arity! {
ListDropAt; LIST_DROP_AT; 2,
ListSwap; LIST_SWAP; 3,
DictSize; DICT_LEN; 1,
DictInsert; DICT_INSERT; 3,
DictRemove; DICT_REMOVE; 2,
DictContains; DICT_CONTAINS; 2,
DictGetUnsafe; DICT_GET_LOWLEVEL; 2,
DictKeys; DICT_KEYS; 1,
DictValues; DICT_VALUES; 1,
DictUnion; DICT_UNION; 2,
DictIntersection; DICT_INTERSECTION; 2,
DictDifference; DICT_DIFFERENCE; 2,
DictWalk; DICT_WALK; 3,
SetFromList; SET_FROM_LIST; 1,
SetToDict; SET_TO_DICT; 1,
NumAdd; NUM_ADD; 2,
NumAddWrap; NUM_ADD_WRAP; 2,
NumAddChecked; NUM_ADD_CHECKED_LOWLEVEL; 2,
@ -563,95 +535,3 @@ fn to_num_checked(symbol: Symbol, var_store: &mut VarStore, lowlevel: LowLevel)
ret_var,
)
}
/// Dict.empty : Dict * *
fn dict_empty(symbol: Symbol, var_store: &mut VarStore) -> Def {
let dict_var = var_store.fresh();
let body = RunLowLevel {
op: LowLevel::DictEmpty,
args: vec![],
ret_var: dict_var,
};
Def {
annotation: None,
expr_var: dict_var,
loc_expr: Loc::at_zero(body),
loc_pattern: Loc::at_zero(Pattern::Identifier(symbol)),
pattern_vars: SendMap::default(),
}
}
/// Set.empty : Set *
fn set_empty(symbol: Symbol, var_store: &mut VarStore) -> Def {
let set_var = var_store.fresh();
let body = RunLowLevel {
op: LowLevel::DictEmpty,
args: vec![],
ret_var: set_var,
};
Def {
annotation: None,
expr_var: set_var,
loc_expr: Loc::at_zero(body),
loc_pattern: Loc::at_zero(Pattern::Identifier(symbol)),
pattern_vars: SendMap::default(),
}
}
/// Set.insert : Set k, k -> Set k
fn set_insert(symbol: Symbol, var_store: &mut VarStore) -> Def {
let dict_var = var_store.fresh();
let key_var = var_store.fresh();
let val_var = Variable::EMPTY_RECORD;
let body = RunLowLevel {
op: LowLevel::DictInsert,
args: vec![
(dict_var, Var(Symbol::ARG_1)),
(key_var, Var(Symbol::ARG_2)),
(val_var, EmptyRecord),
],
ret_var: dict_var,
};
defn(
symbol,
vec![(dict_var, Symbol::ARG_1), (key_var, Symbol::ARG_2)],
var_store,
body,
dict_var,
)
}
/// Set.single : k -> Set k
fn set_single(symbol: Symbol, var_store: &mut VarStore) -> Def {
let key_var = var_store.fresh();
let set_var = var_store.fresh();
let value_var = Variable::EMPTY_RECORD;
let empty = RunLowLevel {
op: LowLevel::DictEmpty,
args: vec![],
ret_var: set_var,
};
let body = RunLowLevel {
op: LowLevel::DictInsert,
args: vec![
(set_var, empty),
(key_var, Var(Symbol::ARG_1)),
(value_var, EmptyRecord),
],
ret_var: set_var,
};
defn(
symbol,
vec![(key_var, Symbol::ARG_1)],
var_store,
body,
set_var,
)
}

View File

@ -2,10 +2,6 @@ use crate::llvm::bitcode::{
call_bitcode_fn, call_bitcode_fn_fixing_for_convention, call_list_bitcode_fn,
call_str_bitcode_fn, call_void_bitcode_fn,
};
use crate::llvm::build_dict::{
self, dict_contains, dict_difference, dict_empty, dict_get, dict_insert, dict_intersection,
dict_keys, dict_len, dict_remove, dict_union, dict_values, dict_walk, set_from_list,
};
use crate::llvm::build_hash::generic_hash;
use crate::llvm::build_list::{
self, allocate_list, empty_polymorphic_list, list_append_unsafe, list_concat, list_drop_at,
@ -2265,15 +2261,6 @@ pub fn allocate_with_refcount_help<'a, 'ctx, 'env>(
.into_pointer_value()
}
macro_rules! dict_key_value_layout {
($dict_layout:expr) => {
match $dict_layout {
Layout::Builtin(Builtin::Dict(key_layout, value_layout)) => (key_layout, value_layout),
_ => unreachable!("invalid dict layout"),
}
};
}
macro_rules! list_element_layout {
($list_layout:expr) => {
match $list_layout {
@ -2824,18 +2811,10 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
build_list::decref(env, value.into_struct_value(), alignment);
}
Layout::Builtin(Builtin::Dict(key_layout, value_layout)) => {
debug_assert!(value.is_struct_value());
let alignment = key_layout
.alignment_bytes(env.target_info)
.max(value_layout.alignment_bytes(env.target_info));
build_dict::decref(env, value.into_struct_value(), alignment);
todo!()
}
Layout::Builtin(Builtin::Set(key_layout)) => {
debug_assert!(value.is_struct_value());
let alignment = key_layout.alignment_bytes(env.target_info);
build_dict::decref(env, value.into_struct_value(), alignment);
todo!()
}
_ if layout.is_refcounted() => {
@ -5341,40 +5320,6 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
_ => unreachable!("invalid list layout"),
}
}
DictWalk { xs, state } => {
let (dict, dict_layout) = load_symbol_and_layout(scope, xs);
let (default, default_layout) = load_symbol_and_layout(scope, state);
let (function, closure, closure_layout) = function_details!();
match dict_layout {
Layout::Builtin(Builtin::Dict(key_layout, value_layout)) => {
let argument_layouts = &[*default_layout, **key_layout, **value_layout];
let roc_function_call = roc_function_call(
env,
layout_ids,
function,
closure,
closure_layout,
function_owns_closure_data,
argument_layouts,
result_layout,
);
dict_walk(
env,
roc_function_call,
dict,
default,
key_layout,
value_layout,
default_layout,
)
}
_ => unreachable!("invalid dict layout"),
}
}
}
}
@ -6135,109 +6080,8 @@ fn run_low_level<'a, 'ctx, 'env>(
generic_hash(env, layout_ids, seed.into_int_value(), value, layout).into()
}
DictSize => {
debug_assert_eq!(args.len(), 1);
dict_len(env, scope, args[0])
}
DictEmpty => {
debug_assert_eq!(args.len(), 0);
dict_empty(env)
}
DictInsert => {
debug_assert_eq!(args.len(), 3);
let (dict, _) = load_symbol_and_layout(scope, &args[0]);
let (key, key_layout) = load_symbol_and_layout(scope, &args[1]);
let (value, value_layout) = load_symbol_and_layout(scope, &args[2]);
dict_insert(env, layout_ids, dict, key, key_layout, value, value_layout)
}
DictRemove => {
debug_assert_eq!(args.len(), 2);
let (dict, dict_layout) = load_symbol_and_layout(scope, &args[0]);
let key = load_symbol(scope, &args[1]);
let (key_layout, value_layout) = dict_key_value_layout!(dict_layout);
dict_remove(env, layout_ids, dict, key, key_layout, value_layout)
}
DictContains => {
debug_assert_eq!(args.len(), 2);
let (dict, dict_layout) = load_symbol_and_layout(scope, &args[0]);
let key = load_symbol(scope, &args[1]);
let (key_layout, value_layout) = dict_key_value_layout!(dict_layout);
dict_contains(env, layout_ids, dict, key, key_layout, value_layout)
}
DictGetUnsafe => {
debug_assert_eq!(args.len(), 2);
let (dict, dict_layout) = load_symbol_and_layout(scope, &args[0]);
let key = load_symbol(scope, &args[1]);
let (key_layout, value_layout) = dict_key_value_layout!(dict_layout);
dict_get(env, layout_ids, dict, key, key_layout, value_layout)
}
DictKeys => {
debug_assert_eq!(args.len(), 1);
let (dict, dict_layout) = load_symbol_and_layout(scope, &args[0]);
let (key_layout, value_layout) = dict_key_value_layout!(dict_layout);
dict_keys(env, layout_ids, dict, key_layout, value_layout)
}
DictValues => {
debug_assert_eq!(args.len(), 1);
let (dict, dict_layout) = load_symbol_and_layout(scope, &args[0]);
let (key_layout, value_layout) = dict_key_value_layout!(dict_layout);
dict_values(env, layout_ids, dict, key_layout, value_layout)
}
DictUnion => {
debug_assert_eq!(args.len(), 2);
let (dict1, dict_layout) = load_symbol_and_layout(scope, &args[0]);
let (dict2, _) = load_symbol_and_layout(scope, &args[1]);
let (key_layout, value_layout) = dict_key_value_layout!(dict_layout);
dict_union(env, layout_ids, dict1, dict2, key_layout, value_layout)
}
DictDifference => {
debug_assert_eq!(args.len(), 2);
let (dict1, dict_layout) = load_symbol_and_layout(scope, &args[0]);
let (dict2, _) = load_symbol_and_layout(scope, &args[1]);
let (key_layout, value_layout) = dict_key_value_layout!(dict_layout);
dict_difference(env, layout_ids, dict1, dict2, key_layout, value_layout)
}
DictIntersection => {
debug_assert_eq!(args.len(), 2);
let (dict1, dict_layout) = load_symbol_and_layout(scope, &args[0]);
let (dict2, _) = load_symbol_and_layout(scope, &args[1]);
let (key_layout, value_layout) = dict_key_value_layout!(dict_layout);
dict_intersection(env, layout_ids, dict1, dict2, key_layout, value_layout)
}
SetFromList => {
debug_assert_eq!(args.len(), 1);
let (list, list_layout) = load_symbol_and_layout(scope, &args[0]);
let key_layout = list_element_layout!(list_layout);
set_from_list(env, layout_ids, list, key_layout)
}
SetToDict => {
debug_assert_eq!(args.len(), 1);
let (set, _set_layout) = load_symbol_and_layout(scope, &args[0]);
set
}
ListMap | ListMap2 | ListMap3 | ListMap4 | ListSortWith | DictWalk => {
ListMap | ListMap2 | ListMap3 | ListMap4 | ListSortWith => {
unreachable!("these are higher order, and are handled elsewhere")
}

View File

@ -315,7 +315,7 @@ impl<'a> LowLevelCall<'a> {
ListIsUnique => self.load_args_and_call_zig(backend, bitcode::LIST_IS_UNIQUE),
ListMap | ListMap2 | ListMap3 | ListMap4 | ListSortWith | DictWalk => {
ListMap | ListMap2 | ListMap3 | ListMap4 | ListSortWith => {
internal_error!("HigherOrder lowlevels should not be handled here")
}
@ -744,12 +744,6 @@ impl<'a> LowLevelCall<'a> {
backend.call_host_fn_after_loading_args(bitcode::LIST_SWAP, 8, false);
}
DictSize | DictEmpty | DictInsert | DictRemove | DictContains | DictGetUnsafe
| DictKeys | DictValues | DictUnion | DictIntersection | DictDifference
| SetFromList | SetToDict => {
todo!("{:?}", self.lowlevel);
}
// Num
NumAdd => match self.ret_layout {
Layout::Builtin(Builtin::Int(width)) => {
@ -2082,7 +2076,6 @@ pub fn call_higher_order_lowlevel<'a>(
ListMap { .. } | ListMap2 { .. } | ListMap3 { .. } | ListMap4 { .. } => {
ProcSource::HigherOrderMapper(passed_proc_index)
}
DictWalk { .. } => todo!("DictWalk"),
}
};
let wrapper_sym = backend.create_symbol(&format!("#wrap#{:?}", fn_name));
@ -2230,8 +2223,6 @@ pub fn call_higher_order_lowlevel<'a>(
backend.call_host_fn_after_loading_args(bitcode::LIST_SORT_WITH, 9, false);
}
DictWalk { .. } => todo!("{:?}", op),
}
}

View File

@ -46,20 +46,6 @@ pub enum LowLevel {
ListDropAt,
ListSwap,
ListIsUnique,
DictSize,
DictEmpty,
DictInsert,
DictRemove,
DictContains,
DictGetUnsafe,
DictKeys,
DictValues,
DictUnion,
DictIntersection,
DictDifference,
DictWalk,
SetFromList,
SetToDict,
NumAdd,
NumAddWrap,
NumAddChecked,
@ -126,7 +112,7 @@ pub enum LowLevel {
macro_rules! higher_order {
() => {
ListMap | ListMap2 | ListMap3 | ListMap4 | ListSortWith | DictWalk
ListMap | ListMap2 | ListMap3 | ListMap4 | ListSortWith
};
}
@ -148,7 +134,6 @@ impl LowLevel {
ListMap3 => 3,
ListMap4 => 4,
ListSortWith => 1,
DictWalk => 2,
_ => unreachable!(),
}
}
@ -207,7 +192,6 @@ macro_rules! map_symbol_to_lowlevel {
LowLevel::ListMap3 => unreachable!(),
LowLevel::ListMap4 => unreachable!(),
LowLevel::ListSortWith => unreachable!(),
LowLevel::DictWalk => unreachable!(),
// (un)boxing is handled in a custom way
LowLevel::BoxExpr => unreachable!(),
@ -219,7 +203,6 @@ macro_rules! map_symbol_to_lowlevel {
LowLevel::NumToIntChecked => unreachable!(),
LowLevel::NumToFloatChecked => unreachable!(),
LowLevel::NumDivUnchecked => unreachable!(),
LowLevel::DictEmpty => unreachable!(),
// these are used internally and not tied to a symbol
LowLevel::Hash => unimplemented!(),
@ -275,18 +258,6 @@ map_symbol_to_lowlevel! {
ListSublist <= LIST_SUBLIST_LOWLEVEL,
ListDropAt <= LIST_DROP_AT,
ListSwap <= LIST_SWAP,
DictSize <= DICT_LEN,
DictInsert <= DICT_INSERT,
DictRemove <= DICT_REMOVE,
DictContains <= DICT_CONTAINS,
DictGetUnsafe <= DICT_GET_LOWLEVEL,
DictKeys <= DICT_KEYS,
DictValues <= DICT_VALUES,
DictUnion <= DICT_UNION,
DictIntersection <= DICT_INTERSECTION,
DictDifference <= DICT_DIFFERENCE,
SetFromList <= SET_FROM_LIST,
SetToDict <= SET_TO_DICT,
NumAdd <= NUM_ADD,
NumAddWrap <= NUM_ADD_WRAP,
NumAddChecked <= NUM_ADD_CHECKED_LOWLEVEL,

View File

@ -602,17 +602,6 @@ impl<'a> BorrowInfState<'a> {
// always own the input list
self.own_var(*xs);
}
DictWalk { xs, state } => {
// own the default value if the function wants to own it
if !function_ps[0].borrow {
self.own_var(*state);
}
// own the data structure if the function wants to own the element
if !function_ps[1].borrow {
self.own_var(*xs);
}
}
}
// own the closure environment if the function needs to own it
@ -939,20 +928,6 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] {
StrRepeat => arena.alloc_slice_copy(&[borrowed, irrelevant]),
StrFromInt | StrFromFloat => arena.alloc_slice_copy(&[irrelevant]),
Hash => arena.alloc_slice_copy(&[borrowed, irrelevant]),
DictSize => arena.alloc_slice_copy(&[borrowed]),
DictEmpty => &[],
DictInsert => arena.alloc_slice_copy(&[owned, owned, owned]),
DictRemove => arena.alloc_slice_copy(&[owned, borrowed]),
DictContains => arena.alloc_slice_copy(&[borrowed, borrowed]),
DictGetUnsafe => arena.alloc_slice_copy(&[borrowed, borrowed]),
DictKeys | DictValues => arena.alloc_slice_copy(&[borrowed]),
DictUnion | DictDifference | DictIntersection => arena.alloc_slice_copy(&[owned, borrowed]),
// borrow function argument so we don't have to worry about RC of the closure
DictWalk => arena.alloc_slice_copy(&[owned, owned, function, closure_data]),
SetFromList => arena.alloc_slice_copy(&[owned]),
SetToDict => arena.alloc_slice_copy(&[owned]),
ListIsUnique => arena.alloc_slice_copy(&[borrowed]),

View File

@ -809,22 +809,6 @@ impl<'a> Context<'a> {
let v = create_call!(function_ps.get(2));
handle_ownerships_pre!(Stmt::Let(z, v, l, b), ownerships)
}
DictWalk { xs, state: _ } => {
let ownerships = [
// borrow data structure based on second argument of the folded function
(xs, function_ps[1]),
];
// borrow the default based on first argument of the folded function
// (state, function_ps[0])
let b = self.add_dec_after_lowlevel(after_arguments, &borrows, b, b_live_vars);
let b = handle_ownerships_post!(b, ownerships);
let v = create_call!(function_ps.get(2));
handle_ownerships_pre!(Stmt::Let(z, v, l, b), ownerships)
}
}

View File

@ -4986,57 +4986,6 @@ pub fn with_hole<'a>(
}};
}
macro_rules! walk {
($oh:ident) => {{
debug_assert_eq!(arg_symbols.len(), 3);
const LIST_INDEX: usize = 0;
const DEFAULT_INDEX: usize = 1;
const CLOSURE_INDEX: usize = 2;
let xs = arg_symbols[LIST_INDEX];
let state = arg_symbols[DEFAULT_INDEX];
let stmt = match_on_closure_argument!($oh, [xs, state]);
// because of a hack to implement List.product and List.sum, we need to also
// assign to symbols here. Normally the arguments to a lowlevel function are
// all symbols anyway, but because of this hack the closure symbol can be an
// actual closure, and the default is either the number 1 or 0
// this can be removed when we define builtin modules as proper modules
let stmt = assign_to_symbol(
env,
procs,
layout_cache,
args[LIST_INDEX].0,
Loc::at_zero(args[LIST_INDEX].1.clone()),
arg_symbols[LIST_INDEX],
stmt,
);
let stmt = assign_to_symbol(
env,
procs,
layout_cache,
args[DEFAULT_INDEX].0,
Loc::at_zero(args[DEFAULT_INDEX].1.clone()),
arg_symbols[DEFAULT_INDEX],
stmt,
);
assign_to_symbol(
env,
procs,
layout_cache,
args[CLOSURE_INDEX].0,
Loc::at_zero(args[CLOSURE_INDEX].1.clone()),
arg_symbols[CLOSURE_INDEX],
stmt,
)
}};
}
use LowLevel::*;
match op {
ListMap => {
@ -5049,7 +4998,6 @@ pub fn with_hole<'a>(
let xs = arg_symbols[0];
match_on_closure_argument!(ListSortWith, [xs])
}
DictWalk => walk!(DictWalk),
ListMap2 => {
debug_assert_eq!(arg_symbols.len(), 3);

View File

@ -23,10 +23,6 @@ pub enum HigherOrder {
ListSortWith {
xs: Symbol,
},
DictWalk {
xs: Symbol,
state: Symbol,
},
}
impl HigherOrder {
@ -37,7 +33,6 @@ impl HigherOrder {
HigherOrder::ListMap3 { .. } => 3,
HigherOrder::ListMap4 { .. } => 4,
HigherOrder::ListSortWith { .. } => 2,
HigherOrder::DictWalk { .. } => 2,
}
}
@ -51,7 +46,6 @@ impl HigherOrder {
ListMap2 { .. } => 3,
ListMap3 { .. } => 4,
ListMap4 { .. } => 5,
DictWalk { .. } => 3,
}
}
@ -85,18 +79,6 @@ enum FirstOrder {
ListAppend,
ListPrepend,
ListSwap,
DictSize,
DictEmpty,
DictInsert,
DictRemove,
DictContains,
DictGetUnsafe,
DictKeys,
DictValues,
DictUnion,
DictIntersection,
DictDifference,
SetFromList,
NumAdd,
NumAddWrap,
NumAddChecked,