mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 00:24:34 +00:00
Merge remote-tracking branch 'origin/trunk' into import-builtin-mod
This commit is contained in:
commit
e3b65b1ce0
31 changed files with 577 additions and 728 deletions
39
Cargo.lock
generated
39
Cargo.lock
generated
|
@ -889,25 +889,6 @@ version = "0.3.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
|
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "docs"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"bumpalo",
|
|
||||||
"fs_extra",
|
|
||||||
"handlebars",
|
|
||||||
"maplit",
|
|
||||||
"pretty_assertions 0.5.1",
|
|
||||||
"pulldown-cmark",
|
|
||||||
"roc_builtins",
|
|
||||||
"roc_can",
|
|
||||||
"roc_collections",
|
|
||||||
"roc_load",
|
|
||||||
"serde",
|
|
||||||
"serde_derive",
|
|
||||||
"serde_json",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "downcast-rs"
|
name = "downcast-rs"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
|
@ -2961,6 +2942,7 @@ dependencies = [
|
||||||
"roc_can",
|
"roc_can",
|
||||||
"roc_collections",
|
"roc_collections",
|
||||||
"roc_constrain",
|
"roc_constrain",
|
||||||
|
"roc_docs",
|
||||||
"roc_editor",
|
"roc_editor",
|
||||||
"roc_fmt",
|
"roc_fmt",
|
||||||
"roc_gen",
|
"roc_gen",
|
||||||
|
@ -3012,6 +2994,25 @@ dependencies = [
|
||||||
"roc_types",
|
"roc_types",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "roc_docs"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"fs_extra",
|
||||||
|
"handlebars",
|
||||||
|
"maplit",
|
||||||
|
"pretty_assertions 0.5.1",
|
||||||
|
"pulldown-cmark",
|
||||||
|
"roc_builtins",
|
||||||
|
"roc_can",
|
||||||
|
"roc_collections",
|
||||||
|
"roc_load",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "roc_editor"
|
name = "roc_editor"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
|
@ -33,6 +33,7 @@ target-all = [
|
||||||
[dependencies]
|
[dependencies]
|
||||||
roc_collections = { path = "../compiler/collections" }
|
roc_collections = { path = "../compiler/collections" }
|
||||||
roc_can = { path = "../compiler/can" }
|
roc_can = { path = "../compiler/can" }
|
||||||
|
roc_docs = { path = "../docs" }
|
||||||
roc_parse = { path = "../compiler/parse" }
|
roc_parse = { path = "../compiler/parse" }
|
||||||
roc_region = { path = "../compiler/region" }
|
roc_region = { path = "../compiler/region" }
|
||||||
roc_module = { path = "../compiler/module" }
|
roc_module = { path = "../compiler/module" }
|
||||||
|
|
|
@ -8,7 +8,7 @@ use roc_build::link::LinkType;
|
||||||
use roc_gen::llvm::build::OptLevel;
|
use roc_gen::llvm::build::OptLevel;
|
||||||
use roc_load::file::LoadingProblem;
|
use roc_load::file::LoadingProblem;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::Path;
|
use std::path::{Path, PathBuf};
|
||||||
use std::process;
|
use std::process;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use target_lexicon::Triple;
|
use target_lexicon::Triple;
|
||||||
|
@ -76,6 +76,21 @@ pub fn build_app<'a>() -> App<'a> {
|
||||||
.help("(optional) The directory or files to open on launch.")
|
.help("(optional) The directory or files to open on launch.")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
.subcommand(
|
||||||
|
App::new("docs")
|
||||||
|
.about("Generate documentation for Roc modules")
|
||||||
|
.arg(Arg::with_name(DIRECTORY_OR_FILES)
|
||||||
|
.index(1)
|
||||||
|
.multiple(true)
|
||||||
|
.required(true)
|
||||||
|
.help("The directory or files to build documentation for")
|
||||||
|
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn docs(files: Vec<PathBuf>) {
|
||||||
|
roc_docs::generate(files, roc_builtins::std::standard_stdlib(), Path::new("./"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(target: &Triple, matches: &ArgMatches, run_after_build: bool) -> io::Result<()> {
|
pub fn build(target: &Triple, matches: &ArgMatches, run_after_build: bool) -> io::Result<()> {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use roc_cli::{build, build_app, repl, DIRECTORY_OR_FILES};
|
use roc_cli::{build, build_app, docs, repl, DIRECTORY_OR_FILES};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::Path;
|
use std::path::{Path, PathBuf};
|
||||||
use target_lexicon::Triple;
|
use target_lexicon::Triple;
|
||||||
|
|
||||||
fn main() -> io::Result<()> {
|
fn main() -> io::Result<()> {
|
||||||
|
@ -35,6 +35,21 @@ fn main() -> io::Result<()> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some("docs") => {
|
||||||
|
let values = matches
|
||||||
|
.subcommand_matches("docs")
|
||||||
|
.unwrap()
|
||||||
|
.values_of_os(DIRECTORY_OR_FILES)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let paths = values
|
||||||
|
.map(|os_str| Path::new(os_str).to_path_buf())
|
||||||
|
.collect::<Vec<PathBuf>>();
|
||||||
|
|
||||||
|
docs(paths);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,7 +148,7 @@ fn jit_to_ast_help<'a>(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let fields = [Layout::Builtin(Builtin::Int64), layout.clone()];
|
let fields = [Layout::Builtin(Builtin::Int64), *layout];
|
||||||
let layout = Layout::Struct(&fields);
|
let layout = Layout::Struct(&fields);
|
||||||
|
|
||||||
let result_stack_size = layout.stack_size(env.ptr_bytes);
|
let result_stack_size = layout.stack_size(env.ptr_bytes);
|
||||||
|
|
|
@ -153,7 +153,7 @@ pub fn gen_and_eval<'a>(
|
||||||
let expr_type_str = content_to_string(content.clone(), &subs, home, &interns);
|
let expr_type_str = content_to_string(content.clone(), &subs, home, &interns);
|
||||||
|
|
||||||
let (_, main_fn_layout) = match procedures.keys().find(|(s, _)| *s == main_fn_symbol) {
|
let (_, main_fn_layout) = match procedures.keys().find(|(s, _)| *s == main_fn_symbol) {
|
||||||
Some(layout) => layout.clone(),
|
Some(layout) => *layout,
|
||||||
None => {
|
None => {
|
||||||
return Ok(ReplOutput::NoProblems {
|
return Ok(ReplOutput::NoProblems {
|
||||||
expr: "<function>".to_string(),
|
expr: "<function>".to_string(),
|
||||||
|
|
|
@ -17,6 +17,6 @@ isEmpty : Dict * * -> Bool
|
||||||
## See for example #Result.map, #List.map, and #Set.map.
|
## See for example #Result.map, #List.map, and #Set.map.
|
||||||
map :
|
map :
|
||||||
Dict beforeKey beforeValue,
|
Dict beforeKey beforeValue,
|
||||||
(\{ key: beforeKey, value: beforeValue } ->
|
({ key: beforeKey, value: beforeValue } ->
|
||||||
{ key: afterKey, value: afterValue }
|
{ key: afterKey, value: afterValue }
|
||||||
) -> Dict afterKey afterValue
|
) -> Dict afterKey afterValue
|
||||||
|
|
|
@ -1,5 +1,54 @@
|
||||||
interface List2
|
interface List2
|
||||||
exposes [ List, single, empty, repeat, range, reverse, sort, map, mapWithIndex, mapOrCancel, mapOks, update, updater, allOks, append, prepend, concat, join, joinMap, oks, zip, zipMap, keepIf, dropIf, first, last, get, max, min, put, drop, append, prepend, dropLast, dropFirst, takeFirst, takeLast, split, sublist, walk, walkBackwards, walkUntil, walkBackwardsUntil, len, isEmpty, contains, all, any ]
|
exposes
|
||||||
|
[ List
|
||||||
|
, single
|
||||||
|
, empty
|
||||||
|
, repeat
|
||||||
|
, range
|
||||||
|
, reverse
|
||||||
|
, sort
|
||||||
|
, map
|
||||||
|
, mapWithIndex
|
||||||
|
, mapOrCancel
|
||||||
|
, mapOks
|
||||||
|
, update
|
||||||
|
, updater
|
||||||
|
, allOks
|
||||||
|
, append
|
||||||
|
, prepend
|
||||||
|
, concat
|
||||||
|
, join
|
||||||
|
, joinMap
|
||||||
|
, oks
|
||||||
|
, zip
|
||||||
|
, zipMap
|
||||||
|
, keepIf
|
||||||
|
, dropIf
|
||||||
|
, first
|
||||||
|
, last
|
||||||
|
, get
|
||||||
|
, max
|
||||||
|
, min
|
||||||
|
, put
|
||||||
|
, drop
|
||||||
|
, append
|
||||||
|
, prepend
|
||||||
|
, dropLast
|
||||||
|
, dropFirst
|
||||||
|
, takeFirst
|
||||||
|
, takeLast
|
||||||
|
, split
|
||||||
|
, sublist
|
||||||
|
, walk
|
||||||
|
, walkBackwards
|
||||||
|
, walkUntil
|
||||||
|
, walkBackwardsUntil
|
||||||
|
, len
|
||||||
|
, isEmpty
|
||||||
|
, contains
|
||||||
|
, all
|
||||||
|
, any
|
||||||
|
]
|
||||||
imports []
|
imports []
|
||||||
|
|
||||||
## Types
|
## Types
|
||||||
|
@ -298,7 +347,7 @@ oks : List (Result elem *) -> List elem
|
||||||
##
|
##
|
||||||
## > For a generalized version that returns whatever you like, instead of a `Pair`,
|
## > For a generalized version that returns whatever you like, instead of a `Pair`,
|
||||||
## > see `zipMap`.
|
## > see `zipMap`.
|
||||||
zip : List a, List b, -> List [ Pair a b ]*
|
zip : List a, List b -> List [ Pair a b ]*
|
||||||
|
|
||||||
## Like `zip` but you can specify what to do with each element.
|
## Like `zip` but you can specify what to do with each element.
|
||||||
##
|
##
|
||||||
|
@ -307,7 +356,7 @@ zip : List a, List b, -> List [ Pair a b ]*
|
||||||
## >>> List.zipMap [ 1, 2, 3 ] [ 0, 5, 4 ] [ 2, 1 ] \num1 num2 num3 -> num1 + num2 - num3
|
## >>> List.zipMap [ 1, 2, 3 ] [ 0, 5, 4 ] [ 2, 1 ] \num1 num2 num3 -> num1 + num2 - num3
|
||||||
##
|
##
|
||||||
## Accepts up to 8 lists.
|
## Accepts up to 8 lists.
|
||||||
zipMap : List a, List b, (a, b) -> List c
|
zipMap : List a, List b, (a, b -> c) -> List c
|
||||||
|
|
||||||
|
|
||||||
## Filter
|
## Filter
|
||||||
|
|
|
@ -2030,7 +2030,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
|
||||||
// access itself!
|
// access itself!
|
||||||
// scope = scope.clone();
|
// scope = scope.clone();
|
||||||
|
|
||||||
scope.insert(*symbol, (layout.clone(), val));
|
scope.insert(*symbol, (*layout, val));
|
||||||
stack.push(*symbol);
|
stack.push(*symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2063,8 +2063,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
|
||||||
} => {
|
} => {
|
||||||
// when the fail case is just Rethrow, there is no cleanup work to do
|
// when the fail case is just Rethrow, there is no cleanup work to do
|
||||||
// so we can just treat this invoke as a normal call
|
// so we can just treat this invoke as a normal call
|
||||||
let stmt =
|
let stmt = roc_mono::ir::Stmt::Let(*symbol, Expr::Call(call.clone()), *layout, pass);
|
||||||
roc_mono::ir::Stmt::Let(*symbol, Expr::Call(call.clone()), layout.clone(), pass);
|
|
||||||
build_exp_stmt(env, layout_ids, scope, parent, &stmt)
|
build_exp_stmt(env, layout_ids, scope, parent, &stmt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2088,7 +2087,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
|
||||||
scope,
|
scope,
|
||||||
parent,
|
parent,
|
||||||
*symbol,
|
*symbol,
|
||||||
layout.clone(),
|
*layout,
|
||||||
function_value.into(),
|
function_value.into(),
|
||||||
call.arguments,
|
call.arguments,
|
||||||
None,
|
None,
|
||||||
|
@ -2108,7 +2107,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
|
||||||
scope,
|
scope,
|
||||||
parent,
|
parent,
|
||||||
*symbol,
|
*symbol,
|
||||||
layout.clone(),
|
*layout,
|
||||||
function_ptr.into(),
|
function_ptr.into(),
|
||||||
call.arguments,
|
call.arguments,
|
||||||
None,
|
None,
|
||||||
|
@ -2135,7 +2134,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
|
||||||
scope,
|
scope,
|
||||||
parent,
|
parent,
|
||||||
*symbol,
|
*symbol,
|
||||||
layout.clone(),
|
*layout,
|
||||||
function_ptr.into(),
|
function_ptr.into(),
|
||||||
call.arguments,
|
call.arguments,
|
||||||
Some(closure_data),
|
Some(closure_data),
|
||||||
|
@ -2194,7 +2193,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
|
||||||
basic_type_from_layout(env.arena, env.context, &ret_layout, env.ptr_bytes);
|
basic_type_from_layout(env.arena, env.context, &ret_layout, env.ptr_bytes);
|
||||||
|
|
||||||
let switch_args = SwitchArgsIr {
|
let switch_args = SwitchArgsIr {
|
||||||
cond_layout: cond_layout.clone(),
|
cond_layout: *cond_layout,
|
||||||
cond_symbol: *cond_symbol,
|
cond_symbol: *cond_symbol,
|
||||||
branches,
|
branches,
|
||||||
default_branch: default_branch.1,
|
default_branch: default_branch.1,
|
||||||
|
@ -2242,7 +2241,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
for (ptr, param) in joinpoint_args.iter().zip(parameters.iter()) {
|
for (ptr, param) in joinpoint_args.iter().zip(parameters.iter()) {
|
||||||
let value = env.builder.build_load(*ptr, "load_jp_argument");
|
let value = env.builder.build_load(*ptr, "load_jp_argument");
|
||||||
scope.insert(param.symbol, (param.layout.clone(), value));
|
scope.insert(param.symbol, (param.layout, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
// put the continuation in
|
// put the continuation in
|
||||||
|
@ -2277,7 +2276,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
|
||||||
match modify {
|
match modify {
|
||||||
Inc(symbol, inc_amount) => {
|
Inc(symbol, inc_amount) => {
|
||||||
let (value, layout) = load_symbol_and_layout(scope, symbol);
|
let (value, layout) = load_symbol_and_layout(scope, symbol);
|
||||||
let layout = layout.clone();
|
let layout = *layout;
|
||||||
|
|
||||||
if layout.contains_refcounted() {
|
if layout.contains_refcounted() {
|
||||||
increment_refcount_layout(
|
increment_refcount_layout(
|
||||||
|
@ -3177,7 +3176,7 @@ pub fn build_closure_caller<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
let function_pointer_type = {
|
let function_pointer_type = {
|
||||||
let function_layout =
|
let function_layout =
|
||||||
ClosureLayout::extend_function_layout(arena, arguments, closure.clone(), result);
|
ClosureLayout::extend_function_layout(arena, arguments, *closure, result);
|
||||||
|
|
||||||
// this is already a (function) pointer type
|
// this is already a (function) pointer type
|
||||||
basic_type_from_layout(arena, context, &function_layout, env.ptr_bytes)
|
basic_type_from_layout(arena, context, &function_layout, env.ptr_bytes)
|
||||||
|
@ -3252,7 +3251,7 @@ pub fn build_closure_caller<'a, 'ctx, 'env>(
|
||||||
);
|
);
|
||||||
|
|
||||||
// STEP 4: build a {} -> u64 function that gives the size of the closure
|
// STEP 4: build a {} -> u64 function that gives the size of the closure
|
||||||
let layout = Layout::Closure(arguments, closure.clone(), result);
|
let layout = Layout::Closure(arguments, *closure, result);
|
||||||
build_host_exposed_alias_size(env, def_name, alias_symbol, &layout);
|
build_host_exposed_alias_size(env, def_name, alias_symbol, &layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3455,7 +3454,7 @@ pub fn build_proc<'a, 'ctx, 'env>(
|
||||||
// Add args to scope
|
// Add args to scope
|
||||||
for (arg_val, (layout, arg_symbol)) in fn_val.get_param_iter().zip(args) {
|
for (arg_val, (layout, arg_symbol)) in fn_val.get_param_iter().zip(args) {
|
||||||
set_name(arg_val, arg_symbol.ident_string(&env.interns));
|
set_name(arg_val, arg_symbol.ident_string(&env.interns));
|
||||||
scope.insert(*arg_symbol, (layout.clone(), arg_val));
|
scope.insert(*arg_symbol, (*layout, arg_val));
|
||||||
}
|
}
|
||||||
|
|
||||||
let body = build_exp_stmt(env, layout_ids, &mut scope, fn_val, &proc.body);
|
let body = build_exp_stmt(env, layout_ids, &mut scope, fn_val, &proc.body);
|
||||||
|
@ -4559,7 +4558,7 @@ fn build_foreign_symbol<'a, 'ctx, 'env>(
|
||||||
{
|
{
|
||||||
env.builder.position_at_end(pass_block);
|
env.builder.position_at_end(pass_block);
|
||||||
|
|
||||||
scope.insert(symbol, (ret_layout.clone(), call_result));
|
scope.insert(symbol, (*ret_layout, call_result));
|
||||||
|
|
||||||
build_exp_stmt(env, layout_ids, scope, parent, pass);
|
build_exp_stmt(env, layout_ids, scope, parent, pass);
|
||||||
|
|
||||||
|
|
|
@ -717,11 +717,7 @@ pub fn dict_walk<'a, 'ctx, 'env>(
|
||||||
env,
|
env,
|
||||||
layout_ids,
|
layout_ids,
|
||||||
stepper_layout,
|
stepper_layout,
|
||||||
&[
|
&[*key_layout, *value_layout, *accum_layout],
|
||||||
key_layout.clone(),
|
|
||||||
value_layout.clone(),
|
|
||||||
accum_layout.clone(),
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
.as_global_value()
|
.as_global_value()
|
||||||
.as_pointer_value();
|
.as_pointer_value();
|
||||||
|
|
|
@ -70,7 +70,7 @@ fn build_hash_layout<'a, 'ctx, 'env>(
|
||||||
unreachable!("recursion pointers should never be hashed directly")
|
unreachable!("recursion pointers should never be hashed directly")
|
||||||
}
|
}
|
||||||
WhenRecursive::Loop(union_layout) => {
|
WhenRecursive::Loop(union_layout) => {
|
||||||
let layout = Layout::Union(union_layout.clone());
|
let layout = Layout::Union(union_layout);
|
||||||
|
|
||||||
let bt = basic_type_from_layout(env.arena, env.context, &layout, env.ptr_bytes);
|
let bt = basic_type_from_layout(env.arena, env.context, &layout, env.ptr_bytes);
|
||||||
|
|
||||||
|
@ -287,7 +287,7 @@ fn hash_struct<'a, 'ctx, 'env>(
|
||||||
unreachable!("The current layout should not be recursive, but is")
|
unreachable!("The current layout should not be recursive, but is")
|
||||||
}
|
}
|
||||||
WhenRecursive::Loop(union_layout) => {
|
WhenRecursive::Loop(union_layout) => {
|
||||||
let field_layout = Layout::Union(union_layout.clone());
|
let field_layout = Layout::Union(*union_layout);
|
||||||
|
|
||||||
let bt = basic_type_from_layout(
|
let bt = basic_type_from_layout(
|
||||||
env.arena,
|
env.arena,
|
||||||
|
@ -811,7 +811,7 @@ fn hash_ptr_to_struct<'a, 'ctx, 'env>(
|
||||||
env,
|
env,
|
||||||
layout_ids,
|
layout_ids,
|
||||||
field_layouts,
|
field_layouts,
|
||||||
WhenRecursive::Loop(union_layout.clone()),
|
WhenRecursive::Loop(*union_layout),
|
||||||
seed,
|
seed,
|
||||||
struct_value,
|
struct_value,
|
||||||
)
|
)
|
||||||
|
|
|
@ -423,7 +423,7 @@ pub fn list_reverse<'a, 'ctx, 'env>(
|
||||||
let ctx = env.context;
|
let ctx = env.context;
|
||||||
|
|
||||||
let wrapper_struct = list.into_struct_value();
|
let wrapper_struct = list.into_struct_value();
|
||||||
let (input_inplace, element_layout) = match list_layout.clone() {
|
let (input_inplace, element_layout) = match *list_layout {
|
||||||
Layout::Builtin(Builtin::EmptyList) => (
|
Layout::Builtin(Builtin::EmptyList) => (
|
||||||
InPlace::InPlace,
|
InPlace::InPlace,
|
||||||
// this pointer will never actually be dereferenced
|
// this pointer will never actually be dereferenced
|
||||||
|
@ -434,7 +434,7 @@ pub fn list_reverse<'a, 'ctx, 'env>(
|
||||||
MemoryMode::Unique => InPlace::InPlace,
|
MemoryMode::Unique => InPlace::InPlace,
|
||||||
MemoryMode::Refcounted => InPlace::Clone,
|
MemoryMode::Refcounted => InPlace::Clone,
|
||||||
},
|
},
|
||||||
elem_layout.clone(),
|
*elem_layout,
|
||||||
),
|
),
|
||||||
|
|
||||||
_ => unreachable!("Invalid layout {:?} in List.reverse", list_layout),
|
_ => unreachable!("Invalid layout {:?} in List.reverse", list_layout),
|
||||||
|
@ -868,7 +868,7 @@ fn list_walk_generic<'a, 'ctx, 'env>(
|
||||||
env,
|
env,
|
||||||
layout_ids,
|
layout_ids,
|
||||||
func_layout,
|
func_layout,
|
||||||
&[element_layout.clone(), default_layout.clone()],
|
&[*element_layout, *default_layout],
|
||||||
)
|
)
|
||||||
.as_global_value()
|
.as_global_value()
|
||||||
.as_pointer_value();
|
.as_pointer_value();
|
||||||
|
@ -959,7 +959,7 @@ pub fn list_keep_if<'a, 'ctx, 'env>(
|
||||||
env.builder.build_store(transform_ptr, transform);
|
env.builder.build_store(transform_ptr, transform);
|
||||||
|
|
||||||
let stepper_caller =
|
let stepper_caller =
|
||||||
build_transform_caller(env, layout_ids, transform_layout, &[element_layout.clone()])
|
build_transform_caller(env, layout_ids, transform_layout, &[*element_layout])
|
||||||
.as_global_value()
|
.as_global_value()
|
||||||
.as_pointer_value();
|
.as_pointer_value();
|
||||||
|
|
||||||
|
@ -1066,7 +1066,7 @@ pub fn list_keep_result<'a, 'ctx, 'env>(
|
||||||
env.builder.build_store(transform_ptr, transform);
|
env.builder.build_store(transform_ptr, transform);
|
||||||
|
|
||||||
let stepper_caller =
|
let stepper_caller =
|
||||||
build_transform_caller(env, layout_ids, transform_layout, &[before_layout.clone()])
|
build_transform_caller(env, layout_ids, transform_layout, &[*before_layout])
|
||||||
.as_global_value()
|
.as_global_value()
|
||||||
.as_pointer_value();
|
.as_pointer_value();
|
||||||
|
|
||||||
|
@ -1130,7 +1130,7 @@ pub fn list_map<'a, 'ctx, 'env>(
|
||||||
list,
|
list,
|
||||||
element_layout,
|
element_layout,
|
||||||
bitcode::LIST_MAP,
|
bitcode::LIST_MAP,
|
||||||
&[element_layout.clone()],
|
&[*element_layout],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1151,7 +1151,7 @@ pub fn list_map_with_index<'a, 'ctx, 'env>(
|
||||||
list,
|
list,
|
||||||
element_layout,
|
element_layout,
|
||||||
bitcode::LIST_MAP_WITH_INDEX,
|
bitcode::LIST_MAP_WITH_INDEX,
|
||||||
&[Layout::Builtin(Builtin::Usize), element_layout.clone()],
|
&[Layout::Builtin(Builtin::Usize), *element_layout],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1255,7 +1255,7 @@ pub fn list_map2<'a, 'ctx, 'env>(
|
||||||
let transform_ptr = builder.build_alloca(transform.get_type(), "transform_ptr");
|
let transform_ptr = builder.build_alloca(transform.get_type(), "transform_ptr");
|
||||||
env.builder.build_store(transform_ptr, transform);
|
env.builder.build_store(transform_ptr, transform);
|
||||||
|
|
||||||
let argument_layouts = [element1_layout.clone(), element2_layout.clone()];
|
let argument_layouts = [*element1_layout, *element2_layout];
|
||||||
let stepper_caller =
|
let stepper_caller =
|
||||||
build_transform_caller(env, layout_ids, transform_layout, &argument_layouts)
|
build_transform_caller(env, layout_ids, transform_layout, &argument_layouts)
|
||||||
.as_global_value()
|
.as_global_value()
|
||||||
|
@ -1351,11 +1351,7 @@ pub fn list_map3<'a, 'ctx, 'env>(
|
||||||
let transform_ptr = builder.build_alloca(transform.get_type(), "transform_ptr");
|
let transform_ptr = builder.build_alloca(transform.get_type(), "transform_ptr");
|
||||||
env.builder.build_store(transform_ptr, transform);
|
env.builder.build_store(transform_ptr, transform);
|
||||||
|
|
||||||
let argument_layouts = [
|
let argument_layouts = [*element1_layout, *element2_layout, *element3_layout];
|
||||||
element1_layout.clone(),
|
|
||||||
element2_layout.clone(),
|
|
||||||
element3_layout.clone(),
|
|
||||||
];
|
|
||||||
let stepper_caller =
|
let stepper_caller =
|
||||||
build_transform_caller(env, layout_ids, transform_layout, &argument_layouts)
|
build_transform_caller(env, layout_ids, transform_layout, &argument_layouts)
|
||||||
.as_global_value()
|
.as_global_value()
|
||||||
|
|
|
@ -102,7 +102,7 @@ fn build_eq_builtin<'a, 'ctx, 'env>(
|
||||||
Builtin::List(_, elem) => build_list_eq(
|
Builtin::List(_, elem) => build_list_eq(
|
||||||
env,
|
env,
|
||||||
layout_ids,
|
layout_ids,
|
||||||
&Layout::Builtin(builtin.clone()),
|
&Layout::Builtin(*builtin),
|
||||||
elem,
|
elem,
|
||||||
lhs_val.into_struct_value(),
|
lhs_val.into_struct_value(),
|
||||||
rhs_val.into_struct_value(),
|
rhs_val.into_struct_value(),
|
||||||
|
@ -170,7 +170,7 @@ fn build_eq<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
|
|
||||||
WhenRecursive::Loop(union_layout) => {
|
WhenRecursive::Loop(union_layout) => {
|
||||||
let layout = Layout::Union(union_layout.clone());
|
let layout = Layout::Union(union_layout);
|
||||||
|
|
||||||
let bt = basic_type_from_layout(env.arena, env.context, &layout, env.ptr_bytes);
|
let bt = basic_type_from_layout(env.arena, env.context, &layout, env.ptr_bytes);
|
||||||
|
|
||||||
|
@ -188,7 +188,7 @@ fn build_eq<'a, 'ctx, 'env>(
|
||||||
build_tag_eq(
|
build_tag_eq(
|
||||||
env,
|
env,
|
||||||
layout_ids,
|
layout_ids,
|
||||||
WhenRecursive::Loop(union_layout.clone()),
|
WhenRecursive::Loop(union_layout),
|
||||||
&layout,
|
&layout,
|
||||||
&union_layout,
|
&union_layout,
|
||||||
field1_cast.into(),
|
field1_cast.into(),
|
||||||
|
@ -262,7 +262,7 @@ fn build_neq_builtin<'a, 'ctx, 'env>(
|
||||||
let is_equal = build_list_eq(
|
let is_equal = build_list_eq(
|
||||||
env,
|
env,
|
||||||
layout_ids,
|
layout_ids,
|
||||||
&Layout::Builtin(builtin.clone()),
|
&Layout::Builtin(*builtin),
|
||||||
elem,
|
elem,
|
||||||
lhs_val.into_struct_value(),
|
lhs_val.into_struct_value(),
|
||||||
rhs_val.into_struct_value(),
|
rhs_val.into_struct_value(),
|
||||||
|
@ -690,7 +690,7 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
|
||||||
unreachable!("The current layout should not be recursive, but is")
|
unreachable!("The current layout should not be recursive, but is")
|
||||||
}
|
}
|
||||||
WhenRecursive::Loop(union_layout) => {
|
WhenRecursive::Loop(union_layout) => {
|
||||||
let field_layout = Layout::Union(union_layout.clone());
|
let field_layout = Layout::Union(*union_layout);
|
||||||
|
|
||||||
let bt = basic_type_from_layout(
|
let bt = basic_type_from_layout(
|
||||||
env.arena,
|
env.arena,
|
||||||
|
@ -717,7 +717,7 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
|
||||||
field2_cast.into(),
|
field2_cast.into(),
|
||||||
&field_layout,
|
&field_layout,
|
||||||
&field_layout,
|
&field_layout,
|
||||||
WhenRecursive::Loop(union_layout.clone()),
|
WhenRecursive::Loop(*union_layout),
|
||||||
)
|
)
|
||||||
.into_int_value()
|
.into_int_value()
|
||||||
}
|
}
|
||||||
|
@ -1234,7 +1234,7 @@ fn eq_ptr_to_struct<'a, 'ctx, 'env>(
|
||||||
env,
|
env,
|
||||||
layout_ids,
|
layout_ids,
|
||||||
field_layouts,
|
field_layouts,
|
||||||
WhenRecursive::Loop(union_layout.clone()),
|
WhenRecursive::Loop(*union_layout),
|
||||||
struct1,
|
struct1,
|
||||||
struct2,
|
struct2,
|
||||||
)
|
)
|
||||||
|
|
|
@ -454,7 +454,7 @@ fn modify_refcount_layout_help<'a, 'ctx, 'env>(
|
||||||
env,
|
env,
|
||||||
layout_ids,
|
layout_ids,
|
||||||
mode,
|
mode,
|
||||||
&WhenRecursive::Loop(variant.clone()),
|
&WhenRecursive::Loop(*variant),
|
||||||
tags,
|
tags,
|
||||||
value.into_pointer_value(),
|
value.into_pointer_value(),
|
||||||
true,
|
true,
|
||||||
|
@ -470,7 +470,7 @@ fn modify_refcount_layout_help<'a, 'ctx, 'env>(
|
||||||
env,
|
env,
|
||||||
layout_ids,
|
layout_ids,
|
||||||
mode,
|
mode,
|
||||||
&WhenRecursive::Loop(variant.clone()),
|
&WhenRecursive::Loop(*variant),
|
||||||
&*env.arena.alloc([other_fields]),
|
&*env.arena.alloc([other_fields]),
|
||||||
value.into_pointer_value(),
|
value.into_pointer_value(),
|
||||||
true,
|
true,
|
||||||
|
@ -484,7 +484,7 @@ fn modify_refcount_layout_help<'a, 'ctx, 'env>(
|
||||||
env,
|
env,
|
||||||
layout_ids,
|
layout_ids,
|
||||||
mode,
|
mode,
|
||||||
&WhenRecursive::Loop(variant.clone()),
|
&WhenRecursive::Loop(*variant),
|
||||||
&*env.arena.alloc([*fields]),
|
&*env.arena.alloc([*fields]),
|
||||||
value.into_pointer_value(),
|
value.into_pointer_value(),
|
||||||
true,
|
true,
|
||||||
|
@ -497,7 +497,7 @@ fn modify_refcount_layout_help<'a, 'ctx, 'env>(
|
||||||
env,
|
env,
|
||||||
layout_ids,
|
layout_ids,
|
||||||
mode,
|
mode,
|
||||||
&WhenRecursive::Loop(variant.clone()),
|
&WhenRecursive::Loop(*variant),
|
||||||
tags,
|
tags,
|
||||||
value.into_pointer_value(),
|
value.into_pointer_value(),
|
||||||
false,
|
false,
|
||||||
|
@ -549,7 +549,7 @@ fn modify_refcount_layout_help<'a, 'ctx, 'env>(
|
||||||
unreachable!("recursion pointers should never be hashed directly")
|
unreachable!("recursion pointers should never be hashed directly")
|
||||||
}
|
}
|
||||||
WhenRecursive::Loop(union_layout) => {
|
WhenRecursive::Loop(union_layout) => {
|
||||||
let layout = Layout::Union(union_layout.clone());
|
let layout = Layout::Union(*union_layout);
|
||||||
|
|
||||||
let bt = basic_type_from_layout(env.arena, env.context, &layout, env.ptr_bytes);
|
let bt = basic_type_from_layout(env.arena, env.context, &layout, env.ptr_bytes);
|
||||||
|
|
||||||
|
|
|
@ -105,7 +105,7 @@ where
|
||||||
} => {
|
} => {
|
||||||
// for now, treat invoke as a normal call
|
// for now, treat invoke as a normal call
|
||||||
|
|
||||||
let stmt = Stmt::Let(*symbol, Expr::Call(call.clone()), layout.clone(), pass);
|
let stmt = Stmt::Let(*symbol, Expr::Call(call.clone()), *layout, pass);
|
||||||
self.build_stmt(&stmt)
|
self.build_stmt(&stmt)
|
||||||
}
|
}
|
||||||
Stmt::Switch {
|
Stmt::Switch {
|
||||||
|
@ -252,32 +252,20 @@ where
|
||||||
x => Err(format!("layout, {:?}, not implemented yet", x)),
|
x => Err(format!("layout, {:?}, not implemented yet", x)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LowLevel::NumAcos => self.build_fn_call(
|
LowLevel::NumAcos => {
|
||||||
sym,
|
self.build_fn_call(sym, bitcode::NUM_ACOS.to_string(), args, &[*layout], layout)
|
||||||
bitcode::NUM_ACOS.to_string(),
|
}
|
||||||
args,
|
LowLevel::NumAsin => {
|
||||||
&[layout.clone()],
|
self.build_fn_call(sym, bitcode::NUM_ASIN.to_string(), args, &[*layout], layout)
|
||||||
layout,
|
}
|
||||||
),
|
LowLevel::NumAtan => {
|
||||||
LowLevel::NumAsin => self.build_fn_call(
|
self.build_fn_call(sym, bitcode::NUM_ATAN.to_string(), args, &[*layout], layout)
|
||||||
sym,
|
}
|
||||||
bitcode::NUM_ASIN.to_string(),
|
|
||||||
args,
|
|
||||||
&[layout.clone()],
|
|
||||||
layout,
|
|
||||||
),
|
|
||||||
LowLevel::NumAtan => self.build_fn_call(
|
|
||||||
sym,
|
|
||||||
bitcode::NUM_ATAN.to_string(),
|
|
||||||
args,
|
|
||||||
&[layout.clone()],
|
|
||||||
layout,
|
|
||||||
),
|
|
||||||
LowLevel::NumPowInt => self.build_fn_call(
|
LowLevel::NumPowInt => self.build_fn_call(
|
||||||
sym,
|
sym,
|
||||||
bitcode::NUM_POW_INT.to_string(),
|
bitcode::NUM_POW_INT.to_string(),
|
||||||
args,
|
args,
|
||||||
&[layout.clone(), layout.clone()],
|
&[*layout, *layout],
|
||||||
layout,
|
layout,
|
||||||
),
|
),
|
||||||
LowLevel::NumSub => {
|
LowLevel::NumSub => {
|
||||||
|
@ -472,7 +460,7 @@ where
|
||||||
} => {
|
} => {
|
||||||
// for now, treat invoke as a normal call
|
// for now, treat invoke as a normal call
|
||||||
|
|
||||||
let stmt = Stmt::Let(*symbol, Expr::Call(call.clone()), layout.clone(), pass);
|
let stmt = Stmt::Let(*symbol, Expr::Call(call.clone()), *layout, pass);
|
||||||
self.scan_ast(&stmt);
|
self.scan_ast(&stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1944,7 +1944,7 @@ fn update<'a>(
|
||||||
};
|
};
|
||||||
|
|
||||||
for (layout, pend) in specs {
|
for (layout, pend) in specs {
|
||||||
existing.insert(layout.clone(), pend.clone());
|
existing.insert(*layout, pend.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ pub fn infer_borrow<'a>(
|
||||||
};
|
};
|
||||||
|
|
||||||
for (key, proc) in procs {
|
for (key, proc) in procs {
|
||||||
param_map.visit_proc(arena, proc, key.clone());
|
param_map.visit_proc(arena, proc, *key);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut env = BorrowInfState {
|
let mut env = BorrowInfState {
|
||||||
|
@ -47,7 +47,7 @@ pub fn infer_borrow<'a>(
|
||||||
// mutually recursive functions (or just make all their arguments owned)
|
// mutually recursive functions (or just make all their arguments owned)
|
||||||
|
|
||||||
for (key, proc) in procs {
|
for (key, proc) in procs {
|
||||||
env.collect_proc(proc, key.1.clone());
|
env.collect_proc(proc, key.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !env.modified {
|
if !env.modified {
|
||||||
|
@ -113,7 +113,7 @@ impl<'a> ParamMap<'a> {
|
||||||
Vec::from_iter_in(
|
Vec::from_iter_in(
|
||||||
ps.iter().map(|p| Param {
|
ps.iter().map(|p| Param {
|
||||||
borrow: p.layout.is_refcounted(),
|
borrow: p.layout.is_refcounted(),
|
||||||
layout: p.layout.clone(),
|
layout: p.layout,
|
||||||
symbol: p.symbol,
|
symbol: p.symbol,
|
||||||
}),
|
}),
|
||||||
arena,
|
arena,
|
||||||
|
@ -125,7 +125,7 @@ impl<'a> ParamMap<'a> {
|
||||||
Vec::from_iter_in(
|
Vec::from_iter_in(
|
||||||
ps.iter().map(|(layout, symbol)| Param {
|
ps.iter().map(|(layout, symbol)| Param {
|
||||||
borrow: should_borrow_layout(layout),
|
borrow: should_borrow_layout(layout),
|
||||||
layout: layout.clone(),
|
layout: *layout,
|
||||||
symbol: *symbol,
|
symbol: *symbol,
|
||||||
}),
|
}),
|
||||||
arena,
|
arena,
|
||||||
|
@ -140,7 +140,7 @@ impl<'a> ParamMap<'a> {
|
||||||
Vec::from_iter_in(
|
Vec::from_iter_in(
|
||||||
ps.iter().map(|(layout, symbol)| Param {
|
ps.iter().map(|(layout, symbol)| Param {
|
||||||
borrow: false,
|
borrow: false,
|
||||||
layout: layout.clone(),
|
layout: *layout,
|
||||||
symbol: *symbol,
|
symbol: *symbol,
|
||||||
}),
|
}),
|
||||||
arena,
|
arena,
|
||||||
|
@ -367,7 +367,7 @@ impl<'a> BorrowInfState<'a> {
|
||||||
name, full_layout, ..
|
name, full_layout, ..
|
||||||
} => {
|
} => {
|
||||||
// get the borrow signature of the applied function
|
// get the borrow signature of the applied function
|
||||||
match self.param_map.get_symbol(*name, full_layout.clone()) {
|
match self.param_map.get_symbol(*name, *full_layout) {
|
||||||
Some(ps) => {
|
Some(ps) => {
|
||||||
// the return value will be owned
|
// the return value will be owned
|
||||||
self.own_var(z);
|
self.own_var(z);
|
||||||
|
@ -499,7 +499,7 @@ impl<'a> BorrowInfState<'a> {
|
||||||
if self.current_proc == *g && x == *z {
|
if self.current_proc == *g && x == *z {
|
||||||
// anonymous functions (for which the ps may not be known)
|
// anonymous functions (for which the ps may not be known)
|
||||||
// can never be tail-recursive, so this is fine
|
// can never be tail-recursive, so this is fine
|
||||||
if let Some(ps) = self.param_map.get_symbol(*g, full_layout.clone()) {
|
if let Some(ps) = self.param_map.get_symbol(*g, *full_layout) {
|
||||||
self.own_params_using_args(ys, ps)
|
self.own_params_using_args(ys, ps)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -541,14 +541,14 @@ impl<'a> BorrowInfState<'a> {
|
||||||
|
|
||||||
Let(x, Expr::FunctionPointer(fsymbol, layout), _, b) => {
|
Let(x, Expr::FunctionPointer(fsymbol, layout), _, b) => {
|
||||||
// ensure that the function pointed to is in the param map
|
// ensure that the function pointed to is in the param map
|
||||||
if let Some(params) = self.param_map.get_symbol(*fsymbol, layout.clone()) {
|
if let Some(params) = self.param_map.get_symbol(*fsymbol, *layout) {
|
||||||
self.param_map
|
self.param_map
|
||||||
.items
|
.items
|
||||||
.insert(Key::Declaration(*x, layout.clone()), params);
|
.insert(Key::Declaration(*x, *layout), params);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.collect_stmt(b);
|
self.collect_stmt(b);
|
||||||
self.preserve_tail_call(*x, &Expr::FunctionPointer(*fsymbol, layout.clone()), b);
|
self.preserve_tail_call(*x, &Expr::FunctionPointer(*fsymbol, *layout), b);
|
||||||
}
|
}
|
||||||
|
|
||||||
Let(x, v, _, b) => {
|
Let(x, v, _, b) => {
|
||||||
|
|
|
@ -22,7 +22,7 @@ pub fn compile<'a>(raw_branches: Vec<(Guard<'a>, Pattern<'a>, u64)>) -> Decision
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(guard, pattern, index)| Branch {
|
.map(|(guard, pattern, index)| Branch {
|
||||||
goal: index,
|
goal: index,
|
||||||
patterns: vec![(Path::Empty, guard, pattern)],
|
patterns: vec![(Vec::new(), guard, pattern)],
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ impl<'a> Guard<'a> {
|
||||||
pub enum DecisionTree<'a> {
|
pub enum DecisionTree<'a> {
|
||||||
Match(Label),
|
Match(Label),
|
||||||
Decision {
|
Decision {
|
||||||
path: Path,
|
path: Vec<PathInstruction>,
|
||||||
edges: Vec<(Test<'a>, DecisionTree<'a>)>,
|
edges: Vec<(Test<'a>, DecisionTree<'a>)>,
|
||||||
default: Option<Box<DecisionTree<'a>>>,
|
default: Option<Box<DecisionTree<'a>>>,
|
||||||
},
|
},
|
||||||
|
@ -132,23 +132,12 @@ impl<'a> Hash for Test<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
|
||||||
pub enum Path {
|
|
||||||
Index {
|
|
||||||
index: u64,
|
|
||||||
tag_id: u8,
|
|
||||||
path: Box<Path>,
|
|
||||||
},
|
|
||||||
Unbox(Box<Path>),
|
|
||||||
Empty,
|
|
||||||
}
|
|
||||||
|
|
||||||
// ACTUALLY BUILD DECISION TREES
|
// ACTUALLY BUILD DECISION TREES
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
struct Branch<'a> {
|
struct Branch<'a> {
|
||||||
goal: Label,
|
goal: Label,
|
||||||
patterns: Vec<(Path, Guard<'a>, Pattern<'a>)>,
|
patterns: Vec<(Vec<PathInstruction>, Guard<'a>, Pattern<'a>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_decision_tree(raw_branches: Vec<Branch>) -> DecisionTree {
|
fn to_decision_tree(raw_branches: Vec<Branch>) -> DecisionTree {
|
||||||
|
@ -172,13 +161,13 @@ fn to_decision_tree(raw_branches: Vec<Branch>) -> DecisionTree {
|
||||||
decision_tree.clone()
|
decision_tree.clone()
|
||||||
}
|
}
|
||||||
(_, None) => DecisionTree::Decision {
|
(_, None) => DecisionTree::Decision {
|
||||||
path,
|
path: path.clone(),
|
||||||
edges: decision_edges,
|
edges: decision_edges,
|
||||||
default: None,
|
default: None,
|
||||||
},
|
},
|
||||||
(None, Some(_)) => to_decision_tree(fallback),
|
(None, Some(_)) => to_decision_tree(fallback),
|
||||||
_ => DecisionTree::Decision {
|
_ => DecisionTree::Decision {
|
||||||
path,
|
path: path.clone(),
|
||||||
edges: decision_edges,
|
edges: decision_edges,
|
||||||
default: Some(Box::new(to_decision_tree(fallback))),
|
default: Some(Box::new(to_decision_tree(fallback))),
|
||||||
},
|
},
|
||||||
|
@ -218,8 +207,8 @@ fn flatten_patterns(branch: Branch) -> Branch {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flatten<'a>(
|
fn flatten<'a>(
|
||||||
path_pattern: (Path, Guard<'a>, Pattern<'a>),
|
path_pattern: (Vec<PathInstruction>, Guard<'a>, Pattern<'a>),
|
||||||
path_patterns: &mut Vec<(Path, Guard<'a>, Pattern<'a>)>,
|
path_patterns: &mut Vec<(Vec<PathInstruction>, Guard<'a>, Pattern<'a>)>,
|
||||||
) {
|
) {
|
||||||
match path_pattern.2 {
|
match path_pattern.2 {
|
||||||
Pattern::AppliedTag {
|
Pattern::AppliedTag {
|
||||||
|
@ -241,8 +230,9 @@ fn flatten<'a>(
|
||||||
// Theory: unbox doesn't have any value for us, because one-element tag unions
|
// Theory: unbox doesn't have any value for us, because one-element tag unions
|
||||||
// don't store the tag anyway.
|
// don't store the tag anyway.
|
||||||
if arguments.len() == 1 {
|
if arguments.len() == 1 {
|
||||||
|
// NOTE here elm will unbox, but we don't use that
|
||||||
path_patterns.push((
|
path_patterns.push((
|
||||||
Path::Unbox(Box::new(path)),
|
path,
|
||||||
path_pattern.1.clone(),
|
path_pattern.1.clone(),
|
||||||
Pattern::AppliedTag {
|
Pattern::AppliedTag {
|
||||||
union,
|
union,
|
||||||
|
@ -254,13 +244,15 @@ fn flatten<'a>(
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
for (index, (arg_pattern, _)) in arguments.iter().enumerate() {
|
for (index, (arg_pattern, _)) in arguments.iter().enumerate() {
|
||||||
|
let mut new_path = path.clone();
|
||||||
|
new_path.push(PathInstruction {
|
||||||
|
index: index as u64,
|
||||||
|
tag_id,
|
||||||
|
});
|
||||||
|
|
||||||
flatten(
|
flatten(
|
||||||
(
|
(
|
||||||
Path::Index {
|
new_path,
|
||||||
index: index as u64,
|
|
||||||
tag_id,
|
|
||||||
path: Box::new(path.clone()),
|
|
||||||
},
|
|
||||||
// same guard here?
|
// same guard here?
|
||||||
path_pattern.1.clone(),
|
path_pattern.1.clone(),
|
||||||
arg_pattern.clone(),
|
arg_pattern.clone(),
|
||||||
|
@ -283,7 +275,7 @@ fn flatten<'a>(
|
||||||
/// path. If that is the case we give the resulting label and a mapping from free
|
/// path. If that is the case we give the resulting label and a mapping from free
|
||||||
/// variables to "how to get their value". So a pattern like (Just (x,_)) will give
|
/// variables to "how to get their value". So a pattern like (Just (x,_)) will give
|
||||||
/// us something like ("x" => value.0.0)
|
/// us something like ("x" => value.0.0)
|
||||||
fn check_for_match(branches: &Vec<Branch>) -> Option<Label> {
|
fn check_for_match(branches: &[Branch]) -> Option<Label> {
|
||||||
match branches.get(0) {
|
match branches.get(0) {
|
||||||
Some(Branch { goal, patterns })
|
Some(Branch { goal, patterns })
|
||||||
if patterns
|
if patterns
|
||||||
|
@ -300,7 +292,7 @@ fn check_for_match(branches: &Vec<Branch>) -> Option<Label> {
|
||||||
|
|
||||||
fn gather_edges<'a>(
|
fn gather_edges<'a>(
|
||||||
branches: Vec<Branch<'a>>,
|
branches: Vec<Branch<'a>>,
|
||||||
path: &Path,
|
path: &[PathInstruction],
|
||||||
) -> (Vec<(Test<'a>, Vec<Branch<'a>>)>, Vec<Branch<'a>>) {
|
) -> (Vec<(Test<'a>, Vec<Branch<'a>>)>, Vec<Branch<'a>>) {
|
||||||
let relevant_tests = tests_at_path(path, &branches);
|
let relevant_tests = tests_at_path(path, &branches);
|
||||||
|
|
||||||
|
@ -326,7 +318,7 @@ fn gather_edges<'a>(
|
||||||
|
|
||||||
/// FIND RELEVANT TESTS
|
/// FIND RELEVANT TESTS
|
||||||
|
|
||||||
fn tests_at_path<'a>(selected_path: &Path, branches: &[Branch<'a>]) -> Vec<Test<'a>> {
|
fn tests_at_path<'a>(selected_path: &[PathInstruction], branches: &[Branch<'a>]) -> Vec<Test<'a>> {
|
||||||
// NOTE the ordering of the result is important!
|
// NOTE the ordering of the result is important!
|
||||||
|
|
||||||
let mut all_tests = Vec::new();
|
let mut all_tests = Vec::new();
|
||||||
|
@ -360,7 +352,11 @@ fn tests_at_path<'a>(selected_path: &Path, branches: &[Branch<'a>]) -> Vec<Test<
|
||||||
unique
|
unique
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_at_path<'a>(selected_path: &Path, branch: &Branch<'a>, all_tests: &mut Vec<Test<'a>>) {
|
fn test_at_path<'a>(
|
||||||
|
selected_path: &[PathInstruction],
|
||||||
|
branch: &Branch<'a>,
|
||||||
|
all_tests: &mut Vec<Test<'a>>,
|
||||||
|
) {
|
||||||
use Pattern::*;
|
use Pattern::*;
|
||||||
use Test::*;
|
use Test::*;
|
||||||
|
|
||||||
|
@ -413,10 +409,10 @@ fn test_at_path<'a>(selected_path: &Path, branch: &Branch<'a>, all_tests: &mut V
|
||||||
for destruct in destructs {
|
for destruct in destructs {
|
||||||
match &destruct.typ {
|
match &destruct.typ {
|
||||||
DestructType::Guard(guard) => {
|
DestructType::Guard(guard) => {
|
||||||
arguments.push((guard.clone(), destruct.layout.clone()));
|
arguments.push((guard.clone(), destruct.layout));
|
||||||
}
|
}
|
||||||
DestructType::Required(_) => {
|
DestructType::Required(_) => {
|
||||||
arguments.push((Pattern::Underscore, destruct.layout.clone()));
|
arguments.push((Pattern::Underscore, destruct.layout));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -469,7 +465,7 @@ fn test_at_path<'a>(selected_path: &Path, branch: &Branch<'a>, all_tests: &mut V
|
||||||
/// BUILD EDGES
|
/// BUILD EDGES
|
||||||
|
|
||||||
fn edges_for<'a>(
|
fn edges_for<'a>(
|
||||||
path: &Path,
|
path: &[PathInstruction],
|
||||||
branches: Vec<Branch<'a>>,
|
branches: Vec<Branch<'a>>,
|
||||||
test: Test<'a>,
|
test: Test<'a>,
|
||||||
) -> (Test<'a>, Vec<Branch<'a>>) {
|
) -> (Test<'a>, Vec<Branch<'a>>) {
|
||||||
|
@ -484,7 +480,7 @@ fn edges_for<'a>(
|
||||||
|
|
||||||
fn to_relevant_branch<'a>(
|
fn to_relevant_branch<'a>(
|
||||||
test: &Test<'a>,
|
test: &Test<'a>,
|
||||||
path: &Path,
|
path: &[PathInstruction],
|
||||||
branch: &Branch<'a>,
|
branch: &Branch<'a>,
|
||||||
new_branches: &mut Vec<Branch<'a>>,
|
new_branches: &mut Vec<Branch<'a>>,
|
||||||
) {
|
) {
|
||||||
|
@ -524,9 +520,9 @@ fn to_relevant_branch<'a>(
|
||||||
|
|
||||||
fn to_relevant_branch_help<'a>(
|
fn to_relevant_branch_help<'a>(
|
||||||
test: &Test<'a>,
|
test: &Test<'a>,
|
||||||
path: &Path,
|
path: &[PathInstruction],
|
||||||
mut start: Vec<(Path, Guard<'a>, Pattern<'a>)>,
|
mut start: Vec<(Vec<PathInstruction>, Guard<'a>, Pattern<'a>)>,
|
||||||
end: Vec<(Path, Guard<'a>, Pattern<'a>)>,
|
end: Vec<(Vec<PathInstruction>, Guard<'a>, Pattern<'a>)>,
|
||||||
branch: &Branch<'a>,
|
branch: &Branch<'a>,
|
||||||
guard: Guard<'a>,
|
guard: Guard<'a>,
|
||||||
pattern: Pattern<'a>,
|
pattern: Pattern<'a>,
|
||||||
|
@ -550,15 +546,13 @@ fn to_relevant_branch_help<'a>(
|
||||||
DestructType::Required(_) => Pattern::Underscore,
|
DestructType::Required(_) => Pattern::Underscore,
|
||||||
};
|
};
|
||||||
|
|
||||||
(
|
let mut new_path = path.to_vec();
|
||||||
Path::Index {
|
new_path.push(PathInstruction {
|
||||||
index: index as u64,
|
index: index as u64,
|
||||||
tag_id: *tag_id,
|
tag_id: *tag_id,
|
||||||
path: Box::new(path.clone()),
|
});
|
||||||
},
|
|
||||||
Guard::NoGuard,
|
(new_path, Guard::NoGuard, pattern)
|
||||||
pattern,
|
|
||||||
)
|
|
||||||
});
|
});
|
||||||
start.extend(sub_positions);
|
start.extend(sub_positions);
|
||||||
start.extend(end);
|
start.extend(end);
|
||||||
|
@ -597,26 +591,21 @@ fn to_relevant_branch_help<'a>(
|
||||||
debug_assert_eq!(arguments.len(), 1);
|
debug_assert_eq!(arguments.len(), 1);
|
||||||
let arg = arguments[0].clone();
|
let arg = arguments[0].clone();
|
||||||
{
|
{
|
||||||
start.push((
|
// NOTE here elm unboxes, but we ignore that
|
||||||
Path::Unbox(Box::new(path.clone())),
|
// Path::Unbox(Box::new(path.clone()))
|
||||||
guard,
|
start.push((path.to_vec(), guard, arg.0));
|
||||||
arg.0,
|
|
||||||
));
|
|
||||||
start.extend(end);
|
start.extend(end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Wrapped::RecordOrSingleTagUnion => {
|
Wrapped::RecordOrSingleTagUnion => {
|
||||||
let sub_positions = arguments.into_iter().enumerate().map(
|
let sub_positions = arguments.into_iter().enumerate().map(
|
||||||
|(index, (pattern, _))| {
|
|(index, (pattern, _))| {
|
||||||
(
|
let mut new_path = path.to_vec();
|
||||||
Path::Index {
|
new_path.push(PathInstruction {
|
||||||
index: index as u64,
|
index: index as u64,
|
||||||
tag_id,
|
tag_id,
|
||||||
path: Box::new(path.clone()),
|
});
|
||||||
},
|
(new_path, Guard::NoGuard, pattern)
|
||||||
Guard::NoGuard,
|
|
||||||
pattern,
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
start.extend(sub_positions);
|
start.extend(sub_positions);
|
||||||
|
@ -625,15 +614,12 @@ fn to_relevant_branch_help<'a>(
|
||||||
Wrapped::MultiTagUnion => {
|
Wrapped::MultiTagUnion => {
|
||||||
let sub_positions = arguments.into_iter().enumerate().map(
|
let sub_positions = arguments.into_iter().enumerate().map(
|
||||||
|(index, (pattern, _))| {
|
|(index, (pattern, _))| {
|
||||||
(
|
let mut new_path = path.to_vec();
|
||||||
Path::Index {
|
new_path.push(PathInstruction {
|
||||||
index: 1 + index as u64,
|
index: 1 + index as u64,
|
||||||
tag_id,
|
tag_id,
|
||||||
path: Box::new(path.clone()),
|
});
|
||||||
},
|
(new_path, Guard::NoGuard, pattern)
|
||||||
Guard::NoGuard,
|
|
||||||
pattern,
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
start.extend(sub_positions);
|
start.extend(sub_positions);
|
||||||
|
@ -715,22 +701,22 @@ fn to_relevant_branch_help<'a>(
|
||||||
enum Extract<'a> {
|
enum Extract<'a> {
|
||||||
NotFound,
|
NotFound,
|
||||||
Found {
|
Found {
|
||||||
start: Vec<(Path, Guard<'a>, Pattern<'a>)>,
|
start: Vec<(Vec<PathInstruction>, Guard<'a>, Pattern<'a>)>,
|
||||||
found_pattern: (Guard<'a>, Pattern<'a>),
|
found_pattern: (Guard<'a>, Pattern<'a>),
|
||||||
end: Vec<(Path, Guard<'a>, Pattern<'a>)>,
|
end: Vec<(Vec<PathInstruction>, Guard<'a>, Pattern<'a>)>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract<'a>(
|
fn extract<'a>(
|
||||||
selected_path: &Path,
|
selected_path: &[PathInstruction],
|
||||||
path_patterns: Vec<(Path, Guard<'a>, Pattern<'a>)>,
|
path_patterns: Vec<(Vec<PathInstruction>, Guard<'a>, Pattern<'a>)>,
|
||||||
) -> Extract<'a> {
|
) -> Extract<'a> {
|
||||||
let mut start = Vec::new();
|
let mut start = Vec::new();
|
||||||
|
|
||||||
// TODO potential ordering problem
|
// TODO potential ordering problem
|
||||||
let mut it = path_patterns.into_iter();
|
let mut it = path_patterns.into_iter();
|
||||||
while let Some(current) = it.next() {
|
while let Some(current) = it.next() {
|
||||||
if ¤t.0 == selected_path {
|
if current.0 == selected_path {
|
||||||
return Extract::Found {
|
return Extract::Found {
|
||||||
start,
|
start,
|
||||||
found_pattern: (current.1, current.2),
|
found_pattern: (current.1, current.2),
|
||||||
|
@ -746,7 +732,7 @@ fn extract<'a>(
|
||||||
|
|
||||||
/// FIND IRRELEVANT BRANCHES
|
/// FIND IRRELEVANT BRANCHES
|
||||||
|
|
||||||
fn is_irrelevant_to<'a>(selected_path: &Path, branch: &Branch<'a>) -> bool {
|
fn is_irrelevant_to<'a>(selected_path: &[PathInstruction], branch: &Branch<'a>) -> bool {
|
||||||
match branch
|
match branch
|
||||||
.patterns
|
.patterns
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -775,7 +761,7 @@ fn needs_tests(pattern: &Pattern) -> bool {
|
||||||
|
|
||||||
/// PICK A PATH
|
/// PICK A PATH
|
||||||
|
|
||||||
fn pick_path<'a>(branches: &'a [Branch]) -> &'a Path {
|
fn pick_path<'a>(branches: &'a [Branch]) -> &'a Vec<PathInstruction> {
|
||||||
let mut all_paths = Vec::with_capacity(branches.len());
|
let mut all_paths = Vec::with_capacity(branches.len());
|
||||||
|
|
||||||
// is choice path
|
// is choice path
|
||||||
|
@ -804,9 +790,12 @@ fn pick_path<'a>(branches: &'a [Branch]) -> &'a Path {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bests_by_small_branching_factor<'a, I>(branches: &[Branch], mut all_paths: I) -> Vec<&'a Path>
|
fn bests_by_small_branching_factor<'a, I>(
|
||||||
|
branches: &[Branch],
|
||||||
|
mut all_paths: I,
|
||||||
|
) -> Vec<&'a Vec<PathInstruction>>
|
||||||
where
|
where
|
||||||
I: Iterator<Item = &'a Path>,
|
I: Iterator<Item = &'a Vec<PathInstruction>>,
|
||||||
{
|
{
|
||||||
match all_paths.next() {
|
match all_paths.next() {
|
||||||
None => panic!("Cannot choose the best of zero paths. This should never happen."),
|
None => panic!("Cannot choose the best of zero paths. This should never happen."),
|
||||||
|
@ -836,9 +825,12 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bests_by_small_defaults<'a, I>(branches: &[Branch], mut all_paths: I) -> Vec<&'a Path>
|
fn bests_by_small_defaults<'a, I>(
|
||||||
|
branches: &[Branch],
|
||||||
|
mut all_paths: I,
|
||||||
|
) -> Vec<&'a Vec<PathInstruction>>
|
||||||
where
|
where
|
||||||
I: Iterator<Item = &'a Path>,
|
I: Iterator<Item = &'a Vec<PathInstruction>>,
|
||||||
{
|
{
|
||||||
match all_paths.next() {
|
match all_paths.next() {
|
||||||
None => panic!("Cannot choose the best of zero paths. This should never happen."),
|
None => panic!("Cannot choose the best of zero paths. This should never happen."),
|
||||||
|
@ -870,7 +862,7 @@ where
|
||||||
|
|
||||||
/// PATH PICKING HEURISTICS
|
/// PATH PICKING HEURISTICS
|
||||||
|
|
||||||
fn small_defaults(branches: &[Branch], path: &Path) -> usize {
|
fn small_defaults(branches: &[Branch], path: &[PathInstruction]) -> usize {
|
||||||
branches
|
branches
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|b| is_irrelevant_to(path, b))
|
.filter(|b| is_irrelevant_to(path, b))
|
||||||
|
@ -878,8 +870,7 @@ fn small_defaults(branches: &[Branch], path: &Path) -> usize {
|
||||||
.sum()
|
.sum()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn small_branching_factor(branches: &[Branch], path: &Path) -> usize {
|
fn small_branching_factor(branches: &[Branch], path: &[PathInstruction]) -> usize {
|
||||||
// TODO remove clone
|
|
||||||
let (edges, fallback) = gather_edges(branches.to_vec(), path);
|
let (edges, fallback) = gather_edges(branches.to_vec(), path);
|
||||||
|
|
||||||
edges.len() + (if fallback.is_empty() { 0 } else { 1 })
|
edges.len() + (if fallback.is_empty() { 0 } else { 1 })
|
||||||
|
@ -889,12 +880,12 @@ fn small_branching_factor(branches: &[Branch], path: &Path) -> usize {
|
||||||
enum Decider<'a, T> {
|
enum Decider<'a, T> {
|
||||||
Leaf(T),
|
Leaf(T),
|
||||||
Chain {
|
Chain {
|
||||||
test_chain: Vec<(Path, Test<'a>)>,
|
test_chain: Vec<(Vec<PathInstruction>, Test<'a>)>,
|
||||||
success: Box<Decider<'a, T>>,
|
success: Box<Decider<'a, T>>,
|
||||||
failure: Box<Decider<'a, T>>,
|
failure: Box<Decider<'a, T>>,
|
||||||
},
|
},
|
||||||
FanOut {
|
FanOut {
|
||||||
path: Path,
|
path: Vec<PathInstruction>,
|
||||||
tests: Vec<(Test<'a>, Decider<'a, T>)>,
|
tests: Vec<(Test<'a>, Decider<'a, T>)>,
|
||||||
fallback: Box<Decider<'a, T>>,
|
fallback: Box<Decider<'a, T>>,
|
||||||
},
|
},
|
||||||
|
@ -973,49 +964,22 @@ pub fn optimize_when<'a>(
|
||||||
stmt
|
stmt
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
struct PathInstruction {
|
pub struct PathInstruction {
|
||||||
index: u64,
|
index: u64,
|
||||||
tag_id: u8,
|
tag_id: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reverse_path(mut path: &Path) -> Vec<PathInstruction> {
|
|
||||||
let mut result = Vec::new();
|
|
||||||
|
|
||||||
loop {
|
|
||||||
match path {
|
|
||||||
Path::Unbox(nested) => {
|
|
||||||
path = nested;
|
|
||||||
}
|
|
||||||
Path::Empty => break,
|
|
||||||
Path::Index {
|
|
||||||
index,
|
|
||||||
tag_id,
|
|
||||||
path: nested,
|
|
||||||
} => {
|
|
||||||
result.push(PathInstruction {
|
|
||||||
index: *index,
|
|
||||||
tag_id: *tag_id,
|
|
||||||
});
|
|
||||||
path = nested;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result.reverse();
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
fn path_to_expr_help<'a>(
|
fn path_to_expr_help<'a>(
|
||||||
env: &mut Env<'a, '_>,
|
env: &mut Env<'a, '_>,
|
||||||
mut symbol: Symbol,
|
mut symbol: Symbol,
|
||||||
path: &Path,
|
path: &[PathInstruction],
|
||||||
mut layout: Layout<'a>,
|
mut layout: Layout<'a>,
|
||||||
) -> (Symbol, StoresVec<'a>, Layout<'a>) {
|
) -> (Symbol, StoresVec<'a>, Layout<'a>) {
|
||||||
let mut stores = bumpalo::collections::Vec::new_in(env.arena);
|
let mut stores = bumpalo::collections::Vec::new_in(env.arena);
|
||||||
|
|
||||||
let instructions = reverse_path(path);
|
// let instructions = reverse_path(path);
|
||||||
|
let instructions = path;
|
||||||
let mut it = instructions.iter().peekable();
|
let mut it = instructions.iter().peekable();
|
||||||
|
|
||||||
while let Some(PathInstruction { index, tag_id }) = it.next() {
|
while let Some(PathInstruction { index, tag_id }) = it.next() {
|
||||||
|
@ -1027,13 +991,12 @@ fn path_to_expr_help<'a>(
|
||||||
debug_assert_eq!(*tag_id, 0);
|
debug_assert_eq!(*tag_id, 0);
|
||||||
debug_assert!(it.peek().is_none());
|
debug_assert!(it.peek().is_none());
|
||||||
|
|
||||||
let field_layouts = vec![layout.clone()];
|
let field_layouts = vec![layout];
|
||||||
|
|
||||||
debug_assert!(*index < field_layouts.len() as u64);
|
debug_assert!(*index < field_layouts.len() as u64);
|
||||||
|
|
||||||
debug_assert_eq!(field_layouts.len(), 1);
|
debug_assert_eq!(field_layouts.len(), 1);
|
||||||
|
|
||||||
let inner_layout = field_layouts[*index as usize].clone();
|
|
||||||
let inner_expr = Expr::AccessAtIndex {
|
let inner_expr = Expr::AccessAtIndex {
|
||||||
index: *index,
|
index: *index,
|
||||||
field_layouts: env.arena.alloc(field_layouts),
|
field_layouts: env.arena.alloc(field_layouts),
|
||||||
|
@ -1042,7 +1005,8 @@ fn path_to_expr_help<'a>(
|
||||||
};
|
};
|
||||||
|
|
||||||
symbol = env.unique_symbol();
|
symbol = env.unique_symbol();
|
||||||
stores.push((symbol, inner_layout.clone(), inner_expr));
|
let inner_layout = layout;
|
||||||
|
stores.push((symbol, inner_layout, inner_expr));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1096,7 +1060,7 @@ fn path_to_expr_help<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
Layout::Struct(layouts) => layouts,
|
Layout::Struct(layouts) => layouts,
|
||||||
other => env.arena.alloc([other.clone()]),
|
other => env.arena.alloc([*other]),
|
||||||
};
|
};
|
||||||
|
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
|
@ -1109,8 +1073,8 @@ fn path_to_expr_help<'a>(
|
||||||
);
|
);
|
||||||
|
|
||||||
let inner_layout = match &field_layouts[index as usize] {
|
let inner_layout = match &field_layouts[index as usize] {
|
||||||
Layout::RecursivePointer => layout.clone(),
|
Layout::RecursivePointer => layout,
|
||||||
other => other.clone(),
|
other => *other,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inner_expr = Expr::AccessAtIndex {
|
let inner_expr = Expr::AccessAtIndex {
|
||||||
|
@ -1121,7 +1085,7 @@ fn path_to_expr_help<'a>(
|
||||||
};
|
};
|
||||||
|
|
||||||
symbol = env.unique_symbol();
|
symbol = env.unique_symbol();
|
||||||
stores.push((symbol, inner_layout.clone(), inner_expr));
|
stores.push((symbol, inner_layout, inner_expr));
|
||||||
|
|
||||||
layout = inner_layout;
|
layout = inner_layout;
|
||||||
}
|
}
|
||||||
|
@ -1135,11 +1099,11 @@ fn test_to_equality<'a>(
|
||||||
env: &mut Env<'a, '_>,
|
env: &mut Env<'a, '_>,
|
||||||
cond_symbol: Symbol,
|
cond_symbol: Symbol,
|
||||||
cond_layout: &Layout<'a>,
|
cond_layout: &Layout<'a>,
|
||||||
path: &Path,
|
path: &[PathInstruction],
|
||||||
test: Test<'a>,
|
test: Test<'a>,
|
||||||
) -> (StoresVec<'a>, Symbol, Symbol, Layout<'a>) {
|
) -> (StoresVec<'a>, Symbol, Symbol, Layout<'a>) {
|
||||||
let (rhs_symbol, mut stores, _layout) =
|
let (rhs_symbol, mut stores, _layout) =
|
||||||
path_to_expr_help(env, cond_symbol, &path, cond_layout.clone());
|
path_to_expr_help(env, cond_symbol, &path, *cond_layout);
|
||||||
|
|
||||||
match test {
|
match test {
|
||||||
Test::IsCtor {
|
Test::IsCtor {
|
||||||
|
@ -1273,7 +1237,7 @@ fn stores_and_condition<'a>(
|
||||||
env: &mut Env<'a, '_>,
|
env: &mut Env<'a, '_>,
|
||||||
cond_symbol: Symbol,
|
cond_symbol: Symbol,
|
||||||
cond_layout: &Layout<'a>,
|
cond_layout: &Layout<'a>,
|
||||||
test_chain: Vec<(Path, Test<'a>)>,
|
test_chain: Vec<(Vec<PathInstruction>, Test<'a>)>,
|
||||||
) -> (Tests<'a>, Option<(Symbol, JoinPointId, Stmt<'a>)>) {
|
) -> (Tests<'a>, Option<(Symbol, JoinPointId, Stmt<'a>)>) {
|
||||||
let mut tests = Vec::with_capacity(test_chain.len());
|
let mut tests = Vec::with_capacity(test_chain.len());
|
||||||
|
|
||||||
|
@ -1399,12 +1363,12 @@ fn compile_test_help<'a>(
|
||||||
} => {
|
} => {
|
||||||
let pass_info = BranchInfo::Constructor {
|
let pass_info = BranchInfo::Constructor {
|
||||||
scrutinee,
|
scrutinee,
|
||||||
layout: layout.clone(),
|
layout,
|
||||||
tag_id: pass,
|
tag_id: pass,
|
||||||
};
|
};
|
||||||
let fail_info = BranchInfo::Constructor {
|
let fail_info = BranchInfo::Constructor {
|
||||||
scrutinee,
|
scrutinee,
|
||||||
layout: layout.clone(),
|
layout,
|
||||||
tag_id: fail,
|
tag_id: fail,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1418,7 +1382,7 @@ fn compile_test_help<'a>(
|
||||||
} => {
|
} => {
|
||||||
let pass_info = BranchInfo::Constructor {
|
let pass_info = BranchInfo::Constructor {
|
||||||
scrutinee,
|
scrutinee,
|
||||||
layout: layout.clone(),
|
layout,
|
||||||
tag_id,
|
tag_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1473,11 +1437,11 @@ fn compile_tests<'a>(
|
||||||
|
|
||||||
// the guard is the final thing that we check, so needs to be layered on first!
|
// the guard is the final thing that we check, so needs to be layered on first!
|
||||||
if let Some((_, id, stmt)) = opt_guard {
|
if let Some((_, id, stmt)) = opt_guard {
|
||||||
cond = compile_guard(env, ret_layout.clone(), id, arena.alloc(stmt), fail, cond);
|
cond = compile_guard(env, ret_layout, id, arena.alloc(stmt), fail, cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (new_stores, lhs, rhs, _layout) in tests.into_iter() {
|
for (new_stores, lhs, rhs, _layout) in tests.into_iter() {
|
||||||
cond = compile_test(env, ret_layout.clone(), new_stores, lhs, rhs, fail, cond);
|
cond = compile_test(env, ret_layout, new_stores, lhs, rhs, fail, cond);
|
||||||
}
|
}
|
||||||
cond
|
cond
|
||||||
}
|
}
|
||||||
|
@ -1501,22 +1465,22 @@ impl<'a> ConstructorKnown<'a> {
|
||||||
fn from_test_chain(
|
fn from_test_chain(
|
||||||
cond_symbol: Symbol,
|
cond_symbol: Symbol,
|
||||||
cond_layout: &Layout<'a>,
|
cond_layout: &Layout<'a>,
|
||||||
test_chain: &[(Path, Test)],
|
test_chain: &[(Vec<PathInstruction>, Test)],
|
||||||
) -> Self {
|
) -> Self {
|
||||||
match test_chain {
|
match test_chain {
|
||||||
[(path, test)] => match (path, test) {
|
[(path, test)] => match test {
|
||||||
(Path::Empty, Test::IsCtor { tag_id, union, .. }) => {
|
Test::IsCtor { tag_id, union, .. } if path.is_empty() => {
|
||||||
if union.alternatives.len() == 2 {
|
if union.alternatives.len() == 2 {
|
||||||
// excluded middle: we also know the tag_id in the fail branch
|
// excluded middle: we also know the tag_id in the fail branch
|
||||||
ConstructorKnown::Both {
|
ConstructorKnown::Both {
|
||||||
layout: cond_layout.clone(),
|
layout: *cond_layout,
|
||||||
scrutinee: cond_symbol,
|
scrutinee: cond_symbol,
|
||||||
pass: *tag_id,
|
pass: *tag_id,
|
||||||
fail: (*tag_id == 0) as u8,
|
fail: (*tag_id == 0) as u8,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ConstructorKnown::OnlyPass {
|
ConstructorKnown::OnlyPass {
|
||||||
layout: cond_layout.clone(),
|
layout: *cond_layout,
|
||||||
scrutinee: cond_symbol,
|
scrutinee: cond_symbol,
|
||||||
tag_id: *tag_id,
|
tag_id: *tag_id,
|
||||||
}
|
}
|
||||||
|
@ -1541,7 +1505,7 @@ fn decide_to_branching<'a>(
|
||||||
cond_layout: Layout<'a>,
|
cond_layout: Layout<'a>,
|
||||||
ret_layout: Layout<'a>,
|
ret_layout: Layout<'a>,
|
||||||
decider: Decider<'a, Choice<'a>>,
|
decider: Decider<'a, Choice<'a>>,
|
||||||
jumps: &Vec<(u64, JoinPointId, Stmt<'a>)>,
|
jumps: &[(u64, JoinPointId, Stmt<'a>)],
|
||||||
) -> Stmt<'a> {
|
) -> Stmt<'a> {
|
||||||
use Choice::*;
|
use Choice::*;
|
||||||
use Decider::*;
|
use Decider::*;
|
||||||
|
@ -1569,8 +1533,8 @@ fn decide_to_branching<'a>(
|
||||||
procs,
|
procs,
|
||||||
layout_cache,
|
layout_cache,
|
||||||
cond_symbol,
|
cond_symbol,
|
||||||
cond_layout.clone(),
|
cond_layout,
|
||||||
ret_layout.clone(),
|
ret_layout,
|
||||||
*success,
|
*success,
|
||||||
jumps,
|
jumps,
|
||||||
);
|
);
|
||||||
|
@ -1580,8 +1544,8 @@ fn decide_to_branching<'a>(
|
||||||
procs,
|
procs,
|
||||||
layout_cache,
|
layout_cache,
|
||||||
cond_symbol,
|
cond_symbol,
|
||||||
cond_layout.clone(),
|
cond_layout,
|
||||||
ret_layout.clone(),
|
ret_layout,
|
||||||
*failure,
|
*failure,
|
||||||
jumps,
|
jumps,
|
||||||
);
|
);
|
||||||
|
@ -1608,7 +1572,7 @@ fn decide_to_branching<'a>(
|
||||||
compile_test_help(
|
compile_test_help(
|
||||||
env,
|
env,
|
||||||
chain_branch_info,
|
chain_branch_info,
|
||||||
ret_layout.clone(),
|
ret_layout,
|
||||||
new_stores,
|
new_stores,
|
||||||
lhs,
|
lhs,
|
||||||
rhs,
|
rhs,
|
||||||
|
@ -1643,15 +1607,15 @@ fn decide_to_branching<'a>(
|
||||||
// switch on the tag discriminant (currently an i64 value)
|
// switch on the tag discriminant (currently an i64 value)
|
||||||
// NOTE the tag discriminant is not actually loaded, `cond` can point to a tag
|
// NOTE the tag discriminant is not actually loaded, `cond` can point to a tag
|
||||||
let (inner_cond_symbol, cond_stores_vec, inner_cond_layout) =
|
let (inner_cond_symbol, cond_stores_vec, inner_cond_layout) =
|
||||||
path_to_expr_help(env, cond_symbol, &path, cond_layout.clone());
|
path_to_expr_help(env, cond_symbol, &path, cond_layout);
|
||||||
|
|
||||||
let default_branch = decide_to_branching(
|
let default_branch = decide_to_branching(
|
||||||
env,
|
env,
|
||||||
procs,
|
procs,
|
||||||
layout_cache,
|
layout_cache,
|
||||||
cond_symbol,
|
cond_symbol,
|
||||||
cond_layout.clone(),
|
cond_layout,
|
||||||
ret_layout.clone(),
|
ret_layout,
|
||||||
*fallback,
|
*fallback,
|
||||||
jumps,
|
jumps,
|
||||||
);
|
);
|
||||||
|
@ -1667,8 +1631,8 @@ fn decide_to_branching<'a>(
|
||||||
procs,
|
procs,
|
||||||
layout_cache,
|
layout_cache,
|
||||||
cond_symbol,
|
cond_symbol,
|
||||||
cond_layout.clone(),
|
cond_layout,
|
||||||
ret_layout.clone(),
|
ret_layout,
|
||||||
decider,
|
decider,
|
||||||
jumps,
|
jumps,
|
||||||
);
|
);
|
||||||
|
@ -1689,7 +1653,7 @@ fn decide_to_branching<'a>(
|
||||||
|
|
||||||
BranchInfo::Constructor {
|
BranchInfo::Constructor {
|
||||||
scrutinee: inner_cond_symbol,
|
scrutinee: inner_cond_symbol,
|
||||||
layout: inner_cond_layout.clone(),
|
layout: inner_cond_layout,
|
||||||
tag_id,
|
tag_id,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1704,7 +1668,7 @@ fn decide_to_branching<'a>(
|
||||||
let default_branch_info = if tag_id_sum > 0 && union_size > 0 {
|
let default_branch_info = if tag_id_sum > 0 && union_size > 0 {
|
||||||
BranchInfo::Constructor {
|
BranchInfo::Constructor {
|
||||||
scrutinee: inner_cond_symbol,
|
scrutinee: inner_cond_symbol,
|
||||||
layout: inner_cond_layout.clone(),
|
layout: inner_cond_layout,
|
||||||
tag_id: tag_id_sum as u8,
|
tag_id: tag_id_sum as u8,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1847,7 +1811,7 @@ fn tree_to_decider(tree: DecisionTree) -> Decider<u64> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_chain<'a>(
|
fn to_chain<'a>(
|
||||||
path: Path,
|
path: Vec<PathInstruction>,
|
||||||
test: Test<'a>,
|
test: Test<'a>,
|
||||||
success_tree: DecisionTree<'a>,
|
success_tree: DecisionTree<'a>,
|
||||||
failure_tree: DecisionTree<'a>,
|
failure_tree: DecisionTree<'a>,
|
||||||
|
|
|
@ -141,7 +141,7 @@ impl<'a, 'i> Env<'a, 'i> {
|
||||||
tag_id,
|
tag_id,
|
||||||
} => {
|
} => {
|
||||||
self.constructor_map.insert(*scrutinee, *tag_id as u64);
|
self.constructor_map.insert(*scrutinee, *tag_id as u64);
|
||||||
self.layout_map.insert(*scrutinee, layout.clone());
|
self.layout_map.insert(*scrutinee, *layout);
|
||||||
}
|
}
|
||||||
BranchInfo::None => (),
|
BranchInfo::None => (),
|
||||||
}
|
}
|
||||||
|
@ -167,7 +167,7 @@ impl<'a, 'i> Env<'a, 'i> {
|
||||||
}
|
}
|
||||||
Closure(arguments, closure_layout, result) => {
|
Closure(arguments, closure_layout, result) => {
|
||||||
let fpointer = Layout::FunctionPointer(arguments, result);
|
let fpointer = Layout::FunctionPointer(arguments, result);
|
||||||
let fields = self.arena.alloc([fpointer, closure_layout.layout.clone()]);
|
let fields = self.arena.alloc([fpointer, *closure_layout.layout]);
|
||||||
self.constructor_map.insert(symbol, 0);
|
self.constructor_map.insert(symbol, 0);
|
||||||
self.layout_map.insert(symbol, Layout::Struct(fields));
|
self.layout_map.insert(symbol, Layout::Struct(fields));
|
||||||
}
|
}
|
||||||
|
@ -247,7 +247,7 @@ fn layout_for_constructor<'a>(
|
||||||
}
|
}
|
||||||
Closure(arguments, closure_layout, result) => {
|
Closure(arguments, closure_layout, result) => {
|
||||||
let fpointer = Layout::FunctionPointer(arguments, result);
|
let fpointer = Layout::FunctionPointer(arguments, result);
|
||||||
let fields = arena.alloc([fpointer, closure_layout.layout.clone()]);
|
let fields = arena.alloc([fpointer, *closure_layout.layout]);
|
||||||
HasFields(fields)
|
HasFields(fields)
|
||||||
}
|
}
|
||||||
other => unreachable!("weird layout {:?}", other),
|
other => unreachable!("weird layout {:?}", other),
|
||||||
|
@ -315,9 +315,9 @@ fn work_for_constructor<'a>(
|
||||||
let alias_symbol = Env::manual_unique_symbol(env.home, env.ident_ids);
|
let alias_symbol = Env::manual_unique_symbol(env.home, env.ident_ids);
|
||||||
|
|
||||||
let layout = if let Layout::RecursivePointer = field_layout {
|
let layout = if let Layout::RecursivePointer = field_layout {
|
||||||
full_layout.clone()
|
*full_layout
|
||||||
} else {
|
} else {
|
||||||
field_layout.clone()
|
*field_layout
|
||||||
};
|
};
|
||||||
|
|
||||||
env.deferred.assignments.push((alias_symbol, expr, layout));
|
env.deferred.assignments.push((alias_symbol, expr, layout));
|
||||||
|
@ -375,7 +375,7 @@ pub fn expand_and_cancel_proc<'a>(
|
||||||
}
|
}
|
||||||
Layout::Closure(arguments, closure_layout, result) => {
|
Layout::Closure(arguments, closure_layout, result) => {
|
||||||
let fpointer = Layout::FunctionPointer(arguments, result);
|
let fpointer = Layout::FunctionPointer(arguments, result);
|
||||||
let fields = env.arena.alloc([fpointer, closure_layout.layout.clone()]);
|
let fields = env.arena.alloc([fpointer, *closure_layout.layout]);
|
||||||
env.insert_struct_info(*symbol, fields);
|
env.insert_struct_info(*symbol, fields);
|
||||||
introduced.push(*symbol);
|
introduced.push(*symbol);
|
||||||
}
|
}
|
||||||
|
@ -412,7 +412,7 @@ fn expand_and_cancel<'a>(env: &mut Env<'a, '_>, stmt: &'a Stmt<'a>) -> &'a Stmt<
|
||||||
let mut result = {
|
let mut result = {
|
||||||
match stmt {
|
match stmt {
|
||||||
Let(mut symbol, expr, layout, cont) => {
|
Let(mut symbol, expr, layout, cont) => {
|
||||||
env.layout_map.insert(symbol, layout.clone());
|
env.layout_map.insert(symbol, *layout);
|
||||||
|
|
||||||
let mut expr = expr;
|
let mut expr = expr;
|
||||||
let mut layout = layout;
|
let mut layout = layout;
|
||||||
|
@ -423,7 +423,7 @@ fn expand_and_cancel<'a>(env: &mut Env<'a, '_>, stmt: &'a Stmt<'a>) -> &'a Stmt<
|
||||||
|
|
||||||
while !matches!(&expr, Expr::AccessAtIndex { .. } | Expr::Struct(_)) {
|
while !matches!(&expr, Expr::AccessAtIndex { .. } | Expr::Struct(_)) {
|
||||||
if let Stmt::Let(symbol1, expr1, layout1, cont1) = cont {
|
if let Stmt::Let(symbol1, expr1, layout1, cont1) = cont {
|
||||||
literal_stack.push((symbol, expr.clone(), layout.clone()));
|
literal_stack.push((symbol, expr.clone(), *layout));
|
||||||
|
|
||||||
symbol = *symbol1;
|
symbol = *symbol1;
|
||||||
expr = expr1;
|
expr = expr1;
|
||||||
|
@ -479,7 +479,7 @@ fn expand_and_cancel<'a>(env: &mut Env<'a, '_>, stmt: &'a Stmt<'a>) -> &'a Stmt<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let stmt = Let(symbol, expr.clone(), layout.clone(), new_cont);
|
let stmt = Let(symbol, expr.clone(), *layout, new_cont);
|
||||||
let mut stmt = &*env.arena.alloc(stmt);
|
let mut stmt = &*env.arena.alloc(stmt);
|
||||||
|
|
||||||
for (symbol, expr, layout) in literal_stack.into_iter().rev() {
|
for (symbol, expr, layout) in literal_stack.into_iter().rev() {
|
||||||
|
@ -519,8 +519,8 @@ fn expand_and_cancel<'a>(env: &mut Env<'a, '_>, stmt: &'a Stmt<'a>) -> &'a Stmt<
|
||||||
|
|
||||||
let stmt = Switch {
|
let stmt = Switch {
|
||||||
cond_symbol: *cond_symbol,
|
cond_symbol: *cond_symbol,
|
||||||
cond_layout: cond_layout.clone(),
|
cond_layout: *cond_layout,
|
||||||
ret_layout: ret_layout.clone(),
|
ret_layout: *ret_layout,
|
||||||
branches: new_branches.into_bump_slice(),
|
branches: new_branches.into_bump_slice(),
|
||||||
default_branch: new_default,
|
default_branch: new_default,
|
||||||
};
|
};
|
||||||
|
@ -579,7 +579,7 @@ fn expand_and_cancel<'a>(env: &mut Env<'a, '_>, stmt: &'a Stmt<'a>) -> &'a Stmt<
|
||||||
let stmt = Invoke {
|
let stmt = Invoke {
|
||||||
symbol: *symbol,
|
symbol: *symbol,
|
||||||
call: call.clone(),
|
call: call.clone(),
|
||||||
layout: layout.clone(),
|
layout: *layout,
|
||||||
pass,
|
pass,
|
||||||
fail,
|
fail,
|
||||||
};
|
};
|
||||||
|
|
|
@ -470,7 +470,7 @@ impl<'a> Context<'a> {
|
||||||
name, full_layout, ..
|
name, full_layout, ..
|
||||||
} => {
|
} => {
|
||||||
// get the borrow signature
|
// get the borrow signature
|
||||||
match self.param_map.get_symbol(*name, full_layout.clone()) {
|
match self.param_map.get_symbol(*name, *full_layout) {
|
||||||
Some(ps) => {
|
Some(ps) => {
|
||||||
let v = Expr::Call(crate::ir::Call {
|
let v = Expr::Call(crate::ir::Call {
|
||||||
call_type,
|
call_type,
|
||||||
|
@ -695,7 +695,7 @@ impl<'a> Context<'a> {
|
||||||
let pair = ctx.visit_variable_declaration(
|
let pair = ctx.visit_variable_declaration(
|
||||||
*symbol,
|
*symbol,
|
||||||
(*expr).clone(),
|
(*expr).clone(),
|
||||||
(*layout).clone(),
|
*layout,
|
||||||
b,
|
b,
|
||||||
&b_live_vars,
|
&b_live_vars,
|
||||||
);
|
);
|
||||||
|
@ -712,13 +712,7 @@ impl<'a> Context<'a> {
|
||||||
Let(symbol, expr, layout, cont) => {
|
Let(symbol, expr, layout, cont) => {
|
||||||
let ctx = self.update_var_info(*symbol, layout, expr);
|
let ctx = self.update_var_info(*symbol, layout, expr);
|
||||||
let (b, b_live_vars) = ctx.visit_stmt(cont);
|
let (b, b_live_vars) = ctx.visit_stmt(cont);
|
||||||
ctx.visit_variable_declaration(
|
ctx.visit_variable_declaration(*symbol, expr.clone(), *layout, b, &b_live_vars)
|
||||||
*symbol,
|
|
||||||
expr.clone(),
|
|
||||||
layout.clone(),
|
|
||||||
b,
|
|
||||||
&b_live_vars,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Invoke {
|
Invoke {
|
||||||
|
@ -759,7 +753,7 @@ impl<'a> Context<'a> {
|
||||||
call: call.clone(),
|
call: call.clone(),
|
||||||
pass,
|
pass,
|
||||||
fail,
|
fail,
|
||||||
layout: layout.clone(),
|
layout: *layout,
|
||||||
};
|
};
|
||||||
|
|
||||||
let cont = self.arena.alloc(invoke);
|
let cont = self.arena.alloc(invoke);
|
||||||
|
@ -783,7 +777,7 @@ impl<'a> Context<'a> {
|
||||||
name, full_layout, ..
|
name, full_layout, ..
|
||||||
} => {
|
} => {
|
||||||
// get the borrow signature
|
// get the borrow signature
|
||||||
match self.param_map.get_symbol(*name, full_layout.clone()) {
|
match self.param_map.get_symbol(*name, *full_layout) {
|
||||||
Some(ps) => self.add_dec_after_application(
|
Some(ps) => self.add_dec_after_application(
|
||||||
call.arguments,
|
call.arguments,
|
||||||
ps,
|
ps,
|
||||||
|
@ -908,8 +902,8 @@ impl<'a> Context<'a> {
|
||||||
cond_symbol: *cond_symbol,
|
cond_symbol: *cond_symbol,
|
||||||
branches,
|
branches,
|
||||||
default_branch,
|
default_branch,
|
||||||
cond_layout: cond_layout.clone(),
|
cond_layout: *cond_layout,
|
||||||
ret_layout: ret_layout.clone(),
|
ret_layout: *ret_layout,
|
||||||
});
|
});
|
||||||
|
|
||||||
(switch, case_live_vars)
|
(switch, case_live_vars)
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -23,7 +23,7 @@ pub enum LayoutProblem {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Types for code gen must be monomorphic. No type variables allowed!
|
/// Types for code gen must be monomorphic. No type variables allowed!
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum Layout<'a> {
|
pub enum Layout<'a> {
|
||||||
Builtin(Builtin<'a>),
|
Builtin(Builtin<'a>),
|
||||||
/// A layout that is empty (turns into the empty struct in LLVM IR
|
/// A layout that is empty (turns into the empty struct in LLVM IR
|
||||||
|
@ -39,7 +39,7 @@ pub enum Layout<'a> {
|
||||||
Pointer(&'a Layout<'a>),
|
Pointer(&'a Layout<'a>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum UnionLayout<'a> {
|
pub enum UnionLayout<'a> {
|
||||||
/// A non-recursive tag union
|
/// A non-recursive tag union
|
||||||
/// e.g. `Result a e : [ Ok a, Err e ]`
|
/// e.g. `Result a e : [ Ok a, Err e ]`
|
||||||
|
@ -93,7 +93,7 @@ impl<'a> UnionLayout<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct ClosureLayout<'a> {
|
pub struct ClosureLayout<'a> {
|
||||||
/// the layout that this specific closure captures
|
/// the layout that this specific closure captures
|
||||||
/// uses a Vec instead of a MutMap because it's Hash
|
/// uses a Vec instead of a MutMap because it's Hash
|
||||||
|
@ -258,7 +258,7 @@ impl<'a> ClosureLayout<'a> {
|
||||||
// define the function pointer
|
// define the function pointer
|
||||||
let function_ptr_layout = {
|
let function_ptr_layout = {
|
||||||
let mut temp = Vec::from_iter_in(argument_layouts.iter().cloned(), arena);
|
let mut temp = Vec::from_iter_in(argument_layouts.iter().cloned(), arena);
|
||||||
temp.push(closure_data_layout.clone());
|
temp.push(*closure_data_layout);
|
||||||
Layout::FunctionPointer(temp.into_bump_slice(), ret_layout)
|
Layout::FunctionPointer(temp.into_bump_slice(), ret_layout)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -278,8 +278,8 @@ impl<'a> ClosureLayout<'a> {
|
||||||
pub fn as_named_layout(&self, symbol: Symbol) -> Layout<'a> {
|
pub fn as_named_layout(&self, symbol: Symbol) -> Layout<'a> {
|
||||||
let layouts = if self.captured.is_empty() {
|
let layouts = if self.captured.is_empty() {
|
||||||
match self.layout {
|
match self.layout {
|
||||||
Layout::Struct(fields) if fields.len() == 1 => fields[0].clone(),
|
Layout::Struct(fields) if fields.len() == 1 => fields[0],
|
||||||
other => other.clone(),
|
other => *other,
|
||||||
}
|
}
|
||||||
} else if let Some((_, tag_args)) = self
|
} else if let Some((_, tag_args)) = self
|
||||||
.captured
|
.captured
|
||||||
|
@ -287,7 +287,7 @@ impl<'a> ClosureLayout<'a> {
|
||||||
.find(|(tn, _)| *tn == TagName::Closure(symbol))
|
.find(|(tn, _)| *tn == TagName::Closure(symbol))
|
||||||
{
|
{
|
||||||
if tag_args.len() == 1 {
|
if tag_args.len() == 1 {
|
||||||
tag_args[0].clone()
|
tag_args[0]
|
||||||
} else {
|
} else {
|
||||||
Layout::Struct(tag_args)
|
Layout::Struct(tag_args)
|
||||||
}
|
}
|
||||||
|
@ -303,13 +303,13 @@ impl<'a> ClosureLayout<'a> {
|
||||||
|
|
||||||
pub fn as_block_of_memory_layout(&self) -> Layout<'a> {
|
pub fn as_block_of_memory_layout(&self) -> Layout<'a> {
|
||||||
match self.layout {
|
match self.layout {
|
||||||
Layout::Struct(fields) if fields.len() == 1 => fields[0].clone(),
|
Layout::Struct(fields) if fields.len() == 1 => fields[0],
|
||||||
other => other.clone(),
|
other => *other,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn internal_layout(&self) -> Layout<'a> {
|
pub fn internal_layout(&self) -> Layout<'a> {
|
||||||
self.layout.clone()
|
*self.layout
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_closure_data(
|
pub fn build_closure_data(
|
||||||
|
@ -382,7 +382,7 @@ pub enum MemoryMode {
|
||||||
Refcounted,
|
Refcounted,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum Builtin<'a> {
|
pub enum Builtin<'a> {
|
||||||
Int128,
|
Int128,
|
||||||
Int64,
|
Int64,
|
||||||
|
@ -825,7 +825,7 @@ impl<'a> LayoutCache<'a> {
|
||||||
// of a problem
|
// of a problem
|
||||||
if false {
|
if false {
|
||||||
let cached_layout = match &result {
|
let cached_layout = match &result {
|
||||||
Ok(layout) => Cached(layout.clone()),
|
Ok(layout) => Cached(*layout),
|
||||||
Err(problem) => Problem(problem.clone()),
|
Err(problem) => Problem(problem.clone()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2057,7 +2057,7 @@ impl<'a> LayoutIds<'a> {
|
||||||
// If we had to default to next_id, it must not have been found;
|
// If we had to default to next_id, it must not have been found;
|
||||||
// store the ID we're going to return and increment next_id.
|
// store the ID we're going to return and increment next_id.
|
||||||
if answer == ids.next_id {
|
if answer == ids.next_id {
|
||||||
ids.by_id.insert(layout.clone(), ids.next_id);
|
ids.by_id.insert(*layout, ids.next_id);
|
||||||
|
|
||||||
ids.next_id += 1;
|
ids.next_id += 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@ pub mod tail_recursion;
|
||||||
// For now, following this warning's advice will lead to nasty type inference errors.
|
// For now, following this warning's advice will lead to nasty type inference errors.
|
||||||
//#[allow(clippy::ptr_arg)]
|
//#[allow(clippy::ptr_arg)]
|
||||||
//pub mod decision_tree;
|
//pub mod decision_tree;
|
||||||
#[allow(clippy::ptr_arg)]
|
|
||||||
pub mod decision_tree;
|
pub mod decision_tree;
|
||||||
#[allow(clippy::ptr_arg)]
|
#[allow(clippy::ptr_arg)]
|
||||||
pub mod exhaustive;
|
pub mod exhaustive;
|
||||||
|
|
|
@ -42,7 +42,7 @@ pub fn make_tail_recursive<'a>(
|
||||||
let params = Vec::from_iter_in(
|
let params = Vec::from_iter_in(
|
||||||
args.iter().map(|(layout, symbol)| Param {
|
args.iter().map(|(layout, symbol)| Param {
|
||||||
symbol: *symbol,
|
symbol: *symbol,
|
||||||
layout: layout.clone(),
|
layout: *layout,
|
||||||
borrow: true,
|
borrow: true,
|
||||||
}),
|
}),
|
||||||
arena,
|
arena,
|
||||||
|
@ -117,7 +117,7 @@ fn insert_jumps<'a>(
|
||||||
if opt_cont.is_some() {
|
if opt_cont.is_some() {
|
||||||
let cont = opt_cont.unwrap_or(cont);
|
let cont = opt_cont.unwrap_or(cont);
|
||||||
|
|
||||||
Some(arena.alloc(Let(*symbol, expr.clone(), layout.clone(), cont)))
|
Some(arena.alloc(Let(*symbol, expr.clone(), *layout, cont)))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,7 @@ fn insert_jumps<'a>(
|
||||||
let stmt = Invoke {
|
let stmt = Invoke {
|
||||||
symbol: *symbol,
|
symbol: *symbol,
|
||||||
call: call.clone(),
|
call: call.clone(),
|
||||||
layout: layout.clone(),
|
layout: *layout,
|
||||||
pass,
|
pass,
|
||||||
fail,
|
fail,
|
||||||
};
|
};
|
||||||
|
@ -222,10 +222,10 @@ fn insert_jumps<'a>(
|
||||||
|
|
||||||
Some(arena.alloc(Switch {
|
Some(arena.alloc(Switch {
|
||||||
cond_symbol: *cond_symbol,
|
cond_symbol: *cond_symbol,
|
||||||
cond_layout: cond_layout.clone(),
|
cond_layout: *cond_layout,
|
||||||
default_branch,
|
default_branch,
|
||||||
branches,
|
branches,
|
||||||
ret_layout: ret_layout.clone(),
|
ret_layout: *ret_layout,
|
||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
|
@ -880,7 +880,7 @@ fn check_for_infinite_type(
|
||||||
let var = loc_var.value;
|
let var = loc_var.value;
|
||||||
|
|
||||||
let is_uniq_infer = matches!(
|
let is_uniq_infer = matches!(
|
||||||
subs.get(var).content,
|
subs.get_ref(var).content,
|
||||||
Content::Alias(Symbol::ATTR_ATTR, _, _)
|
Content::Alias(Symbol::ATTR_ATTR, _, _)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1088,7 +1088,7 @@ fn generalize(
|
||||||
for vars in all_but_last_pool {
|
for vars in all_but_last_pool {
|
||||||
for &var in vars {
|
for &var in vars {
|
||||||
if !subs.redundant(var) {
|
if !subs.redundant(var) {
|
||||||
let rank = subs.get(var).rank;
|
let rank = subs.get_rank(var);
|
||||||
|
|
||||||
pools.get_mut(rank).push(var);
|
pools.get_mut(rank).push(var);
|
||||||
}
|
}
|
||||||
|
@ -1099,13 +1099,12 @@ fn generalize(
|
||||||
// otherwise generalize
|
// otherwise generalize
|
||||||
for &var in last_pool {
|
for &var in last_pool {
|
||||||
if !subs.redundant(var) {
|
if !subs.redundant(var) {
|
||||||
let mut desc = subs.get(var);
|
let desc_rank = subs.get_rank(var);
|
||||||
|
|
||||||
if desc.rank < young_rank {
|
if desc_rank < young_rank {
|
||||||
pools.get_mut(desc.rank).push(var);
|
pools.get_mut(desc_rank).push(var);
|
||||||
} else {
|
} else {
|
||||||
desc.rank = Rank::NONE;
|
subs.set_rank(var, Rank::NONE);
|
||||||
subs.set(var, desc);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1121,18 +1120,8 @@ fn pool_to_rank_table(
|
||||||
|
|
||||||
// Sort the variables into buckets by rank.
|
// Sort the variables into buckets by rank.
|
||||||
for &var in young_vars.iter() {
|
for &var in young_vars.iter() {
|
||||||
let desc = subs.get(var);
|
let rank = subs.get_rank(var);
|
||||||
let rank = desc.rank;
|
subs.set_mark(var, young_mark);
|
||||||
|
|
||||||
subs.set(
|
|
||||||
var,
|
|
||||||
Descriptor {
|
|
||||||
rank,
|
|
||||||
mark: young_mark,
|
|
||||||
content: desc.content,
|
|
||||||
copy: desc.copy,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
debug_assert!(rank.into_usize() < young_rank.into_usize() + 1);
|
debug_assert!(rank.into_usize() < young_rank.into_usize() + 1);
|
||||||
pools.get_mut(rank).push(var);
|
pools.get_mut(rank).push(var);
|
||||||
|
@ -1155,24 +1144,15 @@ fn adjust_rank(
|
||||||
if desc.mark == young_mark {
|
if desc.mark == young_mark {
|
||||||
let Descriptor {
|
let Descriptor {
|
||||||
content,
|
content,
|
||||||
rank,
|
rank: _,
|
||||||
mark: _,
|
mark: _,
|
||||||
copy,
|
copy,
|
||||||
} = desc;
|
} = desc;
|
||||||
|
|
||||||
// Mark the variable as visited before adjusting content, as it may be cyclic.
|
// Mark the variable as visited before adjusting content, as it may be cyclic.
|
||||||
subs.set(
|
subs.set_mark(var, visit_mark);
|
||||||
var,
|
|
||||||
Descriptor {
|
|
||||||
content: content.clone(),
|
|
||||||
rank,
|
|
||||||
mark: visit_mark,
|
|
||||||
copy,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
let max_rank =
|
let max_rank = adjust_rank_content(subs, young_mark, visit_mark, group_rank, &content);
|
||||||
adjust_rank_content(subs, young_mark, visit_mark, group_rank, content.clone());
|
|
||||||
|
|
||||||
subs.set(
|
subs.set(
|
||||||
var,
|
var,
|
||||||
|
@ -1208,7 +1188,7 @@ fn adjust_rank_content(
|
||||||
young_mark: Mark,
|
young_mark: Mark,
|
||||||
visit_mark: Mark,
|
visit_mark: Mark,
|
||||||
group_rank: Rank,
|
group_rank: Rank,
|
||||||
content: Content,
|
content: &Content,
|
||||||
) -> Rank {
|
) -> Rank {
|
||||||
use roc_types::subs::Content::*;
|
use roc_types::subs::Content::*;
|
||||||
use roc_types::subs::FlatType::*;
|
use roc_types::subs::FlatType::*;
|
||||||
|
@ -1224,14 +1204,15 @@ fn adjust_rank_content(
|
||||||
let mut rank = Rank::toplevel();
|
let mut rank = Rank::toplevel();
|
||||||
|
|
||||||
for var in args {
|
for var in args {
|
||||||
rank = rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, var));
|
rank =
|
||||||
|
rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, *var));
|
||||||
}
|
}
|
||||||
|
|
||||||
rank
|
rank
|
||||||
}
|
}
|
||||||
|
|
||||||
Func(arg_vars, closure_var, ret_var) => {
|
Func(arg_vars, closure_var, ret_var) => {
|
||||||
let mut rank = adjust_rank(subs, young_mark, visit_mark, group_rank, ret_var);
|
let mut rank = adjust_rank(subs, young_mark, visit_mark, group_rank, *ret_var);
|
||||||
|
|
||||||
// TODO investigate further.
|
// TODO investigate further.
|
||||||
//
|
//
|
||||||
|
@ -1244,12 +1225,13 @@ fn adjust_rank_content(
|
||||||
young_mark,
|
young_mark,
|
||||||
visit_mark,
|
visit_mark,
|
||||||
group_rank,
|
group_rank,
|
||||||
closure_var,
|
*closure_var,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
for var in arg_vars {
|
for var in arg_vars {
|
||||||
rank = rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, var));
|
rank =
|
||||||
|
rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, *var));
|
||||||
}
|
}
|
||||||
|
|
||||||
rank
|
rank
|
||||||
|
@ -1263,9 +1245,9 @@ fn adjust_rank_content(
|
||||||
EmptyTagUnion => Rank::toplevel(),
|
EmptyTagUnion => Rank::toplevel(),
|
||||||
|
|
||||||
Record(fields, ext_var) => {
|
Record(fields, ext_var) => {
|
||||||
let mut rank = adjust_rank(subs, young_mark, visit_mark, group_rank, ext_var);
|
let mut rank = adjust_rank(subs, young_mark, visit_mark, group_rank, *ext_var);
|
||||||
|
|
||||||
for (_, var) in fields {
|
for var in fields.values() {
|
||||||
rank = rank.max(adjust_rank(
|
rank = rank.max(adjust_rank(
|
||||||
subs,
|
subs,
|
||||||
young_mark,
|
young_mark,
|
||||||
|
@ -1279,7 +1261,7 @@ fn adjust_rank_content(
|
||||||
}
|
}
|
||||||
|
|
||||||
TagUnion(tags, ext_var) => {
|
TagUnion(tags, ext_var) => {
|
||||||
let mut rank = adjust_rank(subs, young_mark, visit_mark, group_rank, ext_var);
|
let mut rank = adjust_rank(subs, young_mark, visit_mark, group_rank, *ext_var);
|
||||||
|
|
||||||
for var in tags.values().flatten() {
|
for var in tags.values().flatten() {
|
||||||
rank =
|
rank =
|
||||||
|
@ -1290,9 +1272,9 @@ fn adjust_rank_content(
|
||||||
}
|
}
|
||||||
|
|
||||||
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
||||||
let mut rank = adjust_rank(subs, young_mark, visit_mark, group_rank, rec_var);
|
let mut rank = adjust_rank(subs, young_mark, visit_mark, group_rank, *rec_var);
|
||||||
rank = rank.max(adjust_rank(
|
rank = rank.max(adjust_rank(
|
||||||
subs, young_mark, visit_mark, group_rank, ext_var,
|
subs, young_mark, visit_mark, group_rank, *ext_var,
|
||||||
));
|
));
|
||||||
|
|
||||||
for var in tags.values().flatten() {
|
for var in tags.values().flatten() {
|
||||||
|
@ -1305,10 +1287,11 @@ fn adjust_rank_content(
|
||||||
|
|
||||||
Boolean(Bool::Shared) => Rank::toplevel(),
|
Boolean(Bool::Shared) => Rank::toplevel(),
|
||||||
Boolean(Bool::Container(cvar, mvars)) => {
|
Boolean(Bool::Container(cvar, mvars)) => {
|
||||||
let mut rank = adjust_rank(subs, young_mark, visit_mark, group_rank, cvar);
|
let mut rank = adjust_rank(subs, young_mark, visit_mark, group_rank, *cvar);
|
||||||
|
|
||||||
for var in mvars {
|
for var in mvars {
|
||||||
rank = rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, var));
|
rank =
|
||||||
|
rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, *var));
|
||||||
}
|
}
|
||||||
|
|
||||||
rank
|
rank
|
||||||
|
@ -1322,13 +1305,13 @@ fn adjust_rank_content(
|
||||||
let mut rank = Rank::toplevel();
|
let mut rank = Rank::toplevel();
|
||||||
|
|
||||||
for (_, var) in args {
|
for (_, var) in args {
|
||||||
rank = rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, var));
|
rank = rank.max(adjust_rank(subs, young_mark, visit_mark, group_rank, *var));
|
||||||
}
|
}
|
||||||
|
|
||||||
// from elm-compiler: THEORY: anything in the real_var would be Rank::toplevel()
|
// from elm-compiler: THEORY: anything in the real_var would be Rank::toplevel()
|
||||||
// this theory is not true in Roc! aliases of function types capture the closure var
|
// this theory is not true in Roc! aliases of function types capture the closure var
|
||||||
rank = rank.max(adjust_rank(
|
rank = rank.max(adjust_rank(
|
||||||
subs, young_mark, visit_mark, group_rank, real_var,
|
subs, young_mark, visit_mark, group_rank, *real_var,
|
||||||
));
|
));
|
||||||
|
|
||||||
rank
|
rank
|
||||||
|
|
|
@ -176,7 +176,7 @@ pub fn helper<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
let (_, main_fn_layout) = match procedures.keys().find(|(s, _)| *s == main_fn_symbol) {
|
let (_, main_fn_layout) = match procedures.keys().find(|(s, _)| *s == main_fn_symbol) {
|
||||||
Some(found) => found.clone(),
|
Some(found) => *found,
|
||||||
None => panic!(
|
None => panic!(
|
||||||
"The main function symbol {:?} does not have a procedure in {:?}",
|
"The main function symbol {:?} does not have a procedure in {:?}",
|
||||||
main_fn_symbol,
|
main_fn_symbol,
|
||||||
|
|
|
@ -306,6 +306,18 @@ impl Subs {
|
||||||
self.utable.probe_value(key)
|
self.utable.probe_value(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_ref(&self, key: Variable) -> &Descriptor {
|
||||||
|
&self.utable.probe_value_ref(key).value
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_rank(&mut self, key: Variable) -> Rank {
|
||||||
|
self.utable.probe_value_ref(key).value.rank
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_mark(&mut self, key: Variable) -> Mark {
|
||||||
|
self.utable.probe_value_ref(key).value.mark
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_without_compacting(&self, key: Variable) -> Descriptor {
|
pub fn get_without_compacting(&self, key: Variable) -> Descriptor {
|
||||||
self.utable.probe_value_without_compacting(key)
|
self.utable.probe_value_without_compacting(key)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[package]
|
[package]
|
||||||
name = "docs"
|
name = "roc_docs"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Pablo Hirafuji <pablohirafuji@gmail.com>"]
|
authors = ["Pablo Hirafuji <pablohirafuji@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
extern crate fs_extra;
|
extern crate fs_extra;
|
||||||
extern crate handlebars;
|
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
|
@ -19,26 +18,26 @@ use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct Template {
|
pub struct Template {
|
||||||
package_name: String,
|
pub package_name: String,
|
||||||
package_version: String,
|
pub package_version: String,
|
||||||
module_name: String,
|
pub module_name: String,
|
||||||
module_docs: String,
|
pub module_docs: String,
|
||||||
module_entries: Vec<ModuleEntry>,
|
pub module_entries: Vec<ModuleEntry>,
|
||||||
module_links: Vec<TemplateLink>,
|
pub module_links: Vec<TemplateLink>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Clone, Debug, PartialEq)]
|
#[derive(Serialize, Clone, Debug, PartialEq)]
|
||||||
pub struct ModuleEntry {
|
pub struct ModuleEntry {
|
||||||
name: String,
|
pub name: String,
|
||||||
docs: String,
|
pub docs: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct TemplateLink {
|
pub struct TemplateLink {
|
||||||
name: String,
|
pub name: String,
|
||||||
href: String,
|
pub href: String,
|
||||||
classes: String,
|
pub classes: String,
|
||||||
entries: Vec<TemplateLinkEntry>,
|
pub entries: Vec<TemplateLinkEntry>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
|
@ -46,27 +45,9 @@ pub struct TemplateLinkEntry {
|
||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
pub fn generate(filenames: Vec<PathBuf>, std_lib: StdLib, build_dir: &Path) {
|
||||||
generate(
|
let files_docs = files_to_documentations(filenames, std_lib);
|
||||||
vec![
|
//
|
||||||
PathBuf::from(r"../compiler/builtins/docs/Bool.roc"),
|
|
||||||
PathBuf::from(r"../compiler/builtins/docs/Dict.roc"),
|
|
||||||
// Not working
|
|
||||||
// PathBuf::from(r"../compiler/builtins/docs/List.roc"),
|
|
||||||
// Not working
|
|
||||||
// PathBuf::from(r"../compiler/builtins/docs/Num.roc"),
|
|
||||||
PathBuf::from(r"../compiler/builtins/docs/Set.roc"),
|
|
||||||
PathBuf::from(r"../compiler/builtins/docs/Str.roc"),
|
|
||||||
],
|
|
||||||
roc_builtins::std::standard_stdlib(),
|
|
||||||
Path::new("../compiler/builtins/docs"),
|
|
||||||
Path::new("./build"),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn generate(filenames: Vec<PathBuf>, std_lib: StdLib, src_dir: &Path, build_dir: &Path) {
|
|
||||||
let files_docs = files_to_documentations(filenames, std_lib, src_dir);
|
|
||||||
|
|
||||||
// TODO: get info from a file like "elm.json"
|
// TODO: get info from a file like "elm.json"
|
||||||
let package = roc_load::docs::Documentation {
|
let package = roc_load::docs::Documentation {
|
||||||
name: "roc/builtins".to_string(),
|
name: "roc/builtins".to_string(),
|
||||||
|
@ -75,21 +56,10 @@ pub fn generate(filenames: Vec<PathBuf>, std_lib: StdLib, src_dir: &Path, build_
|
||||||
modules: files_docs,
|
modules: files_docs,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Remove old build folder, if exists
|
|
||||||
let _ = fs::remove_dir_all(build_dir);
|
|
||||||
|
|
||||||
let version_folder = build_dir
|
|
||||||
.join(package.name.clone())
|
|
||||||
.join(package.version.clone());
|
|
||||||
|
|
||||||
// Make sure the output directories exists
|
|
||||||
fs::create_dir_all(&version_folder)
|
|
||||||
.expect("TODO gracefully handle creating directories failing");
|
|
||||||
|
|
||||||
// Register handlebars template
|
// Register handlebars template
|
||||||
let mut handlebars = handlebars::Handlebars::new();
|
let mut handlebars = handlebars::Handlebars::new();
|
||||||
handlebars
|
handlebars
|
||||||
.register_template_file("page", "./src/templates/page.hbs")
|
.register_template_file("page", "./docs/src/templates/page.hbs")
|
||||||
.expect("TODO gracefully handle registering template failing");
|
.expect("TODO gracefully handle registering template failing");
|
||||||
|
|
||||||
// Write each package's module docs html file
|
// Write each package's module docs html file
|
||||||
|
@ -97,7 +67,7 @@ pub fn generate(filenames: Vec<PathBuf>, std_lib: StdLib, src_dir: &Path, build_
|
||||||
let template = documentation_to_template_data(&package, module);
|
let template = documentation_to_template_data(&package, module);
|
||||||
|
|
||||||
let handlebars_data = handlebars::to_json(&template);
|
let handlebars_data = handlebars::to_json(&template);
|
||||||
let filepath = version_folder.join(format!("{}.html", module.name));
|
let filepath = build_dir.join(format!("{}.html", module.name));
|
||||||
let mut output_file =
|
let mut output_file =
|
||||||
fs::File::create(filepath).expect("TODO gracefully handle creating file failing");
|
fs::File::create(filepath).expect("TODO gracefully handle creating file failing");
|
||||||
handlebars
|
handlebars
|
||||||
|
@ -105,34 +75,25 @@ pub fn generate(filenames: Vec<PathBuf>, std_lib: StdLib, src_dir: &Path, build_
|
||||||
.expect("TODO gracefully handle writing file failing");
|
.expect("TODO gracefully handle writing file failing");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy /static folder content to /build
|
|
||||||
let copy_options = fs_extra::dir::CopyOptions {
|
|
||||||
overwrite: true,
|
|
||||||
skip_exist: false,
|
|
||||||
buffer_size: 64000, //64kb
|
|
||||||
copy_inside: false,
|
|
||||||
content_only: true,
|
|
||||||
depth: 0,
|
|
||||||
};
|
|
||||||
fs_extra::dir::copy("./src/static/", &build_dir, ©_options)
|
|
||||||
.expect("TODO gracefully handle copying static content failing");
|
|
||||||
println!("Docs generated at {}", build_dir.display());
|
println!("Docs generated at {}", build_dir.display());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn files_to_documentations(
|
pub fn files_to_documentations(
|
||||||
filenames: Vec<PathBuf>,
|
filenames: Vec<PathBuf>,
|
||||||
std_lib: StdLib,
|
std_lib: StdLib,
|
||||||
src_dir: &Path,
|
|
||||||
) -> Vec<ModuleDocumentation> {
|
) -> Vec<ModuleDocumentation> {
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
let mut files_docs = vec![];
|
let mut files_docs = vec![];
|
||||||
|
|
||||||
for filename in filenames {
|
for filename in filenames {
|
||||||
|
let mut src_dir = filename.clone();
|
||||||
|
src_dir.pop();
|
||||||
|
|
||||||
match roc_load::file::load_and_typecheck(
|
match roc_load::file::load_and_typecheck(
|
||||||
&arena,
|
&arena,
|
||||||
filename,
|
filename,
|
||||||
&std_lib,
|
&std_lib,
|
||||||
src_dir,
|
src_dir.as_path(),
|
||||||
MutMap::default(),
|
MutMap::default(),
|
||||||
8, // TODO: Is it okay to hardcode ptr_bytes here? I think it should be fine since we'er only type checking (also, 8 => 32bit system)
|
8, // TODO: Is it okay to hardcode ptr_bytes here? I think it should be fine since we'er only type checking (also, 8 => 32bit system)
|
||||||
builtin_defs_map,
|
builtin_defs_map,
|
||||||
|
@ -148,7 +109,10 @@ fn files_to_documentations(
|
||||||
files_docs
|
files_docs
|
||||||
}
|
}
|
||||||
|
|
||||||
fn documentation_to_template_data(doc: &Documentation, module: &ModuleDocumentation) -> Template {
|
pub fn documentation_to_template_data(
|
||||||
|
doc: &Documentation,
|
||||||
|
module: &ModuleDocumentation,
|
||||||
|
) -> Template {
|
||||||
Template {
|
Template {
|
||||||
package_name: doc.name.clone(),
|
package_name: doc.name.clone(),
|
||||||
package_version: doc.version.clone(),
|
package_version: doc.version.clone(),
|
||||||
|
@ -248,51 +212,3 @@ fn markdown_to_html(markdown: String) -> String {
|
||||||
pulldown_cmark::html::push_html(&mut docs_html, docs_parser.into_iter());
|
pulldown_cmark::html::push_html(&mut docs_html, docs_parser.into_iter());
|
||||||
docs_html
|
docs_html
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test_docs {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn internal() {
|
|
||||||
let files_docs = files_to_documentations(
|
|
||||||
vec![PathBuf::from(r"tests/fixtures/Interface.roc")],
|
|
||||||
roc_builtins::std::standard_stdlib(),
|
|
||||||
Path::new("tests/fixtures"),
|
|
||||||
);
|
|
||||||
|
|
||||||
let package = roc_load::docs::Documentation {
|
|
||||||
name: "roc/builtins".to_string(),
|
|
||||||
version: "1.0.0".to_string(),
|
|
||||||
docs: "Package introduction or README.".to_string(),
|
|
||||||
modules: files_docs,
|
|
||||||
};
|
|
||||||
|
|
||||||
let expected_entries = vec![
|
|
||||||
ModuleEntry {
|
|
||||||
name: "singleline".to_string(),
|
|
||||||
docs: "<p>Single line documentation.</p>\n".to_string(),
|
|
||||||
},
|
|
||||||
ModuleEntry {
|
|
||||||
name: "multiline".to_string(),
|
|
||||||
docs: "<p>Multiline documentation.\nWithout any complex syntax yet!</p>\n".to_string(),
|
|
||||||
}, ModuleEntry {
|
|
||||||
name: "multiparagraph".to_string(),
|
|
||||||
docs: "<p>Multiparagraph documentation.</p>\n<p>Without any complex syntax yet!</p>\n".to_string(),
|
|
||||||
}, ModuleEntry {
|
|
||||||
name: "codeblock".to_string(),
|
|
||||||
docs: "<p>Turns >>> into code block for now.</p>\n<pre><code class=\"language-roc\">codeblock</code></pre>\n".to_string(),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
for module in &package.modules {
|
|
||||||
let template = documentation_to_template_data(&package, module);
|
|
||||||
assert_eq!(template.module_name, "Test");
|
|
||||||
template
|
|
||||||
.module_entries
|
|
||||||
.iter()
|
|
||||||
.zip(expected_entries.iter())
|
|
||||||
.for_each(|(x, y)| assert_eq!(x, y));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
49
docs/tests/test_docs.rs
Normal file
49
docs/tests/test_docs.rs
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
use roc_docs::{documentation_to_template_data, files_to_documentations, ModuleEntry};
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test_docs {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn internal() {
|
||||||
|
let files_docs = files_to_documentations(
|
||||||
|
vec![PathBuf::from(r"tests/fixtures/Interface.roc")],
|
||||||
|
roc_builtins::std::standard_stdlib(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let package = roc_load::docs::Documentation {
|
||||||
|
name: "roc/builtins".to_string(),
|
||||||
|
version: "1.0.0".to_string(),
|
||||||
|
docs: "Package introduction or README.".to_string(),
|
||||||
|
modules: files_docs,
|
||||||
|
};
|
||||||
|
|
||||||
|
let expected_entries = vec![
|
||||||
|
ModuleEntry {
|
||||||
|
name: "singleline".to_string(),
|
||||||
|
docs: "<p>Single line documentation.</p>\n".to_string(),
|
||||||
|
},
|
||||||
|
ModuleEntry {
|
||||||
|
name: "multiline".to_string(),
|
||||||
|
docs: "<p>Multiline documentation.\nWithout any complex syntax yet!</p>\n".to_string(),
|
||||||
|
}, ModuleEntry {
|
||||||
|
name: "multiparagraph".to_string(),
|
||||||
|
docs: "<p>Multiparagraph documentation.</p>\n<p>Without any complex syntax yet!</p>\n".to_string(),
|
||||||
|
}, ModuleEntry {
|
||||||
|
name: "codeblock".to_string(),
|
||||||
|
docs: "<p>Turns >>> into code block for now.</p>\n<pre><code class=\"language-roc\">codeblock</code></pre>\n".to_string(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for module in &package.modules {
|
||||||
|
let template = documentation_to_template_data(&package, module);
|
||||||
|
assert_eq!(template.module_name, "Test");
|
||||||
|
template
|
||||||
|
.module_entries
|
||||||
|
.iter()
|
||||||
|
.zip(expected_entries.iter())
|
||||||
|
.for_each(|(x, y)| assert_eq!(x, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
vendor/ena/src/unify/mod.rs
vendored
11
vendor/ena/src/unify/mod.rs
vendored
|
@ -433,6 +433,17 @@ where
|
||||||
self.value(id).value.clone()
|
self.value(id).value.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the current value for the given key. If the key has
|
||||||
|
/// been union'd, this will give the value from the current root.
|
||||||
|
pub fn probe_value_ref<K1>(&self, id: K1) -> &VarValue<K>
|
||||||
|
where
|
||||||
|
K1: Into<K>,
|
||||||
|
{
|
||||||
|
let id = id.into();
|
||||||
|
let id = self.get_root_key_without_compacting(id);
|
||||||
|
self.value(id)
|
||||||
|
}
|
||||||
|
|
||||||
/// This is for a debug_assert! in solve() only. Do not use it elsewhere!
|
/// This is for a debug_assert! in solve() only. Do not use it elsewhere!
|
||||||
pub fn probe_value_without_compacting<K1>(&self, id: K1) -> V
|
pub fn probe_value_without_compacting<K1>(&self, id: K1) -> V
|
||||||
where
|
where
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue