mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 15:51:12 +00:00
commit
65af1f54e1
25 changed files with 3225 additions and 67 deletions
75
Cargo.lock
generated
75
Cargo.lock
generated
|
@ -210,7 +210,16 @@ dependencies = [
|
||||||
"block-padding",
|
"block-padding",
|
||||||
"byte-tools",
|
"byte-tools",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"generic-array",
|
"generic-array 0.12.4",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-buffer"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array 0.14.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -577,6 +586,15 @@ dependencies = [
|
||||||
"objc",
|
"objc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cpufeatures"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dec1028182c380cc45a2e2c5ec841134f2dfd0f8f5f0a5bcd68004f81b5efdf4"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crc32fast"
|
name = "crc32fast"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
|
@ -840,7 +858,16 @@ version = "0.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
|
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"generic-array",
|
"generic-array 0.12.4",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "digest"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array 0.14.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1134,6 +1161,16 @@ dependencies = [
|
||||||
"typenum",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "generic-array"
|
||||||
|
version = "0.14.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
|
||||||
|
dependencies = [
|
||||||
|
"typenum",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.1.16"
|
version = "0.1.16"
|
||||||
|
@ -1875,6 +1912,14 @@ dependencies = [
|
||||||
"ws2_32-sys",
|
"ws2_32-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "morphic_lib"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"sha2",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "naga"
|
name = "naga"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
|
@ -2116,6 +2161,12 @@ version = "0.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
|
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "opaque-debug"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ordered-float"
|
name = "ordered-float"
|
||||||
version = "2.1.1"
|
version = "2.1.1"
|
||||||
|
@ -3212,6 +3263,7 @@ dependencies = [
|
||||||
"indoc 0.3.6",
|
"indoc 0.3.6",
|
||||||
"linked-hash-map",
|
"linked-hash-map",
|
||||||
"maplit",
|
"maplit",
|
||||||
|
"morphic_lib",
|
||||||
"pretty_assertions 0.5.1",
|
"pretty_assertions 0.5.1",
|
||||||
"quickcheck 0.8.5",
|
"quickcheck 0.8.5",
|
||||||
"quickcheck_macros 0.8.0",
|
"quickcheck_macros 0.8.0",
|
||||||
|
@ -3557,10 +3609,23 @@ version = "0.8.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
|
checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"block-buffer",
|
"block-buffer 0.7.3",
|
||||||
"digest",
|
"digest 0.8.1",
|
||||||
"fake-simd",
|
"fake-simd",
|
||||||
"opaque-debug",
|
"opaque-debug 0.2.3",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha2"
|
||||||
|
version = "0.9.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d8f6b75b17576b792bef0db1bcc4b8b8bcdf9506744cf34b974195487af6cff2"
|
||||||
|
dependencies = [
|
||||||
|
"block-buffer 0.9.0",
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest 0.9.0",
|
||||||
|
"opaque-debug 0.3.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -844,7 +844,7 @@ pub fn build_exp_call<'a, 'ctx, 'env>(
|
||||||
.unwrap_or_else(|| panic!("LLVM error: Invalid call by pointer."))
|
.unwrap_or_else(|| panic!("LLVM error: Invalid call by pointer."))
|
||||||
}
|
}
|
||||||
|
|
||||||
CallType::LowLevel { op } => {
|
CallType::LowLevel { op, update_mode: _ } => {
|
||||||
run_low_level(env, layout_ids, scope, parent, layout, *op, arguments)
|
run_low_level(env, layout_ids, scope, parent, layout, *op, arguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -214,7 +214,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CallType::LowLevel { op: lowlevel } => {
|
CallType::LowLevel { op: lowlevel, .. } => {
|
||||||
self.build_run_low_level(sym, lowlevel, arguments, layout)
|
self.build_run_low_level(sym, lowlevel, arguments, layout)
|
||||||
}
|
}
|
||||||
x => Err(format!("the call type, {:?}, is not yet implemented", x)),
|
x => Err(format!("the call type, {:?}, is not yet implemented", x)),
|
||||||
|
|
|
@ -2046,6 +2046,14 @@ fn update<'a>(
|
||||||
&& state.dependencies.solved_all()
|
&& state.dependencies.solved_all()
|
||||||
&& state.goal_phase == Phase::MakeSpecializations
|
&& state.goal_phase == Phase::MakeSpecializations
|
||||||
{
|
{
|
||||||
|
if false {
|
||||||
|
let it = state.procedures.iter().map(|x| x.1);
|
||||||
|
|
||||||
|
if let Err(e) = roc_mono::alias_analysis::spec_program(it) {
|
||||||
|
println!("Error in alias analysis: {:?}", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Proc::insert_refcount_operations(arena, &mut state.procedures);
|
Proc::insert_refcount_operations(arena, &mut state.procedures);
|
||||||
|
|
||||||
Proc::optimize_refcount_operations(
|
Proc::optimize_refcount_operations(
|
||||||
|
@ -3799,6 +3807,8 @@ fn make_specializations<'a>(
|
||||||
home,
|
home,
|
||||||
ident_ids: &mut ident_ids,
|
ident_ids: &mut ident_ids,
|
||||||
ptr_bytes,
|
ptr_bytes,
|
||||||
|
update_mode_counter: 0,
|
||||||
|
call_specialization_counter: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: for now this final specialization pass is sequential,
|
// TODO: for now this final specialization pass is sequential,
|
||||||
|
@ -3860,6 +3870,8 @@ fn build_pending_specializations<'a>(
|
||||||
home,
|
home,
|
||||||
ident_ids: &mut ident_ids,
|
ident_ids: &mut ident_ids,
|
||||||
ptr_bytes,
|
ptr_bytes,
|
||||||
|
update_mode_counter: 0,
|
||||||
|
call_specialization_counter: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add modules' decls to Procs
|
// Add modules' decls to Procs
|
||||||
|
|
|
@ -105,6 +105,10 @@ impl Symbol {
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const fn to_ne_bytes(self) -> [u8; 8] {
|
||||||
|
self.0.to_ne_bytes()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Rather than displaying as this:
|
/// Rather than displaying as this:
|
||||||
|
|
|
@ -15,6 +15,7 @@ roc_unify = { path = "../unify" }
|
||||||
roc_solve = { path = "../solve" }
|
roc_solve = { path = "../solve" }
|
||||||
roc_problem = { path = "../problem" }
|
roc_problem = { path = "../problem" }
|
||||||
ven_pretty = { path = "../../vendor/pretty" }
|
ven_pretty = { path = "../../vendor/pretty" }
|
||||||
|
morphic_lib = { path = "../../vendor/morphic_lib" }
|
||||||
bumpalo = { version = "3.6.1", features = ["collections"] }
|
bumpalo = { version = "3.6.1", features = ["collections"] }
|
||||||
hashbrown = { version = "0.11.2", features = [ "bumpalo" ] }
|
hashbrown = { version = "0.11.2", features = [ "bumpalo" ] }
|
||||||
ven_ena = { path = "../../vendor/ena" }
|
ven_ena = { path = "../../vendor/ena" }
|
||||||
|
|
620
compiler/mono/src/alias_analysis.rs
Normal file
620
compiler/mono/src/alias_analysis.rs
Normal file
|
@ -0,0 +1,620 @@
|
||||||
|
use morphic_lib::TypeContext;
|
||||||
|
use morphic_lib::{
|
||||||
|
BlockExpr, BlockId, CalleeSpecVar, EntryPointName, ExprContext, FuncDef, FuncDefBuilder,
|
||||||
|
FuncName, ModDefBuilder, ModName, ProgramBuilder, Result, TypeId, TypeName, UpdateModeVar,
|
||||||
|
ValueId,
|
||||||
|
};
|
||||||
|
use roc_collections::all::MutMap;
|
||||||
|
use roc_module::low_level::LowLevel;
|
||||||
|
use roc_module::symbol::Symbol;
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
|
use crate::ir::{Call, CallType, Expr, Literal, ModifyRc, Proc, Stmt};
|
||||||
|
use crate::layout::{Builtin, Layout, ListLayout, UnionLayout};
|
||||||
|
|
||||||
|
// just using one module for now
|
||||||
|
const MOD_LIST: ModName = ModName(b"UserApp");
|
||||||
|
const MOD_APP: ModName = ModName(b"UserApp");
|
||||||
|
|
||||||
|
pub fn spec_program<'a, I>(procs: I) -> Result<morphic_lib::Solutions>
|
||||||
|
where
|
||||||
|
I: Iterator<Item = &'a Proc<'a>>,
|
||||||
|
{
|
||||||
|
let mut main_function = None;
|
||||||
|
let main_module = {
|
||||||
|
let mut m = ModDefBuilder::new();
|
||||||
|
|
||||||
|
for proc in procs {
|
||||||
|
let spec = proc_spec(proc)?;
|
||||||
|
|
||||||
|
m.add_func(FuncName(&proc.name.to_ne_bytes()), spec)?;
|
||||||
|
|
||||||
|
if format!("{:?}", proc.name).contains("mainForHost") {
|
||||||
|
main_function = Some(proc.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m.build()?
|
||||||
|
};
|
||||||
|
|
||||||
|
let program = {
|
||||||
|
let mut p = ProgramBuilder::new();
|
||||||
|
p.add_mod(MOD_APP, main_module)?;
|
||||||
|
p.add_entry_point(
|
||||||
|
EntryPointName(b"mainForHost"),
|
||||||
|
MOD_APP,
|
||||||
|
FuncName(&main_function.unwrap().to_ne_bytes()),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
p.build()?
|
||||||
|
};
|
||||||
|
|
||||||
|
morphic_lib::solve(program)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn proc_spec(proc: &Proc) -> Result<FuncDef> {
|
||||||
|
let mut builder = FuncDefBuilder::new();
|
||||||
|
let mut env = Env::default();
|
||||||
|
|
||||||
|
let block = builder.add_block();
|
||||||
|
|
||||||
|
// introduce the arguments
|
||||||
|
let mut argument_layouts = Vec::new();
|
||||||
|
for (i, (layout, symbol)) in proc.args.iter().enumerate() {
|
||||||
|
let value_id = builder.add_get_tuple_field(block, builder.get_argument(), i as u32)?;
|
||||||
|
env.symbols.insert(*symbol, value_id);
|
||||||
|
|
||||||
|
argument_layouts.push(*layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
let value_id = stmt_spec(&mut builder, &mut env, block, &proc.ret_layout, &proc.body)?;
|
||||||
|
|
||||||
|
let root = BlockExpr(block, value_id);
|
||||||
|
let arg_type_id = layout_spec(&mut builder, &Layout::Struct(&argument_layouts))?;
|
||||||
|
let ret_type_id = layout_spec(&mut builder, &proc.ret_layout)?;
|
||||||
|
builder.build(arg_type_id, ret_type_id, root)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct Env {
|
||||||
|
symbols: MutMap<Symbol, ValueId>,
|
||||||
|
join_points: MutMap<crate::ir::JoinPointId, morphic_lib::JoinPointId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stmt_spec(
|
||||||
|
builder: &mut FuncDefBuilder,
|
||||||
|
env: &mut Env,
|
||||||
|
block: BlockId,
|
||||||
|
layout: &Layout,
|
||||||
|
stmt: &Stmt,
|
||||||
|
) -> Result<ValueId> {
|
||||||
|
use Stmt::*;
|
||||||
|
|
||||||
|
match stmt {
|
||||||
|
Let(symbol, expr, layout, continuation) => {
|
||||||
|
let value_id = expr_spec(builder, env, block, layout, expr)?;
|
||||||
|
env.symbols.insert(*symbol, value_id);
|
||||||
|
let result = stmt_spec(builder, env, block, layout, continuation)?;
|
||||||
|
env.symbols.remove(symbol);
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
Invoke {
|
||||||
|
symbol,
|
||||||
|
call,
|
||||||
|
layout: call_layout,
|
||||||
|
pass,
|
||||||
|
fail,
|
||||||
|
} => {
|
||||||
|
// a call that might throw an exception
|
||||||
|
|
||||||
|
let value_id = call_spec(builder, env, block, call_layout, call)?;
|
||||||
|
|
||||||
|
let pass_block = builder.add_block();
|
||||||
|
env.symbols.insert(*symbol, value_id);
|
||||||
|
let pass_value_id = stmt_spec(builder, env, pass_block, layout, pass)?;
|
||||||
|
env.symbols.remove(symbol);
|
||||||
|
let pass_block_expr = BlockExpr(pass_block, pass_value_id);
|
||||||
|
|
||||||
|
let fail_block = builder.add_block();
|
||||||
|
let fail_value_id = stmt_spec(builder, env, fail_block, layout, fail)?;
|
||||||
|
let fail_block_expr = BlockExpr(fail_block, fail_value_id);
|
||||||
|
|
||||||
|
builder.add_choice(block, &[pass_block_expr, fail_block_expr])
|
||||||
|
}
|
||||||
|
Switch {
|
||||||
|
cond_symbol: _,
|
||||||
|
cond_layout: _,
|
||||||
|
branches,
|
||||||
|
default_branch,
|
||||||
|
ret_layout,
|
||||||
|
} => {
|
||||||
|
let mut cases = Vec::with_capacity(branches.len() + 1);
|
||||||
|
|
||||||
|
let it = branches
|
||||||
|
.iter()
|
||||||
|
.map(|(_, _, body)| body)
|
||||||
|
.chain(std::iter::once(default_branch.1));
|
||||||
|
|
||||||
|
for branch in it {
|
||||||
|
let block = builder.add_block();
|
||||||
|
let value_id = stmt_spec(builder, env, block, ret_layout, branch)?;
|
||||||
|
cases.push(BlockExpr(block, value_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.add_choice(block, &cases)
|
||||||
|
}
|
||||||
|
Ret(symbol) => Ok(env.symbols[symbol]),
|
||||||
|
Refcounting(modify_rc, continuation) => match modify_rc {
|
||||||
|
ModifyRc::Inc(symbol, _) | ModifyRc::Dec(symbol) | ModifyRc::DecRef(symbol) => {
|
||||||
|
let result_type = builder.add_tuple_type(&[])?;
|
||||||
|
let argument = env.symbols[symbol];
|
||||||
|
|
||||||
|
// this is how RC is modelled; it recursively touches all heap cells
|
||||||
|
builder.add_unknown_with(block, &[argument], result_type)?;
|
||||||
|
|
||||||
|
stmt_spec(builder, env, block, layout, continuation)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Join {
|
||||||
|
id,
|
||||||
|
parameters,
|
||||||
|
continuation,
|
||||||
|
remainder,
|
||||||
|
} => {
|
||||||
|
let mut type_ids = Vec::new();
|
||||||
|
|
||||||
|
for p in parameters.iter() {
|
||||||
|
type_ids.push(layout_spec(builder, &p.layout)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
let ret_type_id = layout_spec(builder, layout)?;
|
||||||
|
|
||||||
|
let jp_arg_type_id = builder.add_tuple_type(&type_ids)?;
|
||||||
|
|
||||||
|
let (jpid, jp_argument) =
|
||||||
|
builder.declare_join_point(block, jp_arg_type_id, ret_type_id)?;
|
||||||
|
|
||||||
|
let join_body_sub_block = {
|
||||||
|
env.join_points.insert(*id, jpid);
|
||||||
|
let jp_body_block = builder.add_block();
|
||||||
|
|
||||||
|
// unpack the argument
|
||||||
|
for (i, p) in parameters.iter().enumerate() {
|
||||||
|
let value_id =
|
||||||
|
builder.add_get_tuple_field(jp_body_block, jp_argument, i as u32)?;
|
||||||
|
env.symbols.insert(p.symbol, value_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
let jp_body_value_id = stmt_spec(builder, env, jp_body_block, layout, remainder)?;
|
||||||
|
BlockExpr(jp_body_block, jp_body_value_id)
|
||||||
|
};
|
||||||
|
|
||||||
|
// NOTE the symbols bound by the join point can shadow the argument symbols of the
|
||||||
|
// surrounding function, so we don't remove them from the env here
|
||||||
|
|
||||||
|
let cont_block = builder.add_block();
|
||||||
|
let cont_value_id = stmt_spec(builder, env, cont_block, layout, continuation)?;
|
||||||
|
|
||||||
|
env.join_points.remove(id);
|
||||||
|
builder.define_join_point(jpid, join_body_sub_block)?;
|
||||||
|
|
||||||
|
builder.add_sub_block(block, BlockExpr(cont_block, cont_value_id))
|
||||||
|
}
|
||||||
|
Jump(id, symbols) => {
|
||||||
|
let ret_type_id = layout_spec(builder, layout)?;
|
||||||
|
let argument = build_tuple_value(builder, env, block, symbols)?;
|
||||||
|
|
||||||
|
let jpid = env.join_points[id];
|
||||||
|
builder.add_jump(block, jpid, argument, ret_type_id)
|
||||||
|
}
|
||||||
|
Rethrow | RuntimeError(_) => {
|
||||||
|
let type_id = layout_spec(builder, layout)?;
|
||||||
|
|
||||||
|
builder.add_terminate(block, type_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_tuple_value(
|
||||||
|
builder: &mut FuncDefBuilder,
|
||||||
|
env: &Env,
|
||||||
|
block: BlockId,
|
||||||
|
symbols: &[Symbol],
|
||||||
|
) -> Result<ValueId> {
|
||||||
|
let mut value_ids = Vec::new();
|
||||||
|
|
||||||
|
for field in symbols.iter() {
|
||||||
|
let value_id = match env.symbols.get(field) {
|
||||||
|
None => panic!(
|
||||||
|
"Symbol {:?} is not defined in environment {:?}",
|
||||||
|
field, &env.symbols
|
||||||
|
),
|
||||||
|
Some(x) => *x,
|
||||||
|
};
|
||||||
|
value_ids.push(value_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.add_make_tuple(block, &value_ids)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_tuple_type(builder: &mut FuncDefBuilder, layouts: &[Layout]) -> Result<TypeId> {
|
||||||
|
let mut field_types = Vec::new();
|
||||||
|
|
||||||
|
for field in layouts.iter() {
|
||||||
|
field_types.push(layout_spec(builder, field)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.add_tuple_type(&field_types)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call_spec(
|
||||||
|
builder: &mut FuncDefBuilder,
|
||||||
|
env: &Env,
|
||||||
|
block: BlockId,
|
||||||
|
layout: &Layout,
|
||||||
|
call: &Call,
|
||||||
|
) -> Result<ValueId> {
|
||||||
|
use CallType::*;
|
||||||
|
|
||||||
|
match &call.call_type {
|
||||||
|
ByName {
|
||||||
|
name: symbol,
|
||||||
|
full_layout: _,
|
||||||
|
ret_layout: _,
|
||||||
|
arg_layouts: _,
|
||||||
|
specialization_id,
|
||||||
|
} => {
|
||||||
|
let array = specialization_id.to_bytes();
|
||||||
|
let spec_var = CalleeSpecVar(&array);
|
||||||
|
|
||||||
|
let arg_value_id = build_tuple_value(builder, env, block, call.arguments)?;
|
||||||
|
let slice = &symbol.to_ne_bytes();
|
||||||
|
let name = FuncName(slice);
|
||||||
|
let module = MOD_APP;
|
||||||
|
builder.add_call(block, spec_var, module, name, arg_value_id)
|
||||||
|
}
|
||||||
|
ByPointer {
|
||||||
|
name: _,
|
||||||
|
full_layout: _,
|
||||||
|
ret_layout: _,
|
||||||
|
arg_layouts: _,
|
||||||
|
} => todo!(),
|
||||||
|
Foreign {
|
||||||
|
foreign_symbol: _,
|
||||||
|
ret_layout,
|
||||||
|
} => {
|
||||||
|
let arguments: Vec<_> = call
|
||||||
|
.arguments
|
||||||
|
.iter()
|
||||||
|
.map(|symbol| env.symbols[symbol])
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let result_type = layout_spec(builder, ret_layout)?;
|
||||||
|
|
||||||
|
builder.add_unknown_with(block, &arguments, result_type)
|
||||||
|
}
|
||||||
|
LowLevel { op, update_mode } => lowlevel_spec(
|
||||||
|
builder,
|
||||||
|
env,
|
||||||
|
block,
|
||||||
|
layout,
|
||||||
|
op,
|
||||||
|
*update_mode,
|
||||||
|
call.arguments,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lowlevel_spec(
|
||||||
|
builder: &mut FuncDefBuilder,
|
||||||
|
env: &Env,
|
||||||
|
block: BlockId,
|
||||||
|
layout: &Layout,
|
||||||
|
op: &LowLevel,
|
||||||
|
update_mode: crate::ir::UpdateModeId,
|
||||||
|
arguments: &[Symbol],
|
||||||
|
) -> Result<ValueId> {
|
||||||
|
use LowLevel::*;
|
||||||
|
|
||||||
|
let type_id = layout_spec(builder, layout)?;
|
||||||
|
let mode = update_mode.to_bytes();
|
||||||
|
let update_mode_var = UpdateModeVar(&mode);
|
||||||
|
|
||||||
|
match op {
|
||||||
|
NumAdd | NumSub => {
|
||||||
|
// NOTE these numeric operations panic (e.g. on overflow)
|
||||||
|
|
||||||
|
let pass_block = {
|
||||||
|
let block = builder.add_block();
|
||||||
|
let value = new_num(builder, block)?;
|
||||||
|
BlockExpr(block, value)
|
||||||
|
};
|
||||||
|
|
||||||
|
let fail_block = {
|
||||||
|
let block = builder.add_block();
|
||||||
|
let value = builder.add_terminate(block, type_id)?;
|
||||||
|
BlockExpr(block, value)
|
||||||
|
};
|
||||||
|
|
||||||
|
let sub_block = {
|
||||||
|
let block = builder.add_block();
|
||||||
|
let choice = builder.add_choice(block, &[pass_block, fail_block])?;
|
||||||
|
|
||||||
|
BlockExpr(block, choice)
|
||||||
|
};
|
||||||
|
|
||||||
|
builder.add_sub_block(block, sub_block)
|
||||||
|
}
|
||||||
|
Eq | NotEq => new_bool(builder, block),
|
||||||
|
NumLte | NumLt | NumGt | NumGte => new_order(builder, block),
|
||||||
|
ListLen => {
|
||||||
|
let list = env.symbols[&arguments[0]];
|
||||||
|
|
||||||
|
builder.add_get_tuple_field(block, list, LIST_LEN_INDEX)
|
||||||
|
}
|
||||||
|
ListGetUnsafe => {
|
||||||
|
// NOTE the ListGet lowlevel op is only evaluated if the index is in-bounds
|
||||||
|
let list = env.symbols[&arguments[0]];
|
||||||
|
|
||||||
|
let bag = builder.add_get_tuple_field(block, list, LIST_BAG_INDEX)?;
|
||||||
|
let cell = builder.add_get_tuple_field(block, list, LIST_CELL_INDEX)?;
|
||||||
|
|
||||||
|
let _unit = builder.add_touch(block, cell)?;
|
||||||
|
|
||||||
|
builder.add_bag_get(block, bag)
|
||||||
|
}
|
||||||
|
ListSet => {
|
||||||
|
let list = env.symbols[&arguments[0]];
|
||||||
|
let to_insert = env.symbols[&arguments[2]];
|
||||||
|
|
||||||
|
let bag = builder.add_get_tuple_field(block, list, LIST_BAG_INDEX)?;
|
||||||
|
let cell = builder.add_get_tuple_field(block, list, LIST_CELL_INDEX)?;
|
||||||
|
|
||||||
|
let _unit = builder.add_update(block, update_mode_var, cell)?;
|
||||||
|
|
||||||
|
builder.add_bag_insert(block, bag, to_insert)?;
|
||||||
|
|
||||||
|
Ok(list)
|
||||||
|
}
|
||||||
|
other => todo!("lowlevel op not implemented: {:?}", other),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_variant_types(
|
||||||
|
builder: &mut FuncDefBuilder,
|
||||||
|
layout: &Layout,
|
||||||
|
) -> Option<Result<Vec<TypeId>>> {
|
||||||
|
match layout {
|
||||||
|
Layout::Union(union_layout) => Some(build_variant_types_help(builder, union_layout)),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_variant_types_help(
|
||||||
|
builder: &mut FuncDefBuilder,
|
||||||
|
union_layout: &UnionLayout,
|
||||||
|
) -> Result<Vec<TypeId>> {
|
||||||
|
use UnionLayout::*;
|
||||||
|
|
||||||
|
let mut result = Vec::new();
|
||||||
|
|
||||||
|
match union_layout {
|
||||||
|
NonRecursive(tags) => {
|
||||||
|
for tag in tags.iter() {
|
||||||
|
result.push(build_tuple_type(builder, tag)?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Recursive(_) => todo!(),
|
||||||
|
NonNullableUnwrapped(_) => todo!(),
|
||||||
|
NullableWrapped {
|
||||||
|
nullable_id: _,
|
||||||
|
other_tags: _,
|
||||||
|
} => todo!(),
|
||||||
|
NullableUnwrapped {
|
||||||
|
nullable_id: _,
|
||||||
|
other_fields: _,
|
||||||
|
} => todo!(),
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expr_spec(
|
||||||
|
builder: &mut FuncDefBuilder,
|
||||||
|
env: &Env,
|
||||||
|
block: BlockId,
|
||||||
|
layout: &Layout,
|
||||||
|
expr: &Expr,
|
||||||
|
) -> Result<ValueId> {
|
||||||
|
use Expr::*;
|
||||||
|
|
||||||
|
match expr {
|
||||||
|
Literal(literal) => literal_spec(builder, block, literal),
|
||||||
|
FunctionPointer(_, _) => todo!(),
|
||||||
|
Call(call) => call_spec(builder, env, block, layout, call),
|
||||||
|
Tag {
|
||||||
|
tag_layout,
|
||||||
|
tag_name: _,
|
||||||
|
tag_id,
|
||||||
|
union_size: _,
|
||||||
|
arguments,
|
||||||
|
} => {
|
||||||
|
let value_id = build_tuple_value(builder, env, block, arguments)?;
|
||||||
|
let variant_types = build_variant_types(builder, tag_layout).unwrap()?;
|
||||||
|
builder.add_make_union(block, &variant_types, *tag_id as u32, value_id)
|
||||||
|
}
|
||||||
|
Struct(fields) => build_tuple_value(builder, env, block, fields),
|
||||||
|
AccessAtIndex {
|
||||||
|
index,
|
||||||
|
field_layouts: _,
|
||||||
|
structure,
|
||||||
|
wrapped,
|
||||||
|
} => {
|
||||||
|
use crate::ir::Wrapped;
|
||||||
|
|
||||||
|
let value_id = env.symbols[structure];
|
||||||
|
|
||||||
|
match wrapped {
|
||||||
|
Wrapped::EmptyRecord => {
|
||||||
|
// this is a unit value
|
||||||
|
builder.add_make_tuple(block, &[])
|
||||||
|
}
|
||||||
|
Wrapped::SingleElementRecord => {
|
||||||
|
todo!("do we unwrap single-element records still?")
|
||||||
|
}
|
||||||
|
Wrapped::RecordOrSingleTagUnion => {
|
||||||
|
builder.add_get_tuple_field(block, value_id, *index as u32)
|
||||||
|
}
|
||||||
|
Wrapped::MultiTagUnion => {
|
||||||
|
builder.add_get_tuple_field(block, value_id, *index as u32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Array { elem_layout, elems } => {
|
||||||
|
let type_id = layout_spec(builder, elem_layout)?;
|
||||||
|
|
||||||
|
let list = new_list(builder, block, type_id)?;
|
||||||
|
|
||||||
|
let mut bag = builder.add_get_tuple_field(block, list, LIST_BAG_INDEX)?;
|
||||||
|
|
||||||
|
for symbol in elems.iter() {
|
||||||
|
let value_id = env.symbols[symbol];
|
||||||
|
|
||||||
|
bag = builder.add_bag_insert(block, bag, value_id)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(bag)
|
||||||
|
}
|
||||||
|
|
||||||
|
EmptyArray => {
|
||||||
|
use ListLayout::*;
|
||||||
|
|
||||||
|
match ListLayout::try_from(layout) {
|
||||||
|
Ok(EmptyList) => {
|
||||||
|
// just make up an element type
|
||||||
|
let type_id = builder.add_tuple_type(&[])?;
|
||||||
|
new_list(builder, block, type_id)
|
||||||
|
}
|
||||||
|
Ok(List(element_layout)) => {
|
||||||
|
let type_id = layout_spec(builder, element_layout)?;
|
||||||
|
new_list(builder, block, type_id)
|
||||||
|
}
|
||||||
|
Err(()) => unreachable!("empty array does not have a list layout"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reuse { .. } => todo!("currently unused"),
|
||||||
|
Reset(_) => todo!("currently unused"),
|
||||||
|
RuntimeErrorFunction(_) => {
|
||||||
|
let type_id = layout_spec(builder, layout)?;
|
||||||
|
|
||||||
|
builder.add_terminate(block, type_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn literal_spec(
|
||||||
|
builder: &mut FuncDefBuilder,
|
||||||
|
block: BlockId,
|
||||||
|
literal: &Literal,
|
||||||
|
) -> Result<ValueId> {
|
||||||
|
use Literal::*;
|
||||||
|
|
||||||
|
match literal {
|
||||||
|
Str(_) => new_static_string(builder, block),
|
||||||
|
Int(_) | Float(_) | Bool(_) | Byte(_) => builder.add_make_tuple(block, &[]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn layout_spec(builder: &mut FuncDefBuilder, layout: &Layout) -> Result<TypeId> {
|
||||||
|
use Layout::*;
|
||||||
|
|
||||||
|
match layout {
|
||||||
|
Builtin(builtin) => builtin_spec(builder, builtin),
|
||||||
|
PhantomEmptyStruct => todo!(),
|
||||||
|
Struct(fields) => build_tuple_type(builder, fields),
|
||||||
|
Union(union_layout) => {
|
||||||
|
let variant_types = build_variant_types_help(builder, union_layout)?;
|
||||||
|
builder.add_union_type(&variant_types)
|
||||||
|
}
|
||||||
|
RecursivePointer => todo!(),
|
||||||
|
FunctionPointer(_, _) => todo!(),
|
||||||
|
Closure(_, _, _) => todo!(),
|
||||||
|
Pointer(_) => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn builtin_spec(builder: &mut FuncDefBuilder, builtin: &Builtin) -> Result<TypeId> {
|
||||||
|
use Builtin::*;
|
||||||
|
|
||||||
|
match builtin {
|
||||||
|
Int128 | Int64 | Int32 | Int16 | Int8 | Int1 | Usize => builder.add_tuple_type(&[]),
|
||||||
|
Float128 => todo!(),
|
||||||
|
Float64 => todo!(),
|
||||||
|
Float32 => todo!(),
|
||||||
|
Float16 => todo!(),
|
||||||
|
Str => todo!(),
|
||||||
|
Dict(_, _) => todo!(),
|
||||||
|
Set(_) => todo!(),
|
||||||
|
List(_, _) => {
|
||||||
|
// TODO should incorporate the element type into the name
|
||||||
|
Ok(builder.add_named_type(MOD_LIST, TypeName(b"List")))
|
||||||
|
}
|
||||||
|
EmptyStr => todo!(),
|
||||||
|
EmptyList => todo!(),
|
||||||
|
EmptyDict => todo!(),
|
||||||
|
EmptySet => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// const OK_TAG_ID: u8 = 1u8;
|
||||||
|
// const ERR_TAG_ID: u8 = 0u8;
|
||||||
|
|
||||||
|
const LIST_CELL_INDEX: u32 = 0;
|
||||||
|
const LIST_BAG_INDEX: u32 = 1;
|
||||||
|
const LIST_LEN_INDEX: u32 = 2;
|
||||||
|
|
||||||
|
fn new_list(builder: &mut FuncDefBuilder, block: BlockId, element_type: TypeId) -> Result<ValueId> {
|
||||||
|
let cell = builder.add_new_heap_cell(block)?;
|
||||||
|
let bag = builder.add_empty_bag(block, element_type)?;
|
||||||
|
let length = new_usize(builder, block)?;
|
||||||
|
builder.add_make_tuple(block, &[cell, bag, length])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_usize(builder: &mut FuncDefBuilder, block: BlockId) -> Result<ValueId> {
|
||||||
|
new_num(builder, block)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_static_string(builder: &mut FuncDefBuilder, block: BlockId) -> Result<ValueId> {
|
||||||
|
let cell = builder.add_new_heap_cell(block)?;
|
||||||
|
|
||||||
|
// immediately mutate the cell, so any future updates on this value are invalid
|
||||||
|
// updating a static string would cause a crash at runtime
|
||||||
|
let _ = builder.add_update(block, UpdateModeVar(&[]), cell)?;
|
||||||
|
|
||||||
|
let length = new_usize(builder, block)?;
|
||||||
|
builder.add_make_tuple(block, &[cell, length])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_order(builder: &mut FuncDefBuilder, block: BlockId) -> Result<ValueId> {
|
||||||
|
// always generats EQ
|
||||||
|
let tag_id = 0;
|
||||||
|
|
||||||
|
let unit = builder.add_tuple_type(&[])?;
|
||||||
|
let unit_value = builder.add_make_tuple(block, &[])?;
|
||||||
|
builder.add_make_union(block, &[unit, unit, unit], tag_id, unit_value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_bool(builder: &mut FuncDefBuilder, block: BlockId) -> Result<ValueId> {
|
||||||
|
// always generats False
|
||||||
|
let tag_id = 0;
|
||||||
|
|
||||||
|
let unit = builder.add_tuple_type(&[])?;
|
||||||
|
let unit_value = builder.add_make_tuple(block, &[])?;
|
||||||
|
builder.add_make_union(block, &[unit, unit], tag_id, unit_value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_num(builder: &mut FuncDefBuilder, block: BlockId) -> Result<ValueId> {
|
||||||
|
// we model all our numbers as unit values
|
||||||
|
builder.add_make_tuple(block, &[])
|
||||||
|
}
|
|
@ -402,7 +402,7 @@ impl<'a> BorrowInfState<'a> {
|
||||||
self.own_args(arguments);
|
self.own_args(arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
LowLevel { op } => {
|
LowLevel { op, .. } => {
|
||||||
// very unsure what demand RunLowLevel should place upon its arguments
|
// very unsure what demand RunLowLevel should place upon its arguments
|
||||||
self.own_var(z);
|
self.own_var(z);
|
||||||
|
|
||||||
|
|
|
@ -1404,8 +1404,12 @@ fn compile_test_help<'a>(
|
||||||
default_branch,
|
default_branch,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let op = LowLevel::Eq;
|
||||||
let test = Expr::Call(crate::ir::Call {
|
let test = Expr::Call(crate::ir::Call {
|
||||||
call_type: crate::ir::CallType::LowLevel { op: LowLevel::Eq },
|
call_type: crate::ir::CallType::LowLevel {
|
||||||
|
op,
|
||||||
|
update_mode: env.next_update_mode_id(),
|
||||||
|
},
|
||||||
arguments: arena.alloc([lhs, rhs]),
|
arguments: arena.alloc([lhs, rhs]),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -442,7 +442,7 @@ impl<'a> Context<'a> {
|
||||||
use crate::ir::CallType::*;
|
use crate::ir::CallType::*;
|
||||||
|
|
||||||
match &call_type {
|
match &call_type {
|
||||||
LowLevel { op } => {
|
LowLevel { op, .. } => {
|
||||||
let ps = crate::borrow::lowlevel_borrow_signature(self.arena, *op);
|
let ps = crate::borrow::lowlevel_borrow_signature(self.arena, *op);
|
||||||
let b = self.add_dec_after_lowlevel(arguments, ps, b, b_live_vars);
|
let b = self.add_dec_after_lowlevel(arguments, ps, b, b_live_vars);
|
||||||
|
|
||||||
|
@ -768,7 +768,7 @@ impl<'a> Context<'a> {
|
||||||
|
|
||||||
use crate::ir::CallType;
|
use crate::ir::CallType;
|
||||||
let stmt = match &call.call_type {
|
let stmt = match &call.call_type {
|
||||||
CallType::LowLevel { op } => {
|
CallType::LowLevel { op, .. } => {
|
||||||
let ps = crate::borrow::lowlevel_borrow_signature(self.arena, *op);
|
let ps = crate::borrow::lowlevel_borrow_signature(self.arena, *op);
|
||||||
self.add_dec_after_lowlevel(call.arguments, ps, cont, &case_live_vars)
|
self.add_dec_after_lowlevel(call.arguments, ps, cont, &case_live_vars)
|
||||||
}
|
}
|
||||||
|
|
|
@ -735,6 +735,8 @@ pub struct Env<'a, 'i> {
|
||||||
pub home: ModuleId,
|
pub home: ModuleId,
|
||||||
pub ident_ids: &'i mut IdentIds,
|
pub ident_ids: &'i mut IdentIds,
|
||||||
pub ptr_bytes: u32,
|
pub ptr_bytes: u32,
|
||||||
|
pub update_mode_counter: u64,
|
||||||
|
pub call_specialization_counter: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'i> Env<'a, 'i> {
|
impl<'a, 'i> Env<'a, 'i> {
|
||||||
|
@ -746,6 +748,26 @@ impl<'a, 'i> Env<'a, 'i> {
|
||||||
Symbol::new(self.home, ident_id)
|
Symbol::new(self.home, ident_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn next_update_mode_id(&mut self) -> UpdateModeId {
|
||||||
|
let id = UpdateModeId {
|
||||||
|
id: self.update_mode_counter,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.update_mode_counter += 1;
|
||||||
|
|
||||||
|
id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next_call_specialization_id(&mut self) -> CallSpecId {
|
||||||
|
let id = CallSpecId {
|
||||||
|
id: self.call_specialization_counter,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.call_specialization_counter += 1;
|
||||||
|
|
||||||
|
id
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_imported_symbol(&self, symbol: Symbol) -> bool {
|
pub fn is_imported_symbol(&self, symbol: Symbol) -> bool {
|
||||||
symbol.module_id() != self.home && !symbol.is_builtin()
|
symbol.module_id() != self.home && !symbol.is_builtin()
|
||||||
}
|
}
|
||||||
|
@ -1004,7 +1026,7 @@ impl<'a> Call<'a> {
|
||||||
.text("CallByPointer ")
|
.text("CallByPointer ")
|
||||||
.append(alloc.intersperse(it, " "))
|
.append(alloc.intersperse(it, " "))
|
||||||
}
|
}
|
||||||
LowLevel { op: lowlevel } => {
|
LowLevel { op: lowlevel, .. } => {
|
||||||
let it = arguments.iter().map(|s| symbol_to_doc(alloc, *s));
|
let it = arguments.iter().map(|s| symbol_to_doc(alloc, *s));
|
||||||
|
|
||||||
alloc
|
alloc
|
||||||
|
@ -1024,18 +1046,39 @@ impl<'a> Call<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
pub struct CallSpecId {
|
||||||
|
id: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CallSpecId {
|
||||||
|
pub fn to_bytes(self) -> [u8; 8] {
|
||||||
|
self.id.to_ne_bytes()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
pub struct UpdateModeId {
|
||||||
|
id: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UpdateModeId {
|
||||||
|
pub fn to_bytes(self) -> [u8; 8] {
|
||||||
|
self.id.to_ne_bytes()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum CallType<'a> {
|
pub enum CallType<'a> {
|
||||||
ByName {
|
ByName {
|
||||||
name: Symbol,
|
name: Symbol,
|
||||||
|
|
||||||
full_layout: Layout<'a>,
|
full_layout: Layout<'a>,
|
||||||
ret_layout: Layout<'a>,
|
ret_layout: Layout<'a>,
|
||||||
arg_layouts: &'a [Layout<'a>],
|
arg_layouts: &'a [Layout<'a>],
|
||||||
|
specialization_id: CallSpecId,
|
||||||
},
|
},
|
||||||
ByPointer {
|
ByPointer {
|
||||||
name: Symbol,
|
name: Symbol,
|
||||||
|
|
||||||
full_layout: Layout<'a>,
|
full_layout: Layout<'a>,
|
||||||
ret_layout: Layout<'a>,
|
ret_layout: Layout<'a>,
|
||||||
arg_layouts: &'a [Layout<'a>],
|
arg_layouts: &'a [Layout<'a>],
|
||||||
|
@ -1046,6 +1089,7 @@ pub enum CallType<'a> {
|
||||||
},
|
},
|
||||||
LowLevel {
|
LowLevel {
|
||||||
op: LowLevel,
|
op: LowLevel,
|
||||||
|
update_mode: UpdateModeId,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4168,7 +4212,10 @@ pub fn with_hole<'a>(
|
||||||
return_on_layout_error!(env, layout_cache.from_var(env.arena, ret_var, env.subs));
|
return_on_layout_error!(env, layout_cache.from_var(env.arena, ret_var, env.subs));
|
||||||
|
|
||||||
let call = self::Call {
|
let call = self::Call {
|
||||||
call_type: CallType::LowLevel { op },
|
call_type: CallType::LowLevel {
|
||||||
|
op,
|
||||||
|
update_mode: env.next_update_mode_id(),
|
||||||
|
},
|
||||||
arguments: arg_symbols,
|
arguments: arg_symbols,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4316,8 +4363,10 @@ pub fn from_can<'a>(
|
||||||
let bool_layout = Layout::Builtin(Builtin::Int1);
|
let bool_layout = Layout::Builtin(Builtin::Int1);
|
||||||
let cond_symbol = env.unique_symbol();
|
let cond_symbol = env.unique_symbol();
|
||||||
|
|
||||||
|
let op = LowLevel::ExpectTrue;
|
||||||
let call_type = CallType::LowLevel {
|
let call_type = CallType::LowLevel {
|
||||||
op: LowLevel::ExpectTrue,
|
op,
|
||||||
|
update_mode: env.next_update_mode_id(),
|
||||||
};
|
};
|
||||||
let arguments = env.arena.alloc([cond_symbol]);
|
let arguments = env.arena.alloc([cond_symbol]);
|
||||||
let call = self::Call {
|
let call = self::Call {
|
||||||
|
@ -5054,11 +5103,13 @@ fn substitute_in_call<'a>(
|
||||||
arg_layouts,
|
arg_layouts,
|
||||||
ret_layout,
|
ret_layout,
|
||||||
full_layout,
|
full_layout,
|
||||||
|
specialization_id,
|
||||||
} => substitute(subs, *name).map(|new| CallType::ByName {
|
} => substitute(subs, *name).map(|new| CallType::ByName {
|
||||||
name: new,
|
name: new,
|
||||||
arg_layouts,
|
arg_layouts,
|
||||||
ret_layout: *ret_layout,
|
ret_layout: *ret_layout,
|
||||||
full_layout: *full_layout,
|
full_layout: *full_layout,
|
||||||
|
specialization_id: *specialization_id,
|
||||||
}),
|
}),
|
||||||
CallType::ByPointer {
|
CallType::ByPointer {
|
||||||
name,
|
name,
|
||||||
|
@ -5840,6 +5891,7 @@ fn call_by_pointer<'a>(
|
||||||
full_layout: layout,
|
full_layout: layout,
|
||||||
ret_layout: *ret_layout,
|
ret_layout: *ret_layout,
|
||||||
arg_layouts,
|
arg_layouts,
|
||||||
|
specialization_id: env.next_call_specialization_id(),
|
||||||
};
|
};
|
||||||
let call = Call {
|
let call = Call {
|
||||||
call_type,
|
call_type,
|
||||||
|
@ -6098,6 +6150,7 @@ fn call_by_name<'a>(
|
||||||
ret_layout: *ret_layout,
|
ret_layout: *ret_layout,
|
||||||
full_layout,
|
full_layout,
|
||||||
arg_layouts,
|
arg_layouts,
|
||||||
|
specialization_id: env.next_call_specialization_id(),
|
||||||
},
|
},
|
||||||
arguments: field_symbols,
|
arguments: field_symbols,
|
||||||
};
|
};
|
||||||
|
@ -6142,6 +6195,7 @@ fn call_by_name<'a>(
|
||||||
ret_layout: *ret_layout,
|
ret_layout: *ret_layout,
|
||||||
full_layout,
|
full_layout,
|
||||||
arg_layouts,
|
arg_layouts,
|
||||||
|
specialization_id: env.next_call_specialization_id(),
|
||||||
},
|
},
|
||||||
arguments: field_symbols,
|
arguments: field_symbols,
|
||||||
};
|
};
|
||||||
|
@ -6248,6 +6302,7 @@ fn call_by_name<'a>(
|
||||||
ret_layout: *ret_layout,
|
ret_layout: *ret_layout,
|
||||||
full_layout,
|
full_layout,
|
||||||
arg_layouts,
|
arg_layouts,
|
||||||
|
specialization_id: env.next_call_specialization_id(),
|
||||||
},
|
},
|
||||||
arguments: field_symbols,
|
arguments: field_symbols,
|
||||||
}
|
}
|
||||||
|
@ -6311,6 +6366,7 @@ fn call_specialized_proc<'a>(
|
||||||
ret_layout: function_layout.result,
|
ret_layout: function_layout.result,
|
||||||
full_layout: function_layout.full,
|
full_layout: function_layout.full,
|
||||||
arg_layouts: function_layout.arguments,
|
arg_layouts: function_layout.arguments,
|
||||||
|
specialization_id: env.next_call_specialization_id(),
|
||||||
},
|
},
|
||||||
arguments: field_symbols,
|
arguments: field_symbols,
|
||||||
};
|
};
|
||||||
|
@ -6332,6 +6388,7 @@ fn call_specialized_proc<'a>(
|
||||||
ret_layout: function_layout.result,
|
ret_layout: function_layout.result,
|
||||||
full_layout: function_layout.full,
|
full_layout: function_layout.full,
|
||||||
arg_layouts: function_layout.arguments,
|
arg_layouts: function_layout.arguments,
|
||||||
|
specialization_id: env.next_call_specialization_id(),
|
||||||
},
|
},
|
||||||
arguments: field_symbols,
|
arguments: field_symbols,
|
||||||
};
|
};
|
||||||
|
@ -6351,6 +6408,7 @@ fn call_specialized_proc<'a>(
|
||||||
ret_layout: function_layout.result,
|
ret_layout: function_layout.result,
|
||||||
full_layout: function_layout.full,
|
full_layout: function_layout.full,
|
||||||
arg_layouts: function_layout.arguments,
|
arg_layouts: function_layout.arguments,
|
||||||
|
specialization_id: env.next_call_specialization_id(),
|
||||||
},
|
},
|
||||||
arguments: field_symbols,
|
arguments: field_symbols,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1980,3 +1980,21 @@ impl<'a> LayoutIds<'a> {
|
||||||
LayoutId(answer)
|
LayoutId(answer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub enum ListLayout<'a> {
|
||||||
|
EmptyList,
|
||||||
|
List(&'a Layout<'a>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> std::convert::TryFrom<&Layout<'a>> for ListLayout<'a> {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_from(value: &Layout<'a>) -> Result<Self, Self::Error> {
|
||||||
|
match value {
|
||||||
|
Layout::Builtin(Builtin::EmptyList) => Ok(ListLayout::EmptyList),
|
||||||
|
Layout::Builtin(Builtin::List(_, element)) => Ok(ListLayout::List(element)),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check.
|
// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check.
|
||||||
#![allow(clippy::large_enum_variant, clippy::upper_case_acronyms)]
|
#![allow(clippy::large_enum_variant, clippy::upper_case_acronyms)]
|
||||||
|
|
||||||
|
pub mod alias_analysis;
|
||||||
pub mod borrow;
|
pub mod borrow;
|
||||||
pub mod expand_rc;
|
pub mod expand_rc;
|
||||||
pub mod inc_dec;
|
pub mod inc_dec;
|
||||||
|
|
|
@ -100,6 +100,8 @@ mod test_reporting {
|
||||||
home,
|
home,
|
||||||
ident_ids: &mut ident_ids,
|
ident_ids: &mut ident_ids,
|
||||||
ptr_bytes: 8,
|
ptr_bytes: 8,
|
||||||
|
update_mode_counter: 0,
|
||||||
|
call_specialization_counter: 0,
|
||||||
};
|
};
|
||||||
let _mono_expr = Stmt::new(
|
let _mono_expr = Stmt::new(
|
||||||
&mut mono_env,
|
&mut mono_env,
|
||||||
|
|
|
@ -4,9 +4,11 @@ app "quicksort"
|
||||||
provides [ quicksort ] to base
|
provides [ quicksort ] to base
|
||||||
|
|
||||||
quicksort = \originalList ->
|
quicksort = \originalList ->
|
||||||
|
n = List.len originalList
|
||||||
|
quicksortHelp originalList 0 (n - 1)
|
||||||
|
|
||||||
quicksortHelp : List (Num a), Nat, Nat -> List (Num a)
|
quicksortHelp : List (Num a), Nat, Nat -> List (Num a)
|
||||||
quicksortHelp = \list, low, high ->
|
quicksortHelp = \list, low, high ->
|
||||||
if low < high then
|
if low < high then
|
||||||
when partition low high list is
|
when partition low high list is
|
||||||
Pair partitionIndex partitioned ->
|
Pair partitionIndex partitioned ->
|
||||||
|
@ -17,8 +19,8 @@ quicksort = \originalList ->
|
||||||
list
|
list
|
||||||
|
|
||||||
|
|
||||||
partition : Nat, Nat, List (Num a) -> [ Pair Nat (List (Num a)) ]
|
partition : Nat, Nat, List (Num a) -> [ Pair Nat (List (Num a)) ]
|
||||||
partition = \low, high, initialList ->
|
partition = \low, high, initialList ->
|
||||||
when List.get initialList high is
|
when List.get initialList high is
|
||||||
Ok pivot ->
|
Ok pivot ->
|
||||||
when partitionHelp (low - 1) low initialList high pivot is
|
when partitionHelp (low - 1) low initialList high pivot is
|
||||||
|
@ -28,8 +30,8 @@ quicksort = \originalList ->
|
||||||
Err _ ->
|
Err _ ->
|
||||||
Pair (low - 1) initialList
|
Pair (low - 1) initialList
|
||||||
|
|
||||||
partitionHelp : Nat, Nat, List (Num c), Nat, (Num c) -> [ Pair Nat (List (Num c)) ]
|
partitionHelp : Nat, Nat, List (Num c), Nat, (Num c) -> [ Pair Nat (List (Num c)) ]
|
||||||
partitionHelp = \i, j, list, high, pivot ->
|
partitionHelp = \i, j, list, high, pivot ->
|
||||||
if j < high then
|
if j < high then
|
||||||
when List.get list j is
|
when List.get list j is
|
||||||
Ok value ->
|
Ok value ->
|
||||||
|
@ -44,8 +46,8 @@ quicksort = \originalList ->
|
||||||
Pair i list
|
Pair i list
|
||||||
|
|
||||||
|
|
||||||
swap : Nat, Nat, List a -> List a
|
swap : Nat, Nat, List a -> List a
|
||||||
swap = \i, j, list ->
|
swap = \i, j, list ->
|
||||||
when Pair (List.get list i) (List.get list j) is
|
when Pair (List.get list i) (List.get list j) is
|
||||||
Pair (Ok atI) (Ok atJ) ->
|
Pair (Ok atI) (Ok atJ) ->
|
||||||
list
|
list
|
||||||
|
@ -55,5 +57,3 @@ quicksort = \originalList ->
|
||||||
_ ->
|
_ ->
|
||||||
[]
|
[]
|
||||||
|
|
||||||
n = List.len originalList
|
|
||||||
quicksortHelp originalList 0 (n - 1)
|
|
||||||
|
|
2
vendor/morphic_lib/.gitignore
vendored
Normal file
2
vendor/morphic_lib/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/target
|
||||||
|
Cargo.lock
|
9
vendor/morphic_lib/Cargo.toml
vendored
Normal file
9
vendor/morphic_lib/Cargo.toml
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[package]
|
||||||
|
name = "morphic_lib"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["William Brandon", "Wilson Berkow", "Frank Dai", "Benjamin Driscoll"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
thiserror = "1.0.24"
|
||||||
|
sha2 = "0.9.4"
|
176
vendor/morphic_lib/LICENSE-APACHE
vendored
Normal file
176
vendor/morphic_lib/LICENSE-APACHE
vendored
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
23
vendor/morphic_lib/LICENSE-MIT
vendored
Normal file
23
vendor/morphic_lib/LICENSE-MIT
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
Permission is hereby granted, free of charge, to any
|
||||||
|
person obtaining a copy of this software and associated
|
||||||
|
documentation files (the "Software"), to deal in the
|
||||||
|
Software without restriction, including without
|
||||||
|
limitation the rights to use, copy, modify, merge,
|
||||||
|
publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software
|
||||||
|
is furnished to do so, subject to the following
|
||||||
|
conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice
|
||||||
|
shall be included in all copies or substantial portions
|
||||||
|
of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||||
|
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||||
|
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||||
|
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||||
|
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
1325
vendor/morphic_lib/src/api.rs
vendored
Normal file
1325
vendor/morphic_lib/src/api.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
706
vendor/morphic_lib/src/bindings.rs
vendored
Normal file
706
vendor/morphic_lib/src/bindings.rs
vendored
Normal file
|
@ -0,0 +1,706 @@
|
||||||
|
// TODO: These bindings are incomplete
|
||||||
|
// TODO: Add test for compatibility with `include/morphic.h`
|
||||||
|
|
||||||
|
use crate::api::*;
|
||||||
|
use std::{ffi::CString, os::raw::c_char, ptr, slice};
|
||||||
|
|
||||||
|
macro_rules! check_err {
|
||||||
|
($expr:expr) => {
|
||||||
|
match $expr {
|
||||||
|
::std::result::Result::Ok(val) => val,
|
||||||
|
::std::result::Result::Err(err) => {
|
||||||
|
return ::std::boxed::Box::into_raw(::std::boxed::Box::new(err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct RawModName {
|
||||||
|
data: *mut u8,
|
||||||
|
len: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RawModName {
|
||||||
|
unsafe fn slice<'a>(&self) -> ModName<'a> {
|
||||||
|
ModName(slice::from_raw_parts(self.data, self.len))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct RawEntryPointName {
|
||||||
|
data: *mut u8,
|
||||||
|
len: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RawEntryPointName {
|
||||||
|
unsafe fn slice<'a>(&self) -> EntryPointName<'a> {
|
||||||
|
EntryPointName(slice::from_raw_parts(self.data, self.len))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct RawFuncName {
|
||||||
|
data: *mut u8,
|
||||||
|
len: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RawFuncName {
|
||||||
|
unsafe fn slice<'a>(&self) -> FuncName<'a> {
|
||||||
|
FuncName(slice::from_raw_parts(self.data, self.len))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct RawTypeName {
|
||||||
|
data: *mut u8,
|
||||||
|
len: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RawTypeName {
|
||||||
|
unsafe fn slice<'a>(&self) -> TypeName<'a> {
|
||||||
|
TypeName(slice::from_raw_parts(self.data, self.len))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct RawCalleeSpecVar {
|
||||||
|
data: *mut u8,
|
||||||
|
len: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RawCalleeSpecVar {
|
||||||
|
unsafe fn slice<'a>(&self) -> CalleeSpecVar<'a> {
|
||||||
|
CalleeSpecVar(slice::from_raw_parts(self.data, self.len))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct RawUpdateModeVar {
|
||||||
|
data: *mut u8,
|
||||||
|
len: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RawUpdateModeVar {
|
||||||
|
unsafe fn slice<'a>(&self) -> UpdateModeVar<'a> {
|
||||||
|
UpdateModeVar(slice::from_raw_parts(self.data, self.len))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct RawString {
|
||||||
|
data: *mut c_char,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RawString {
|
||||||
|
fn new<T: Into<Vec<u8>>>(t: T) -> Self {
|
||||||
|
let c_str = CString::new(t).unwrap();
|
||||||
|
Self {
|
||||||
|
data: c_str.into_raw(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn raw<T>(t: T) -> *mut T {
|
||||||
|
Box::into_raw(Box::new(t))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_String_Drop(_: Option<Box<RawString>>) {}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_Error_Clone(err: &Error) -> Box<Error> {
|
||||||
|
Box::new(err.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_Error_Drop(_: Option<Box<Error>>) {}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_Error_Display(self_: *const Error, out: *mut RawString) {
|
||||||
|
*out = RawString::new(format!("{}", *self_));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_TypeDef_Drop(_: Option<Box<TypeDef>>) {}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_TypeDefBuilder_Drop(_: Option<Box<TypeDefBuilder>>) {}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_TypeDefBuilder_New(out: *mut *mut TypeDefBuilder) {
|
||||||
|
*out = raw(TypeDefBuilder::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_TypeDefBuilder_Build(
|
||||||
|
self_: Box<TypeDefBuilder>,
|
||||||
|
root: TypeId,
|
||||||
|
out: *mut *mut TypeDef,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = raw(check_err!(self_.build(root)));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_TypeDefBuilder_AddNamedType(
|
||||||
|
self_: *mut TypeDefBuilder,
|
||||||
|
mod_: RawModName,
|
||||||
|
type_: RawTypeName,
|
||||||
|
out: *mut TypeId,
|
||||||
|
) {
|
||||||
|
*out = (*self_).add_named_type(mod_.slice(), type_.slice());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_TypeDefBuilder_AddTupleType(
|
||||||
|
self_: *mut TypeDefBuilder,
|
||||||
|
field_types: *const TypeId,
|
||||||
|
field_types_len: usize,
|
||||||
|
out: *mut TypeId,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = check_err!((*self_).add_tuple_type(slice::from_raw_parts(field_types, field_types_len)));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_TypeDefBuilder_AddUnionType(
|
||||||
|
self_: *mut TypeDefBuilder,
|
||||||
|
variant_types: *const TypeId,
|
||||||
|
variant_types_len: usize,
|
||||||
|
out: *mut TypeId,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = check_err!(
|
||||||
|
(*self_).add_union_type(slice::from_raw_parts(variant_types, variant_types_len))
|
||||||
|
);
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_TypeDefBuilder_AddHeapCellType(
|
||||||
|
self_: *mut TypeDefBuilder,
|
||||||
|
out: *mut TypeId,
|
||||||
|
) {
|
||||||
|
*out = (*self_).add_heap_cell_type();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_TypeDefBuilder_AddBagType(
|
||||||
|
self_: *mut TypeDefBuilder,
|
||||||
|
item_type: TypeId,
|
||||||
|
out: *mut TypeId,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = check_err!((*self_).add_bag_type(item_type));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDef_Drop(_: Option<Box<FuncDef>>) {}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_Drop(_: Option<Box<FuncDefBuilder>>) {}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_New(out: *mut *mut FuncDefBuilder) {
|
||||||
|
*out = raw(FuncDefBuilder::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_Build(
|
||||||
|
self_: Box<FuncDefBuilder>,
|
||||||
|
arg_type: TypeId,
|
||||||
|
ret_type: TypeId,
|
||||||
|
root: BlockExpr,
|
||||||
|
out: *mut *mut FuncDef,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = raw(check_err!(self_.build(arg_type, ret_type, root)));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_DeclareJoinPoint(
|
||||||
|
self_: *mut FuncDefBuilder,
|
||||||
|
block: BlockId,
|
||||||
|
arg_type: TypeId,
|
||||||
|
ret_type: TypeId,
|
||||||
|
out0: *mut JoinPointId,
|
||||||
|
out1: *mut ValueId,
|
||||||
|
) -> *mut Error {
|
||||||
|
let (join_point, value) = check_err!((*self_).declare_join_point(block, arg_type, ret_type));
|
||||||
|
*out0 = join_point;
|
||||||
|
*out1 = value;
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_DefineJoinPoint(
|
||||||
|
self_: *mut FuncDefBuilder,
|
||||||
|
join_point: JoinPointId,
|
||||||
|
body: BlockExpr,
|
||||||
|
) -> *mut Error {
|
||||||
|
check_err!((*self_).define_join_point(join_point, body));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_AddJump(
|
||||||
|
self_: *mut FuncDefBuilder,
|
||||||
|
block: BlockId,
|
||||||
|
join_point: JoinPointId,
|
||||||
|
arg: ValueId,
|
||||||
|
unreachable_result_type: TypeId,
|
||||||
|
out: *mut ValueId,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = check_err!((*self_).add_jump(block, join_point, arg, unreachable_result_type));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_AddBlock(
|
||||||
|
self_: *mut FuncDefBuilder,
|
||||||
|
out: *mut BlockId,
|
||||||
|
) {
|
||||||
|
*out = (*self_).add_block();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_AddUnknownWith(
|
||||||
|
self_: *mut FuncDefBuilder,
|
||||||
|
block: BlockId,
|
||||||
|
args: *const ValueId,
|
||||||
|
args_len: usize,
|
||||||
|
result_type: TypeId,
|
||||||
|
out: *mut ValueId,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = check_err!((*self_).add_unknown_with(
|
||||||
|
block,
|
||||||
|
slice::from_raw_parts(args, args_len),
|
||||||
|
result_type
|
||||||
|
));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_AddCall(
|
||||||
|
self_: *mut FuncDefBuilder,
|
||||||
|
block: BlockId,
|
||||||
|
callee_spec_var: RawCalleeSpecVar,
|
||||||
|
callee_mod: RawModName,
|
||||||
|
callee: RawFuncName,
|
||||||
|
arg: ValueId,
|
||||||
|
) -> *mut Error {
|
||||||
|
check_err!((*self_).add_call(
|
||||||
|
block,
|
||||||
|
callee_spec_var.slice(),
|
||||||
|
callee_mod.slice(),
|
||||||
|
callee.slice(),
|
||||||
|
arg
|
||||||
|
));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_AddChoice(
|
||||||
|
self_: *mut FuncDefBuilder,
|
||||||
|
block: BlockId,
|
||||||
|
cases: *const BlockExpr,
|
||||||
|
cases_len: usize,
|
||||||
|
out: *mut ValueId,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = check_err!((*self_).add_choice(block, slice::from_raw_parts(cases, cases_len)));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_AddTerminate(
|
||||||
|
self_: *mut FuncDefBuilder,
|
||||||
|
block: BlockId,
|
||||||
|
result_type: TypeId,
|
||||||
|
out: *mut ValueId,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = check_err!((*self_).add_terminate(block, result_type));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_AddNewHeapCell(
|
||||||
|
self_: *mut FuncDefBuilder,
|
||||||
|
block: BlockId,
|
||||||
|
out: *mut ValueId,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = check_err!((*self_).add_new_heap_cell(block));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_AddTouch(
|
||||||
|
self_: *mut FuncDefBuilder,
|
||||||
|
block: BlockId,
|
||||||
|
heap_cell: ValueId,
|
||||||
|
out: *mut ValueId,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = check_err!((*self_).add_touch(block, heap_cell));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_AddUpdate(
|
||||||
|
self_: *mut FuncDefBuilder,
|
||||||
|
block: BlockId,
|
||||||
|
update_mode_var: RawUpdateModeVar,
|
||||||
|
heap_cell: ValueId,
|
||||||
|
out: *mut ValueId,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = check_err!((*self_).add_update(block, update_mode_var.slice(), heap_cell));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_AddUpdateWriteOnly(
|
||||||
|
self_: *mut FuncDefBuilder,
|
||||||
|
block: BlockId,
|
||||||
|
update_mode_var: RawUpdateModeVar,
|
||||||
|
heap_cell: ValueId,
|
||||||
|
out: *mut ValueId,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = check_err!((*self_).add_update_write_only(block, update_mode_var.slice(), heap_cell));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_AddEmptyBag(
|
||||||
|
self_: *mut FuncDefBuilder,
|
||||||
|
block: BlockId,
|
||||||
|
item_type: TypeId,
|
||||||
|
out: *mut ValueId,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = check_err!((*self_).add_empty_bag(block, item_type));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_AddBagInsert(
|
||||||
|
self_: *mut FuncDefBuilder,
|
||||||
|
block: BlockId,
|
||||||
|
bag: ValueId,
|
||||||
|
to_insert: ValueId,
|
||||||
|
out: *mut ValueId,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = check_err!((*self_).add_bag_insert(block, bag, to_insert));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_AddBagGet(
|
||||||
|
self_: *mut FuncDefBuilder,
|
||||||
|
block: BlockId,
|
||||||
|
bag: ValueId,
|
||||||
|
out: *mut ValueId,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = check_err!((*self_).add_bag_get(block, bag));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_AddBagRemove(
|
||||||
|
self_: *mut FuncDefBuilder,
|
||||||
|
block: BlockId,
|
||||||
|
bag: ValueId,
|
||||||
|
out: *mut ValueId,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = check_err!((*self_).add_bag_remove(block, bag));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_AddMakeTuple(
|
||||||
|
self_: *mut FuncDefBuilder,
|
||||||
|
block: BlockId,
|
||||||
|
field_vals: *const ValueId,
|
||||||
|
field_vals_len: usize,
|
||||||
|
out: *mut ValueId,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = check_err!(
|
||||||
|
(*self_).add_make_tuple(block, slice::from_raw_parts(field_vals, field_vals_len))
|
||||||
|
);
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_AddGetTupleField(
|
||||||
|
self_: *mut FuncDefBuilder,
|
||||||
|
block: BlockId,
|
||||||
|
tuple: ValueId,
|
||||||
|
field_idx: u32,
|
||||||
|
out: *mut ValueId,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = check_err!((*self_).add_get_tuple_field(block, tuple, field_idx));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_AddMakeUnion(
|
||||||
|
self_: *mut FuncDefBuilder,
|
||||||
|
block: BlockId,
|
||||||
|
variant_types: *const TypeId,
|
||||||
|
variant_types_len: usize,
|
||||||
|
variant_idx: u32,
|
||||||
|
to_wrap: ValueId,
|
||||||
|
out: *mut ValueId,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = check_err!((*self_).add_make_union(
|
||||||
|
block,
|
||||||
|
slice::from_raw_parts(variant_types, variant_types_len),
|
||||||
|
variant_idx,
|
||||||
|
to_wrap
|
||||||
|
));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_AddMakeNamed(
|
||||||
|
self_: *mut FuncDefBuilder,
|
||||||
|
block: BlockId,
|
||||||
|
named_mod: RawModName,
|
||||||
|
named: RawTypeName,
|
||||||
|
to_wrap: ValueId,
|
||||||
|
out: *mut ValueId,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = check_err!((*self_).add_make_named(block, named_mod.slice(), named.slice(), to_wrap));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_AddUnwrapNamed(
|
||||||
|
self_: *mut FuncDefBuilder,
|
||||||
|
block: BlockId,
|
||||||
|
named_mod: RawModName,
|
||||||
|
named: RawTypeName,
|
||||||
|
to_unwrap: ValueId,
|
||||||
|
out: *mut ValueId,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out =
|
||||||
|
check_err!((*self_).add_unwrap_named(block, named_mod.slice(), named.slice(), to_unwrap));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_AddNamedType(
|
||||||
|
self_: *mut FuncDefBuilder,
|
||||||
|
mod_: RawModName,
|
||||||
|
type_: RawTypeName,
|
||||||
|
out: *mut TypeId,
|
||||||
|
) {
|
||||||
|
*out = (*self_).add_named_type(mod_.slice(), type_.slice());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_AddTupleType(
|
||||||
|
self_: *mut FuncDefBuilder,
|
||||||
|
field_types: *const TypeId,
|
||||||
|
field_types_len: usize,
|
||||||
|
out: *mut TypeId,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = check_err!((*self_).add_tuple_type(slice::from_raw_parts(field_types, field_types_len)));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_AddUnionType(
|
||||||
|
self_: *mut FuncDefBuilder,
|
||||||
|
variant_types: *const TypeId,
|
||||||
|
variant_types_len: usize,
|
||||||
|
out: *mut TypeId,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = check_err!(
|
||||||
|
(*self_).add_union_type(slice::from_raw_parts(variant_types, variant_types_len))
|
||||||
|
);
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_AddHeapCellType(
|
||||||
|
self_: *mut FuncDefBuilder,
|
||||||
|
out: *mut TypeId,
|
||||||
|
) {
|
||||||
|
*out = (*self_).add_heap_cell_type();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncDefBuilder_AddBagType(
|
||||||
|
self_: *mut FuncDefBuilder,
|
||||||
|
item_type: TypeId,
|
||||||
|
out: *mut TypeId,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = check_err!((*self_).add_bag_type(item_type));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_ModDef_Drop(_: Option<Box<ModDef>>) {}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_ModDefBuilder_Drop(_: Option<Box<ModDefBuilder>>) {}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_ModDefBuilder_New(out: *mut *mut ModDefBuilder) {
|
||||||
|
*out = raw(ModDefBuilder::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_ModDefBuilder_Build(
|
||||||
|
self_: Box<ModDefBuilder>,
|
||||||
|
out: *mut *mut ModDef,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = raw(check_err!(self_.build()));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_ModDefBuilder_AddNamedType(
|
||||||
|
self_: *mut ModDefBuilder,
|
||||||
|
name: RawTypeName,
|
||||||
|
type_def: Box<TypeDef>,
|
||||||
|
) -> *mut Error {
|
||||||
|
check_err!((*self_).add_named_type(name.slice(), *type_def));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_ModDefBuilder_AddFunc(
|
||||||
|
self_: *mut ModDefBuilder,
|
||||||
|
name: RawFuncName,
|
||||||
|
func_def: Box<FuncDef>,
|
||||||
|
) -> *mut Error {
|
||||||
|
check_err!((*self_).add_func(name.slice(), *func_def));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_Program_Drop(_: Option<Box<Program>>) {}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_ProgramBuilder_Drop(_: Option<Box<ProgramBuilder>>) {}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_ProgramBuilder_New(out: *mut *mut ProgramBuilder) {
|
||||||
|
*out = raw(ProgramBuilder::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_ProgramBuilder_Build(
|
||||||
|
self_: Box<ProgramBuilder>,
|
||||||
|
out: *mut *mut Program,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = raw(check_err!(self_.build()));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_ProgramBuilder_AddMod(
|
||||||
|
self_: *mut ProgramBuilder,
|
||||||
|
name: RawModName,
|
||||||
|
mod_def: Box<ModDef>,
|
||||||
|
) -> *mut Error {
|
||||||
|
check_err!((*self_).add_mod(name.slice(), *mod_def));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_ProgramBuilder_AddEntryPoint(
|
||||||
|
self_: *mut ProgramBuilder,
|
||||||
|
name: RawEntryPointName,
|
||||||
|
func_mod: RawModName,
|
||||||
|
func: RawFuncName,
|
||||||
|
) -> *mut Error {
|
||||||
|
check_err!((*self_).add_entry_point(name.slice(), func_mod.slice(), func.slice()));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncSpecSolutions_CalleeSpec(
|
||||||
|
self_: *const FuncSpecSolutions,
|
||||||
|
var: RawCalleeSpecVar,
|
||||||
|
out: *mut FuncSpec,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = check_err!((*self_).callee_spec(var.slice()));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncSpecSolutions_UpdateMode(
|
||||||
|
self_: *const FuncSpecSolutions,
|
||||||
|
var: RawUpdateModeVar,
|
||||||
|
out: *mut UpdateMode,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = check_err!((*self_).update_mode(var.slice()));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FuncSpecIter<'a> {
|
||||||
|
iter: Box<dyn Iterator<Item = &'a FuncSpec>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncSpecIter_Next(
|
||||||
|
self_: *mut FuncSpecIter,
|
||||||
|
item: *mut *const FuncSpec,
|
||||||
|
) -> bool {
|
||||||
|
match (*self_).iter.next() {
|
||||||
|
Some(val) => {
|
||||||
|
*item = val;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
None => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncSolutions_Specs(
|
||||||
|
_self: *const FuncSolutions,
|
||||||
|
_out: *mut *mut FuncSpecIter,
|
||||||
|
) {
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_FuncSolutions_Spec(
|
||||||
|
self_: *mut FuncSolutions,
|
||||||
|
spec: *const FuncSpec,
|
||||||
|
out: *mut *const FuncSpecSolutions,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = check_err!((*self_).spec(&*spec));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_ModSolutions_FuncSolutions(
|
||||||
|
self_: *mut ModSolutions,
|
||||||
|
func: RawFuncName,
|
||||||
|
out: *mut *const FuncSolutions,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = check_err!((*self_).func_solutions(func.slice()));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_Solutions_Drop(_: Option<Box<Solutions>>) {}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_Solutions_ModSolutions(
|
||||||
|
self_: *mut Solutions,
|
||||||
|
mod_: RawModName,
|
||||||
|
out: *mut *const ModSolutions,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = check_err!((*self_).mod_solutions(mod_.slice()));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn Morphic_Solve(
|
||||||
|
program: Box<Program>,
|
||||||
|
out: *mut *mut Solutions,
|
||||||
|
) -> *mut Error {
|
||||||
|
*out = raw(check_err!(solve(*program)));
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
9
vendor/morphic_lib/src/lib.rs
vendored
Normal file
9
vendor/morphic_lib/src/lib.rs
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
mod util;
|
||||||
|
|
||||||
|
mod api;
|
||||||
|
mod bindings;
|
||||||
|
|
||||||
|
pub use api::*;
|
27
vendor/morphic_lib/src/util/bytes_id.rs
vendored
Normal file
27
vendor/morphic_lib/src/util/bytes_id.rs
vendored
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
macro_rules! bytes_id {
|
||||||
|
(
|
||||||
|
// Capturing attributes allows us to capture doc comments
|
||||||
|
$(#[$annot_borrowed:meta])* $borrowed_vis:vis $borrowed:ident;
|
||||||
|
$(#[$annot_owned:meta])* $owned_vis:vis $owned:ident;
|
||||||
|
) => {
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
$(#[$annot_borrowed])*
|
||||||
|
$borrowed_vis struct $borrowed<'a>($borrowed_vis &'a [u8]);
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
$(#[$annot_owned])*
|
||||||
|
$owned_vis struct $owned($owned_vis ::std::vec::Vec<u8>);
|
||||||
|
|
||||||
|
impl $owned {
|
||||||
|
fn borrowed<'a>(&'a self) -> $borrowed<'a> {
|
||||||
|
$borrowed(&self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ::std::convert::From<$borrowed<'a>> for $owned {
|
||||||
|
fn from(borrowed: $borrowed<'a>) -> Self {
|
||||||
|
$owned(<[u8]>::to_vec(&borrowed.0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
91
vendor/morphic_lib/src/util/forward_trait.rs
vendored
Normal file
91
vendor/morphic_lib/src/util/forward_trait.rs
vendored
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
macro_rules! forward_trait {
|
||||||
|
(
|
||||||
|
$(#[$annot:meta])*
|
||||||
|
$t_vis:vis trait $t_name:ident {
|
||||||
|
$($methods:tt)*
|
||||||
|
}
|
||||||
|
|
||||||
|
$($impls:tt)*
|
||||||
|
) => {
|
||||||
|
$(#[$annot])*
|
||||||
|
$t_vis trait $t_name { $($methods)* }
|
||||||
|
|
||||||
|
forward_trait_impls!(trait $t_name { $($methods)* } $($impls)*);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! forward_trait_impls {
|
||||||
|
(
|
||||||
|
trait $t_name:ident { $($methods:tt)* }
|
||||||
|
) => {
|
||||||
|
// Base case: no impls left
|
||||||
|
};
|
||||||
|
|
||||||
|
(
|
||||||
|
trait $t_name:ident { $($methods:tt)* }
|
||||||
|
|
||||||
|
impl $wrapper:ident => .$field:ident;
|
||||||
|
|
||||||
|
$($impls:tt)*
|
||||||
|
) => {
|
||||||
|
impl $t_name for $wrapper {
|
||||||
|
forward_trait_impl_body!( { $($methods)* } .$field );
|
||||||
|
}
|
||||||
|
|
||||||
|
forward_trait_impls!(trait $t_name { $($methods)* } $($impls)*);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! forward_trait_impl_body {
|
||||||
|
(
|
||||||
|
{}
|
||||||
|
.$field:ident
|
||||||
|
) => {
|
||||||
|
// Base case: no methods left
|
||||||
|
};
|
||||||
|
|
||||||
|
(
|
||||||
|
{
|
||||||
|
$(#[$annot:meta])*
|
||||||
|
fn $fn_name:ident(self $(, $arg_name:ident : $arg_ty:ty)* $(,)? ) -> $ret_ty:ty ;
|
||||||
|
$($methods:tt)*
|
||||||
|
}
|
||||||
|
.$field:ident
|
||||||
|
) => {
|
||||||
|
fn $fn_name(self, $($arg_name: $arg_ty),*) -> $ret_ty {
|
||||||
|
self.$field.$fn_name($($arg_name),*)
|
||||||
|
}
|
||||||
|
|
||||||
|
forward_trait_impl_body!({ $($methods)* } .$field);
|
||||||
|
};
|
||||||
|
|
||||||
|
(
|
||||||
|
{
|
||||||
|
$(#[$annot:meta])*
|
||||||
|
fn $fn_name:ident(&self $(, $arg_name:ident : $arg_ty:ty)* $(,)? ) -> $ret_ty:ty ;
|
||||||
|
$($methods:tt)*
|
||||||
|
}
|
||||||
|
.$field:ident
|
||||||
|
) => {
|
||||||
|
fn $fn_name(&self, $($arg_name: $arg_ty),*) -> $ret_ty {
|
||||||
|
self.$field.$fn_name($($arg_name),*)
|
||||||
|
}
|
||||||
|
|
||||||
|
forward_trait_impl_body!({ $($methods)* } .$field);
|
||||||
|
};
|
||||||
|
|
||||||
|
(
|
||||||
|
{
|
||||||
|
$(#[$annot:meta])*
|
||||||
|
fn $fn_name:ident(&mut self $(, $arg_name:ident : $arg_ty:ty)* $(,)? ) -> $ret_ty:ty ;
|
||||||
|
$($methods:tt)*
|
||||||
|
}
|
||||||
|
.$field:ident
|
||||||
|
) => {
|
||||||
|
fn $fn_name(&mut self, $($arg_name: $arg_ty),*) -> $ret_ty {
|
||||||
|
self.$field.$fn_name($($arg_name),*)
|
||||||
|
}
|
||||||
|
|
||||||
|
forward_trait_impl_body!({ $($methods)* } .$field);
|
||||||
|
};
|
||||||
|
}
|
5
vendor/morphic_lib/src/util/mod.rs
vendored
Normal file
5
vendor/morphic_lib/src/util/mod.rs
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#[macro_use]
|
||||||
|
pub mod bytes_id;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
pub mod forward_trait;
|
Loading…
Add table
Add a link
Reference in a new issue