Add List.takeFisrt2, List.takeLast2 for demo

This commit is contained in:
satotake 2021-11-12 12:23:41 +00:00 committed by GitHub
parent ac733b1805
commit d63849c5a3
5 changed files with 265 additions and 0 deletions

View file

@ -94,6 +94,8 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option<Def>
LIST_MAP4 => list_map4,
LIST_TAKE_FIRST => list_take_first,
LIST_TAKE_LAST => list_take_last,
LIST_TAKE_FIRST_2 => list_take_first_2,
LIST_TAKE_LAST_2 => list_take_last_2,
LIST_SUBLIST => list_sublist,
LIST_DROP => list_drop,
LIST_DROP_AT => list_drop_at,
@ -2038,6 +2040,120 @@ fn list_take_first(symbol: Symbol, var_store: &mut VarStore) -> Def {
)
}
/// List.takeFirst2 : List elem, Nat -> List elem
fn list_take_first_2(symbol: Symbol, var_store: &mut VarStore) -> Def {
let list_var = var_store.fresh();
let len_var = var_store.fresh();
let sym_rec = Symbol::LIST_TAKE_3_TEMP;
let int_var = var_store.fresh();
let bool_var = var_store.fresh();
let clos_var = var_store.fresh();
let list_after = var_store.fresh();
let one = || int(int_var, Variable::NATURAL, 1);
let clos = Closure(ClosureData {
function_type: clos_var,
closure_type: var_store.fresh(),
closure_ext_var: var_store.fresh(),
return_type: list_after,
name: sym_rec,
recursive: Recursive::Recursive,
captured_symbols: vec![],
arguments: vec![(list_after, no_region(Pattern::Identifier(Symbol::ARG_3)))],
loc_body: {
Box::new(no_region(If {
cond_var: var_store.fresh(),
branch_var: var_store.fresh(),
branches: vec![(
no_region(RunLowLevel {
op: LowLevel::NumLte,
args: vec![
(
int_var,
RunLowLevel {
op: LowLevel::ListLen,
args: vec![(list_after, Var(Symbol::ARG_3))],
ret_var: int_var,
},
),
(int_var, Var(Symbol::ARG_2)),
],
ret_var: bool_var,
}),
no_region(Var(Symbol::ARG_3)),
)],
final_else: Box::new(no_region(Call(
Box::new((
clos_var,
no_region(Var(sym_rec)),
var_store.fresh(),
list_after,
)),
vec![(
list_after,
no_region(RunLowLevel {
// DropLast
op: LowLevel::ListDrop,
args: vec![
(list_after, Var(Symbol::ARG_3)),
(
int_var,
RunLowLevel {
ret_var: int_var,
op: LowLevel::NumSubWrap,
args: vec![
(
int_var,
RunLowLevel {
ret_var: int_var,
op: LowLevel::ListLen,
args: vec![(list_after, Var(Symbol::ARG_3))],
},
),
(int_var, one()),
],
},
),
],
ret_var: list_after,
}),
)],
CalledVia::Space,
))),
}))
},
});
let def_rec = Def {
annotation: None,
expr_var: int_var,
loc_expr: no_region(clos),
loc_pattern: no_region(Pattern::Identifier(sym_rec)),
pattern_vars: Default::default(),
};
let body = Call(
Box::new((
clos_var,
no_region(Var(sym_rec)),
var_store.fresh(),
list_var,
)),
vec![(list_var, no_region(Var(Symbol::ARG_1)))],
CalledVia::Space,
);
defn(
symbol,
vec![(list_var, Symbol::ARG_1), (len_var, Symbol::ARG_2)],
var_store,
LetRec(vec![def_rec], Box::new(no_region(body)), list_var),
list_var,
)
}
/// List.takeLast : List elem, Nat -> List elem
fn list_take_last(symbol: Symbol, var_store: &mut VarStore) -> Def {
let list_var = var_store.fresh();
@ -2061,6 +2177,78 @@ fn list_take_last(symbol: Symbol, var_store: &mut VarStore) -> Def {
)
}
/// List.takeLast2 : List elem, Nat -> List elem
fn list_take_last_2(symbol: Symbol, var_store: &mut VarStore) -> Def {
let list_var = var_store.fresh();
let len_var = var_store.fresh();
let sym_list = Symbol::ARG_1;
let sym_len = Symbol::ARG_2;
let drop_len = Symbol::LIST_TAKE_2_TEMP;
let bool_var = var_store.fresh();
let int_var = var_store.fresh();
let zero = || int(int_var, Variable::NATURAL, 0);
let def_drop_len = Def {
annotation: None,
expr_var: int_var,
loc_expr: no_region(RunLowLevel {
op: LowLevel::NumSubWrap,
args: vec![
(
int_var,
RunLowLevel {
op: LowLevel::ListLen,
args: vec![(list_var, Var(sym_list))],
ret_var: int_var,
},
),
(int_var, Var(sym_len)),
],
ret_var: int_var,
}),
loc_pattern: no_region(Pattern::Identifier(drop_len)),
pattern_vars: Default::default(),
};
let get_larger = If {
cond_var: bool_var,
branch_var: int_var,
branches: vec![(
no_region(RunLowLevel {
op: LowLevel::NumGte,
args: vec![(int_var, Var(drop_len)), (int_var, zero())],
ret_var: bool_var,
}),
no_region(Var(drop_len)),
)],
final_else: Box::new(no_region(zero())),
};
let body_drop = RunLowLevel {
op: LowLevel::ListDrop,
args: vec![(list_var, Var(sym_list)), (int_var, get_larger)],
ret_var: list_var,
};
let body = LetNonRec(
Box::new(def_drop_len),
Box::new(no_region(body_drop)),
list_var,
);
defn(
symbol,
vec![(list_var, sym_list), (len_var, sym_len)],
var_store,
body,
list_var,
)
}
/// List.sublist : List elem, { start : Nat, len : Nat } -> List elem
fn list_sublist(symbol: Symbol, var_store: &mut VarStore) -> Def {
let list_var = var_store.fresh();