working AStar

This commit is contained in:
Folkert 2021-02-15 21:34:55 +01:00
parent 9527434be8
commit 13b2c23c01
19 changed files with 578 additions and 81 deletions

View file

@ -1,10 +1,11 @@
use crate::def::Def;
use crate::expr::Expr::*;
use crate::expr::{Expr, Recursive};
use crate::expr::{Expr, Recursive, WhenBranch};
use crate::pattern::Pattern;
use roc_collections::all::{MutMap, SendMap};
use roc_module::ident::TagName;
use roc_module::low_level::LowLevel;
use roc_module::operator::CalledVia;
use roc_module::symbol::Symbol;
use roc_region::all::{Located, Region};
use roc_types::subs::{VarStore, Variable};
@ -60,6 +61,7 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option<Def>
STR_ENDS_WITH => str_ends_with,
STR_COUNT_GRAPHEMES => str_count_graphemes,
STR_FROM_INT => str_from_int,
STR_FROM_FLOAT=> str_from_float,
LIST_LEN => list_len,
LIST_GET => list_get,
LIST_SET => list_set,
@ -144,7 +146,10 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option<Def>
NUM_MAX_INT => num_max_int,
NUM_MIN_INT => num_min_int,
NUM_BITWISE_AND => num_bitwise_and,
NUM_BITWISE_XOR => num_bitwise_xor
NUM_BITWISE_XOR => num_bitwise_xor,
RESULT_MAP => result_map,
RESULT_MAP_ERR => result_map_err,
RESULT_WITH_DEFAULT => result_with_default,
}
}
@ -180,6 +185,7 @@ pub fn builtin_defs(var_store: &mut VarStore) -> MutMap<Symbol, Def> {
Symbol::STR_ENDS_WITH => str_ends_with,
Symbol::STR_COUNT_GRAPHEMES => str_count_graphemes,
Symbol::STR_FROM_INT => str_from_int,
Symbol::STR_FROM_FLOAT=> str_from_float,
Symbol::LIST_LEN => list_len,
Symbol::LIST_GET => list_get,
Symbol::LIST_SET => list_set,
@ -259,6 +265,9 @@ pub fn builtin_defs(var_store: &mut VarStore) -> MutMap<Symbol, Def> {
Symbol::NUM_ASIN => num_asin,
Symbol::NUM_MAX_INT => num_max_int,
Symbol::NUM_MIN_INT => num_min_int,
Symbol::RESULT_MAP => result_map,
Symbol::RESULT_MAP_ERR => result_map_err,
Symbol::RESULT_WITH_DEFAULT => result_with_default,
}
}
@ -1404,7 +1413,7 @@ fn str_count_graphemes(symbol: Symbol, var_store: &mut VarStore) -> Def {
)
}
/// Str.fromInt : Int -> Str
/// Str.fromInt : Int * -> Str
fn str_from_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
let int_var = var_store.fresh();
let str_var = var_store.fresh();
@ -1424,6 +1433,26 @@ fn str_from_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
)
}
/// Str.fromFloat : Float * -> Str
fn str_from_float(symbol: Symbol, var_store: &mut VarStore) -> Def {
let float_var = var_store.fresh();
let str_var = var_store.fresh();
let body = RunLowLevel {
op: LowLevel::StrFromFloat,
args: vec![(float_var, Var(Symbol::ARG_1))],
ret_var: str_var,
};
defn(
symbol,
vec![(float_var, Symbol::ARG_1)],
var_store,
body,
str_var,
)
}
/// List.concat : List elem, List elem -> List elem
fn list_concat(symbol: Symbol, var_store: &mut VarStore) -> Def {
let list_var = var_store.fresh();
@ -2365,15 +2394,12 @@ fn set_remove(symbol: Symbol, var_store: &mut VarStore) -> Def {
/// Set.walk : Set k, (k, accum -> accum), accum -> accum
fn set_walk(symbol: Symbol, var_store: &mut VarStore) -> Def {
use roc_module::operator::CalledVia;
let dict_var = var_store.fresh();
let func_var = var_store.fresh();
let key_var = var_store.fresh();
let accum_var = var_store.fresh();
let wrapper_var = var_store.fresh();
// let (fn_var, loc_fn, closure_var, ret_var) = &**boxed;
let user_function = Box::new((
func_var,
no_region(Var(Symbol::ARG_2)),
@ -2835,6 +2861,263 @@ fn list_last(symbol: Symbol, var_store: &mut VarStore) -> Def {
)
}
fn result_map(symbol: Symbol, var_store: &mut VarStore) -> Def {
let ret_var = var_store.fresh();
let func_var = var_store.fresh();
let result_var = var_store.fresh();
let mut branches = vec![];
{
let user_function = Box::new((
func_var,
no_region(Var(Symbol::ARG_2)),
var_store.fresh(),
var_store.fresh(),
));
let call_func = Call(
user_function,
vec![(var_store.fresh(), no_region(Var(Symbol::ARG_5)))],
CalledVia::Space,
);
let tag_name = TagName::Global("Ok".into());
// ok branch
let ok = Tag {
variant_var: var_store.fresh(),
ext_var: var_store.fresh(),
name: tag_name.clone(),
arguments: vec![(var_store.fresh(), no_region(call_func))],
};
let pattern = Pattern::AppliedTag {
whole_var: result_var,
ext_var: var_store.fresh(),
tag_name,
arguments: vec![(
var_store.fresh(),
no_region(Pattern::Identifier(Symbol::ARG_5)),
)],
};
let branch = WhenBranch {
patterns: vec![no_region(pattern)],
value: no_region(ok),
guard: None,
};
branches.push(branch);
}
{
// err branch
let tag_name = TagName::Global("Err".into());
let err = Tag {
variant_var: var_store.fresh(),
ext_var: var_store.fresh(),
name: tag_name.clone(),
arguments: vec![(var_store.fresh(), no_region(Var(Symbol::ARG_4)))],
};
let pattern = Pattern::AppliedTag {
whole_var: result_var,
ext_var: var_store.fresh(),
tag_name,
arguments: vec![(
var_store.fresh(),
no_region(Pattern::Identifier(Symbol::ARG_4)),
)],
};
let branch = WhenBranch {
patterns: vec![no_region(pattern)],
value: no_region(err),
guard: None,
};
branches.push(branch);
}
let body = When {
cond_var: result_var,
expr_var: ret_var,
region: Region::zero(),
loc_cond: Box::new(no_region(Var(Symbol::ARG_1))),
branches,
};
defn(
symbol,
vec![(result_var, Symbol::ARG_1), (func_var, Symbol::ARG_2)],
var_store,
body,
ret_var,
)
}
fn result_map_err(symbol: Symbol, var_store: &mut VarStore) -> Def {
let ret_var = var_store.fresh();
let func_var = var_store.fresh();
let result_var = var_store.fresh();
let mut branches = vec![];
{
let user_function = Box::new((
func_var,
no_region(Var(Symbol::ARG_2)),
var_store.fresh(),
var_store.fresh(),
));
let call_func = Call(
user_function,
vec![(var_store.fresh(), no_region(Var(Symbol::ARG_5)))],
CalledVia::Space,
);
let tag_name = TagName::Global("Err".into());
// ok branch
let ok = Tag {
variant_var: var_store.fresh(),
ext_var: var_store.fresh(),
name: tag_name.clone(),
arguments: vec![(var_store.fresh(), no_region(call_func))],
};
let pattern = Pattern::AppliedTag {
whole_var: result_var,
ext_var: var_store.fresh(),
tag_name,
arguments: vec![(
var_store.fresh(),
no_region(Pattern::Identifier(Symbol::ARG_5)),
)],
};
let branch = WhenBranch {
patterns: vec![no_region(pattern)],
value: no_region(ok),
guard: None,
};
branches.push(branch);
}
{
// err branch
let tag_name = TagName::Global("Ok".into());
let err = Tag {
variant_var: var_store.fresh(),
ext_var: var_store.fresh(),
name: tag_name.clone(),
arguments: vec![(var_store.fresh(), no_region(Var(Symbol::ARG_4)))],
};
let pattern = Pattern::AppliedTag {
whole_var: result_var,
ext_var: var_store.fresh(),
tag_name,
arguments: vec![(
var_store.fresh(),
no_region(Pattern::Identifier(Symbol::ARG_4)),
)],
};
let branch = WhenBranch {
patterns: vec![no_region(pattern)],
value: no_region(err),
guard: None,
};
branches.push(branch);
}
let body = When {
cond_var: result_var,
expr_var: ret_var,
region: Region::zero(),
loc_cond: Box::new(no_region(Var(Symbol::ARG_1))),
branches,
};
defn(
symbol,
vec![(result_var, Symbol::ARG_1), (func_var, Symbol::ARG_2)],
var_store,
body,
ret_var,
)
}
fn result_with_default(symbol: Symbol, var_store: &mut VarStore) -> Def {
let ret_var = var_store.fresh();
let result_var = var_store.fresh();
let mut branches = vec![];
{
// ok branch
let tag_name = TagName::Global("Ok".into());
let pattern = Pattern::AppliedTag {
whole_var: result_var,
ext_var: var_store.fresh(),
tag_name,
arguments: vec![(ret_var, no_region(Pattern::Identifier(Symbol::ARG_3)))],
};
let branch = WhenBranch {
patterns: vec![no_region(pattern)],
value: no_region(Var(Symbol::ARG_3)),
guard: None,
};
branches.push(branch);
}
{
// err branch
let tag_name = TagName::Global("Err".into());
let pattern = Pattern::AppliedTag {
whole_var: result_var,
ext_var: var_store.fresh(),
tag_name,
arguments: vec![(var_store.fresh(), no_region(Pattern::Underscore))],
};
let branch = WhenBranch {
patterns: vec![no_region(pattern)],
value: no_region(Var(Symbol::ARG_2)),
guard: None,
};
branches.push(branch);
}
let body = When {
cond_var: result_var,
expr_var: ret_var,
region: Region::zero(),
loc_cond: Box::new(no_region(Var(Symbol::ARG_1))),
branches,
};
defn(
symbol,
vec![(result_var, Symbol::ARG_1), (ret_var, Symbol::ARG_2)],
var_store,
body,
ret_var,
)
}
#[inline(always)]
fn no_region<T>(value: T) -> Located<T> {
Located {