working parallel implementation

This commit is contained in:
Folkert 2021-10-17 20:42:29 +02:00
parent b8a2db793f
commit 434ccbbf68
2 changed files with 194 additions and 194 deletions

View file

@ -107,6 +107,118 @@ pub enum LowLevel {
ExpectTrue, ExpectTrue,
} }
macro_rules! first_order {
() => {
StrConcat
| StrJoinWith
| StrIsEmpty
| StrStartsWith
| StrStartsWithCodePt
| StrEndsWith
| StrSplit
| StrCountGraphemes
| StrFromInt
| StrFromUtf8
| StrFromUtf8Range
| StrToUtf8
| StrRepeat
| StrFromFloat
| ListLen
| ListGetUnsafe
| ListSet
| ListDrop
| ListDropAt
| ListSingle
| ListRepeat
| ListReverse
| ListConcat
| ListContains
| ListAppend
| ListPrepend
| ListJoin
| ListRange
| ListSwap
| DictSize
| DictEmpty
| DictInsert
| DictRemove
| DictContains
| DictGetUnsafe
| DictKeys
| DictValues
| DictUnion
| DictIntersection
| DictDifference
| SetFromList
| NumAdd
| NumAddWrap
| NumAddChecked
| NumSub
| NumSubWrap
| NumSubChecked
| NumMul
| NumMulWrap
| NumMulChecked
| NumGt
| NumGte
| NumLt
| NumLte
| NumCompare
| NumDivUnchecked
| NumRemUnchecked
| NumIsMultipleOf
| NumAbs
| NumNeg
| NumSin
| NumCos
| NumSqrtUnchecked
| NumLogUnchecked
| NumRound
| NumToFloat
| NumPow
| NumCeiling
| NumPowInt
| NumFloor
| NumIsFinite
| NumAtan
| NumAcos
| NumAsin
| NumBitwiseAnd
| NumBitwiseXor
| NumBitwiseOr
| NumShiftLeftBy
| NumShiftRightBy
| NumBytesToU16
| NumBytesToU32
| NumShiftRightZfBy
| NumIntCast
| Eq
| NotEq
| And
| Or
| Not
| Hash
| ExpectTrue
};
}
macro_rules! higher_order {
() => {
ListMap
| ListMap2
| ListMap3
| ListMapWithIndex
| ListKeepIf
| ListWalk
| ListWalkUntil
| ListWalkBackwards
| ListKeepOks
| ListKeepErrs
| ListSortWith
| DictWalk
};
}
impl LowLevel { impl LowLevel {
/// is one of the arguments always a function? /// is one of the arguments always a function?
/// An example is List.map. /// An example is List.map.
@ -114,25 +226,28 @@ impl LowLevel {
use LowLevel::*; use LowLevel::*;
match self { match self {
StrConcat | StrJoinWith | StrIsEmpty | StrStartsWith | StrStartsWithCodePt first_order!() => false,
| StrEndsWith | StrSplit | StrCountGraphemes | StrFromInt | StrFromUtf8 higher_order!() => true,
| StrFromUtf8Range | StrToUtf8 | StrRepeat | StrFromFloat | ListLen | ListGetUnsafe }
| ListSet | ListDrop | ListDropAt | ListSingle | ListRepeat | ListReverse }
| ListConcat | ListContains | ListAppend | ListPrepend | ListJoin | ListRange
| ListSwap | DictSize | DictEmpty | DictInsert | DictRemove | DictContains
| DictGetUnsafe | DictKeys | DictValues | DictUnion | DictIntersection
| DictDifference | SetFromList | NumAdd | NumAddWrap | NumAddChecked | NumSub
| NumSubWrap | NumSubChecked | NumMul | NumMulWrap | NumMulChecked | NumGt | NumGte
| NumLt | NumLte | NumCompare | NumDivUnchecked | NumRemUnchecked | NumIsMultipleOf
| NumAbs | NumNeg | NumSin | NumCos | NumSqrtUnchecked | NumLogUnchecked | NumRound
| NumToFloat | NumPow | NumCeiling | NumPowInt | NumFloor | NumIsFinite | NumAtan
| NumAcos | NumAsin | NumBitwiseAnd | NumBitwiseXor | NumBitwiseOr | NumShiftLeftBy
| NumShiftRightBy | NumBytesToU16 | NumBytesToU32 | NumShiftRightZfBy | NumIntCast
| Eq | NotEq | And | Or | Not | Hash | ExpectTrue => false,
ListMap | ListMap2 | ListMap3 | ListMapWithIndex | ListKeepIf | ListWalk pub fn function_argument_position(&self) -> usize {
| ListWalkUntil | ListWalkBackwards | ListKeepOks | ListKeepErrs | ListSortWith use LowLevel::*;
| DictWalk => true,
match self {
first_order!() => unreachable!(),
ListMap => 1,
ListMap2 => 2,
ListMap3 => 3,
ListMapWithIndex => 1,
ListKeepIf => 1,
ListWalk => 2,
ListWalkUntil => 2,
ListWalkBackwards => 2,
ListKeepOks => 1,
ListKeepErrs => 1,
ListSortWith => 1,
DictWalk => 2,
} }
} }
} }

View file

@ -2707,48 +2707,6 @@ fn specialize_naked_symbol<'a>(
) )
} }
macro_rules! match_on_closure_argument {
($env:expr, $procs:expr, $layout_cache:expr, $closure_data_symbol:expr, $closure_data_var:expr, $op:expr, [$($x:expr),* $(,)?], $layout: expr, $assigned:expr, $hole:expr) => {{
let closure_data_layout = return_on_layout_error!(
$env,
$layout_cache.raw_from_var($env.arena, $closure_data_var, $env.subs)
);
let top_level = ProcLayout::from_raw($env.arena, closure_data_layout);
let arena = $env.arena;
let arg_layouts = top_level.arguments;
let ret_layout = top_level.result;
match closure_data_layout {
RawFunctionLayout::Function(_, lambda_set, _) => {
lowlevel_match_on_lambda_set(
$env,
lambda_set,
$op,
$closure_data_symbol,
|top_level_function, closure_data, closure_env_layout, specialization_id| self::Call {
call_type: CallType::HigherOrderLowLevel {
op: $op,
closure_env_layout,
specialization_id,
function_owns_closure_data: false,
arg_layouts,
ret_layout,
},
arguments: arena.alloc([$($x,)* top_level_function, closure_data]),
},
$layout,
$assigned,
$hole,
)
}
RawFunctionLayout::ZeroArgumentThunk(_) => unreachable!("match_on_closure_argument received a zero-argument thunk"),
}
}};
}
fn try_make_literal<'a>( fn try_make_literal<'a>(
env: &mut Env<'a, '_>, env: &mut Env<'a, '_>,
can_expr: &roc_can::expr::Expr, can_expr: &roc_can::expr::Expr,
@ -4041,61 +3999,11 @@ pub fn with_hole<'a>(
let layout = let layout =
return_on_layout_error!(env, layout_cache.from_var(env.arena, ret_var, env.subs)); return_on_layout_error!(env, layout_cache.from_var(env.arena, ret_var, env.subs));
let closure_data_symbol = arg_symbols[2]; macro_rules! match_on_closure_argument {
( $ho:ident, [$($x:ident),* $(,)?]) => {{
macro_rules! new_match_on_closure_argument { let closure_index = op.function_argument_position();
($env:expr, $procs:expr, $layout_cache:expr, $closure_data_symbol:expr, $closure_data_var:expr, $op:expr, $ho:ident, [$($x:ident),* $(,)?], $layout: expr, $assigned:expr, $hole:expr) => {{
let closure_data_layout = return_on_layout_error!(
$env,
$layout_cache.raw_from_var($env.arena, $closure_data_var, $env.subs)
);
let top_level = ProcLayout::from_raw($env.arena, closure_data_layout);
let arena = $env.arena;
let arg_layouts = top_level.arguments;
let ret_layout = top_level.result;
match closure_data_layout {
RawFunctionLayout::Function(_, lambda_set, _) => {
lowlevel_match_on_lambda_set(
$env,
lambda_set,
$op,
$closure_data_symbol,
|top_level_function, closure_data, closure_env_layout, specialization_id| self::Call {
call_type: CallType::NewHigherOrderLowLevel {
op: $ho { $($x,)* },
closure_env_layout,
specialization_id,
function_owns_closure_data: false,
function_env: closure_data_symbol,
function_name: top_level_function,
arg_layouts,
ret_layout,
},
arguments: arena.alloc([$($x,)* top_level_function, closure_data]),
},
$layout,
$assigned,
$hole,
)
}
RawFunctionLayout::ZeroArgumentThunk(_) => unreachable!("match_on_closure_argument received a zero-argument thunk"),
}
}};
}
use LowLevel::*;
match op {
ListMap => {
debug_assert_eq!(arg_symbols.len(), 2);
let closure_index = 1;
let closure_data_symbol = arg_symbols[closure_index]; let closure_data_symbol = arg_symbols[closure_index];
let closure_data_var = args[closure_index].0; let closure_data_var = args[closure_index].0;
let xs = arg_symbols[0];
let closure_data_layout = return_on_layout_error!( let closure_data_layout = return_on_layout_error!(
env, env,
@ -4116,12 +4024,9 @@ pub fn with_hole<'a>(
lambda_set, lambda_set,
op, op,
closure_data_symbol, closure_data_symbol,
|top_level_function, |top_level_function, closure_data, closure_env_layout, specialization_id| self::Call {
closure_data,
closure_env_layout,
specialization_id| self::Call {
call_type: CallType::NewHigherOrderLowLevel { call_type: CallType::NewHigherOrderLowLevel {
op: crate::low_level::HigherOrder::ListMap { xs }, op: crate::low_level::HigherOrder::$ho { $($x,)* },
closure_env_layout, closure_env_layout,
specialization_id, specialization_id,
function_owns_closure_data: false, function_owns_closure_data: false,
@ -4130,66 +4035,30 @@ pub fn with_hole<'a>(
arg_layouts, arg_layouts,
ret_layout, ret_layout,
}, },
arguments: arena.alloc([xs, top_level_function, closure_data]), arguments: arena.alloc([$($x,)* top_level_function, closure_data]),
}, },
layout, layout,
assigned, assigned,
hole, hole,
) )
} }
RawFunctionLayout::ZeroArgumentThunk(_) => { RawFunctionLayout::ZeroArgumentThunk(_) => unreachable!("match_on_closure_argument received a zero-argument thunk"),
unreachable!("match_on_closure_argument received a zero-argument thunk")
}
} }
}};
} }
ListMapWithIndex | ListKeepIf | ListKeepOks | ListKeepErrs | ListSortWith => { macro_rules! walk {
debug_assert_eq!(arg_symbols.len(), 2); ($oh:ident) => {{
let closure_index = 1;
let closure_data_symbol = arg_symbols[closure_index];
let closure_data_var = args[closure_index].0;
let xs = arg_symbols[0];
use crate::low_level::HigherOrder::ListMapWithIndex;
new_match_on_closure_argument!(
env,
procs,
layout_cache,
closure_data_symbol,
closure_data_var,
op,
ListMapWithIndex,
[xs],
layout,
assigned,
hole
)
}
ListWalk | ListWalkUntil | ListWalkBackwards | DictWalk => {
debug_assert_eq!(arg_symbols.len(), 3); debug_assert_eq!(arg_symbols.len(), 3);
const LIST_INDEX: usize = 0; const LIST_INDEX: usize = 0;
const DEFAULT_INDEX: usize = 1; const DEFAULT_INDEX: usize = 1;
const CLOSURE_INDEX: usize = 2; const CLOSURE_INDEX: usize = 2;
let closure_data_symbol = arg_symbols[CLOSURE_INDEX]; let xs = arg_symbols[LIST_INDEX];
let closure_data_var = args[CLOSURE_INDEX].0; let state = arg_symbols[DEFAULT_INDEX];
let stmt = match_on_closure_argument!( let stmt = match_on_closure_argument!($oh, [xs, state]);
env,
procs,
layout_cache,
closure_data_symbol,
closure_data_var,
op,
[arg_symbols[LIST_INDEX], arg_symbols[DEFAULT_INDEX]],
layout,
assigned,
hole
);
// because of a hack to implement List.product and List.sum, we need to also // 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 // assign to symbols here. Normally the arguments to a lowlevel function are
@ -4226,46 +4095,62 @@ pub fn with_hole<'a>(
arg_symbols[CLOSURE_INDEX], arg_symbols[CLOSURE_INDEX],
stmt, stmt,
) )
}};
} }
use LowLevel::*;
match op {
ListMap => {
debug_assert_eq!(arg_symbols.len(), 2);
let xs = arg_symbols[0];
match_on_closure_argument!(ListMap, [xs])
}
ListMapWithIndex => {
debug_assert_eq!(arg_symbols.len(), 2);
let xs = arg_symbols[0];
match_on_closure_argument!(ListMapWithIndex, [xs])
}
ListKeepIf => {
debug_assert_eq!(arg_symbols.len(), 2);
let xs = arg_symbols[0];
match_on_closure_argument!(ListKeepIf, [xs])
}
ListKeepOks => {
debug_assert_eq!(arg_symbols.len(), 2);
let xs = arg_symbols[0];
match_on_closure_argument!(ListKeepOks, [xs])
}
ListKeepErrs => {
debug_assert_eq!(arg_symbols.len(), 2);
let xs = arg_symbols[0];
match_on_closure_argument!(ListKeepErrs, [xs])
}
ListSortWith => {
debug_assert_eq!(arg_symbols.len(), 2);
let xs = arg_symbols[0];
match_on_closure_argument!(ListSortWith, [xs])
}
ListWalk => walk!(ListWalk),
ListWalkUntil => walk!(ListWalkUntil),
ListWalkBackwards => walk!(ListWalkBackwards),
DictWalk => walk!(DictWalk),
ListMap2 => { ListMap2 => {
debug_assert_eq!(arg_symbols.len(), 3); debug_assert_eq!(arg_symbols.len(), 3);
let closure_index = 2; let xs = arg_symbols[0];
let closure_data_symbol = arg_symbols[closure_index]; let ys = arg_symbols[1];
let closure_data_var = args[closure_index].0;
match_on_closure_argument!( match_on_closure_argument!(ListMap2, [xs, ys])
env,
procs,
layout_cache,
closure_data_symbol,
closure_data_var,
op,
[arg_symbols[0], arg_symbols[1]],
layout,
assigned,
hole
)
} }
ListMap3 => { ListMap3 => {
debug_assert_eq!(arg_symbols.len(), 4); debug_assert_eq!(arg_symbols.len(), 4);
let closure_index = 3; let xs = arg_symbols[0];
let closure_data_symbol = arg_symbols[closure_index]; let ys = arg_symbols[1];
let closure_data_var = args[closure_index].0; let zs = arg_symbols[2];
match_on_closure_argument!( match_on_closure_argument!(ListMap3, [xs, ys, zs])
env,
procs,
layout_cache,
closure_data_symbol,
closure_data_var,
op,
[arg_symbols[0], arg_symbols[1], arg_symbols[2]],
layout,
assigned,
hole
)
} }
_ => { _ => {
let call = self::Call { let call = self::Call {