Merge branch 'trunk' into hash-links

This commit is contained in:
Richard Feldman 2021-05-24 08:25:11 -04:00 committed by GitHub
commit c8665fa9b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
50 changed files with 3378 additions and 112 deletions

100
Cargo.lock generated
View File

@ -210,7 +210,16 @@ dependencies = [
"block-padding",
"byte-tools",
"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]]
@ -577,6 +586,15 @@ dependencies = [
"objc",
]
[[package]]
name = "cpufeatures"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dec1028182c380cc45a2e2c5ec841134f2dfd0f8f5f0a5bcd68004f81b5efdf4"
dependencies = [
"libc",
]
[[package]]
name = "crc32fast"
version = "1.2.1"
@ -840,7 +858,16 @@ version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
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]]
@ -1134,6 +1161,16 @@ dependencies = [
"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]]
name = "getrandom"
version = "0.1.16"
@ -1875,6 +1912,14 @@ dependencies = [
"ws2_32-sys",
]
[[package]]
name = "morphic_lib"
version = "0.1.0"
dependencies = [
"sha2",
"thiserror",
]
[[package]]
name = "naga"
version = "0.4.1"
@ -2083,22 +2128,21 @@ dependencies = [
[[package]]
name = "object"
version = "0.22.0"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397"
checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4"
[[package]]
name = "object"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a5b3dd1c072ee7963717671d1ca129f1048fda25edea6b752bfc71ac8854170"
dependencies = [
"crc32fast",
"flate2",
"indexmap",
"wasmparser",
]
[[package]]
name = "object"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4"
[[package]]
name = "once_cell"
version = "1.7.2"
@ -2117,6 +2161,12 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
[[package]]
name = "opaque-debug"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "ordered-float"
version = "2.1.1"
@ -3136,7 +3186,7 @@ dependencies = [
"libc",
"libloading 0.6.7",
"maplit",
"object 0.22.0",
"object 0.24.0",
"pretty_assertions 0.5.1",
"quickcheck 0.8.5",
"quickcheck_macros 0.8.0",
@ -3215,6 +3265,7 @@ dependencies = [
"indoc 0.3.6",
"linked-hash-map",
"maplit",
"morphic_lib",
"pretty_assertions 0.5.1",
"quickcheck 0.8.5",
"quickcheck_macros 0.8.0",
@ -3560,10 +3611,23 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
dependencies = [
"block-buffer",
"digest",
"block-buffer 0.7.3",
"digest 0.8.1",
"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]]
@ -4136,12 +4200,6 @@ version = "0.2.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f"
[[package]]
name = "wasmparser"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32fddd575d477c6e9702484139cf9f23dcd554b06d185ed0f56c857dd3a47aa6"
[[package]]
name = "wayland-client"
version = "0.28.5"

View File

@ -496,3 +496,22 @@ of the authors and should not be interpreted as representing official policies,
either expressed or implied, of the FreeBSD Project.
===========================================================
* morphic_lib - https://github.com/morphic-lang/morphic_lib
This source code can be found in vendor/morphic_lib and is licensed under the following terms:
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
===========================================================

View File

@ -1,4 +1,4 @@
#![warn(clippy::all, clippy::dbg_macro)]
#![warn(clippy::dbg_macro)]
// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check.
#![allow(clippy::large_enum_variant)]
pub mod link;

View File

@ -1,4 +1,4 @@
#![warn(clippy::all, clippy::dbg_macro)]
#![warn(clippy::dbg_macro)]
// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check.
#![allow(clippy::large_enum_variant)]
pub mod bitcode;

View File

@ -1,4 +1,4 @@
#![warn(clippy::all, clippy::dbg_macro)]
#![warn(clippy::dbg_macro)]
// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check.
#![allow(clippy::large_enum_variant)]
pub mod annotation;

View File

@ -1,4 +1,4 @@
#![warn(clippy::all, clippy::dbg_macro)]
#![warn(clippy::dbg_macro)]
// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check.
#![allow(clippy::large_enum_variant)]

View File

@ -1,4 +1,4 @@
#![warn(clippy::all, clippy::dbg_macro)]
#![warn(clippy::dbg_macro)]
// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check.
#![allow(clippy::large_enum_variant)]
pub mod builtins;

View File

@ -1,4 +1,4 @@
#![warn(clippy::all, clippy::dbg_macro)]
#![warn(clippy::dbg_macro)]
// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check.
#![allow(clippy::large_enum_variant)]
pub mod annotation;

View File

@ -1,4 +1,4 @@
#![warn(clippy::all, clippy::dbg_macro)]
#![warn(clippy::dbg_macro)]
// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check.
#![allow(clippy::large_enum_variant)]
// we actually want to compare against the literal float bits

View File

@ -844,7 +844,7 @@ pub fn build_exp_call<'a, 'ctx, 'env>(
.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)
}

View File

@ -23,7 +23,7 @@ bumpalo = { version = "3.6.1", features = ["collections"] }
inlinable_string = "0.1"
target-lexicon = "0.10"
libloading = "0.6"
object = { version = "0.22", features = ["write"] }
object = { version = "0.24", features = ["write"] }
[dev-dependencies]
roc_can = { path = "../can" }

View File

@ -1,4 +1,4 @@
#![warn(clippy::all, clippy::dbg_macro)]
#![warn(clippy::dbg_macro)]
// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check.
#![allow(clippy::large_enum_variant, clippy::upper_case_acronyms)]
@ -214,7 +214,7 @@ where
}
}
CallType::LowLevel { op: lowlevel } => {
CallType::LowLevel { op: lowlevel, .. } => {
self.build_run_low_level(sym, lowlevel, arguments, layout)
}
x => Err(format!("the call type, {:?}, is not yet implemented", x)),

View File

@ -13,7 +13,9 @@ use roc_mono::ir::Proc;
use roc_mono::layout::Layout;
use target_lexicon::{Architecture as TargetArch, BinaryFormat as TargetBF, Triple};
const VERSION: &str = env!("CARGO_PKG_VERSION");
// This is used by some code below which is currently commented out.
// See that code for more details!
// const VERSION: &str = env!("CARGO_PKG_VERSION");
/// build_module is the high level builder/delegator.
/// It takes the request to build a module and output the object file for the module.
@ -41,6 +43,28 @@ pub fn build_module<'a>(
Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little),
)
}
Triple {
architecture: TargetArch::X86_64,
binary_format: TargetBF::Macho,
..
} => {
let backend: Backend64Bit<
x86_64::X86_64GeneralReg,
x86_64::X86_64FloatReg,
x86_64::X86_64Assembler,
x86_64::X86_64SystemV,
> = Backend::new(env, target)?;
build_object(
env,
procedures,
backend,
Object::new(
BinaryFormat::MachO,
Architecture::X86_64,
Endianness::Little,
),
)
}
Triple {
architecture: TargetArch::Aarch64(_),
binary_format: TargetBF::Elf,
@ -72,12 +96,16 @@ fn build_object<'a, B: Backend<'a>>(
mut output: Object,
) -> Result<Object, String> {
let data_section = output.section_id(StandardSection::Data);
let comment = output.add_section(vec![], b"comment".to_vec(), SectionKind::OtherString);
/*
// Commented out because we couldn't figure out how to get it to work on mac - see https://github.com/rtfeldman/roc/pull/1323
let comment = output.add_section(vec![], b".comment".to_vec(), SectionKind::OtherString);
output.append_section_data(
comment,
format!("\0roc dev backend version {} \0", VERSION).as_bytes(),
1,
);
*/
// Setup layout_ids for procedure calls.
let mut layout_ids = roc_mono::layout::LayoutIds::default();
@ -89,7 +117,7 @@ fn build_object<'a, B: Backend<'a>>(
let section_id = output.add_section(
output.segment_name(StandardSegment::Text).to_vec(),
format!(".text.{}", fn_name).as_bytes().to_vec(),
format!(".text.{:x}", sym.as_u64()).as_bytes().to_vec(),
SectionKind::Text,
);
@ -182,7 +210,7 @@ fn build_object<'a, B: Backend<'a>>(
offset: offset + proc_offset,
size: 32,
kind: RelocationKind::PltRelative,
encoding: RelocationEncoding::Generic,
encoding: RelocationEncoding::X86Branch,
symbol: sym_id,
addend: -4,
}

View File

@ -10,7 +10,7 @@ extern crate libc;
#[macro_use]
mod helpers;
#[cfg(all(test, target_os = "linux", any(target_arch = "x86_64"/*, target_arch = "aarch64"*/)))]
#[cfg(all(test, any(target_os = "linux", target_os = "macos"), any(target_arch = "x86_64"/*, target_arch = "aarch64"*/)))]
mod gen_num {
#[test]
fn i64_values() {

View File

@ -2046,6 +2046,14 @@ fn update<'a>(
&& state.dependencies.solved_all()
&& 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::optimize_refcount_operations(
@ -3810,6 +3818,8 @@ fn make_specializations<'a>(
home,
ident_ids: &mut ident_ids,
ptr_bytes,
update_mode_counter: 0,
call_specialization_counter: 0,
};
// TODO: for now this final specialization pass is sequential,
@ -3871,6 +3881,8 @@ fn build_pending_specializations<'a>(
home,
ident_ids: &mut ident_ids,
ptr_bytes,
update_mode_counter: 0,
call_specialization_counter: 0,
};
// Add modules' decls to Procs

View File

@ -1,4 +1,4 @@
#![warn(clippy::all, clippy::dbg_macro)]
#![warn(clippy::dbg_macro)]
// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check.
#![allow(clippy::large_enum_variant)]
pub mod docs;

View File

@ -1,4 +1,4 @@
#![warn(clippy::all, clippy::dbg_macro)]
#![warn(clippy::dbg_macro)]
// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check.
#![allow(clippy::large_enum_variant, clippy::upper_case_acronyms)]

View File

@ -86,6 +86,10 @@ impl Symbol {
})
}
pub fn as_u64(self) -> u64 {
self.0
}
pub fn fully_qualified(self, interns: &Interns, home: ModuleId) -> InlinableString {
let module_id = self.module_id();
@ -101,6 +105,10 @@ impl Symbol {
.into()
}
}
pub const fn to_ne_bytes(self) -> [u8; 8] {
self.0.to_ne_bytes()
}
}
/// Rather than displaying as this:

View File

@ -15,6 +15,7 @@ roc_unify = { path = "../unify" }
roc_solve = { path = "../solve" }
roc_problem = { path = "../problem" }
ven_pretty = { path = "../../vendor/pretty" }
morphic_lib = { path = "../../vendor/morphic_lib" }
bumpalo = { version = "3.6.1", features = ["collections"] }
hashbrown = { version = "0.11.2", features = [ "bumpalo" ] }
ven_ena = { path = "../../vendor/ena" }

View 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, &[])
}

View File

@ -402,7 +402,7 @@ impl<'a> BorrowInfState<'a> {
self.own_args(arguments);
}
LowLevel { op } => {
LowLevel { op, .. } => {
// very unsure what demand RunLowLevel should place upon its arguments
self.own_var(z);

View File

@ -1404,8 +1404,12 @@ fn compile_test_help<'a>(
default_branch,
};
let op = LowLevel::Eq;
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]),
});

View File

@ -442,7 +442,7 @@ impl<'a> Context<'a> {
use crate::ir::CallType::*;
match &call_type {
LowLevel { op } => {
LowLevel { op, .. } => {
let ps = crate::borrow::lowlevel_borrow_signature(self.arena, *op);
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;
let stmt = match &call.call_type {
CallType::LowLevel { op } => {
CallType::LowLevel { op, .. } => {
let ps = crate::borrow::lowlevel_borrow_signature(self.arena, *op);
self.add_dec_after_lowlevel(call.arguments, ps, cont, &case_live_vars)
}

View File

@ -735,6 +735,8 @@ pub struct Env<'a, 'i> {
pub home: ModuleId,
pub ident_ids: &'i mut IdentIds,
pub ptr_bytes: u32,
pub update_mode_counter: u64,
pub call_specialization_counter: u64,
}
impl<'a, 'i> Env<'a, 'i> {
@ -746,6 +748,26 @@ impl<'a, 'i> Env<'a, 'i> {
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 {
symbol.module_id() != self.home && !symbol.is_builtin()
}
@ -1004,7 +1026,7 @@ impl<'a> Call<'a> {
.text("CallByPointer ")
.append(alloc.intersperse(it, " "))
}
LowLevel { op: lowlevel } => {
LowLevel { op: lowlevel, .. } => {
let it = arguments.iter().map(|s| symbol_to_doc(alloc, *s));
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)]
pub enum CallType<'a> {
ByName {
name: Symbol,
full_layout: Layout<'a>,
ret_layout: Layout<'a>,
arg_layouts: &'a [Layout<'a>],
specialization_id: CallSpecId,
},
ByPointer {
name: Symbol,
full_layout: Layout<'a>,
ret_layout: Layout<'a>,
arg_layouts: &'a [Layout<'a>],
@ -1046,6 +1089,7 @@ pub enum CallType<'a> {
},
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));
let call = self::Call {
call_type: CallType::LowLevel { op },
call_type: CallType::LowLevel {
op,
update_mode: env.next_update_mode_id(),
},
arguments: arg_symbols,
};
@ -4316,8 +4363,10 @@ pub fn from_can<'a>(
let bool_layout = Layout::Builtin(Builtin::Int1);
let cond_symbol = env.unique_symbol();
let op = LowLevel::ExpectTrue;
let call_type = CallType::LowLevel {
op: LowLevel::ExpectTrue,
op,
update_mode: env.next_update_mode_id(),
};
let arguments = env.arena.alloc([cond_symbol]);
let call = self::Call {
@ -5054,11 +5103,13 @@ fn substitute_in_call<'a>(
arg_layouts,
ret_layout,
full_layout,
specialization_id,
} => substitute(subs, *name).map(|new| CallType::ByName {
name: new,
arg_layouts,
ret_layout: *ret_layout,
full_layout: *full_layout,
specialization_id: *specialization_id,
}),
CallType::ByPointer {
name,
@ -5840,6 +5891,7 @@ fn call_by_pointer<'a>(
full_layout: layout,
ret_layout: *ret_layout,
arg_layouts,
specialization_id: env.next_call_specialization_id(),
};
let call = Call {
call_type,
@ -6098,6 +6150,7 @@ fn call_by_name<'a>(
ret_layout: *ret_layout,
full_layout,
arg_layouts,
specialization_id: env.next_call_specialization_id(),
},
arguments: field_symbols,
};
@ -6142,6 +6195,7 @@ fn call_by_name<'a>(
ret_layout: *ret_layout,
full_layout,
arg_layouts,
specialization_id: env.next_call_specialization_id(),
},
arguments: field_symbols,
};
@ -6248,6 +6302,7 @@ fn call_by_name<'a>(
ret_layout: *ret_layout,
full_layout,
arg_layouts,
specialization_id: env.next_call_specialization_id(),
},
arguments: field_symbols,
}
@ -6311,6 +6366,7 @@ fn call_specialized_proc<'a>(
ret_layout: function_layout.result,
full_layout: function_layout.full,
arg_layouts: function_layout.arguments,
specialization_id: env.next_call_specialization_id(),
},
arguments: field_symbols,
};
@ -6332,6 +6388,7 @@ fn call_specialized_proc<'a>(
ret_layout: function_layout.result,
full_layout: function_layout.full,
arg_layouts: function_layout.arguments,
specialization_id: env.next_call_specialization_id(),
},
arguments: field_symbols,
};
@ -6351,6 +6408,7 @@ fn call_specialized_proc<'a>(
ret_layout: function_layout.result,
full_layout: function_layout.full,
arg_layouts: function_layout.arguments,
specialization_id: env.next_call_specialization_id(),
},
arguments: field_symbols,
};

View File

@ -1980,3 +1980,21 @@ impl<'a> LayoutIds<'a> {
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(()),
}
}
}

View File

@ -1,7 +1,8 @@
#![warn(clippy::all, clippy::dbg_macro)]
#![warn(clippy::dbg_macro)]
// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check.
#![allow(clippy::large_enum_variant, clippy::upper_case_acronyms)]
pub mod alias_analysis;
pub mod borrow;
pub mod expand_rc;
pub mod inc_dec;

View File

@ -1,4 +1,4 @@
#![warn(clippy::all, clippy::dbg_macro)]
#![warn(clippy::dbg_macro)]
// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check.
#![allow(clippy::large_enum_variant)]

View File

@ -1,4 +1,4 @@
#![warn(clippy::all, clippy::dbg_macro)]
#![warn(clippy::dbg_macro)]
// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check.
#![allow(clippy::large_enum_variant)]
pub mod can;

View File

@ -1,4 +1,4 @@
#![warn(clippy::all, clippy::dbg_macro)]
#![warn(clippy::dbg_macro)]
// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check.
#![allow(clippy::large_enum_variant)]

View File

@ -1,4 +1,4 @@
#![warn(clippy::all, clippy::dbg_macro)]
#![warn(clippy::dbg_macro)]
// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check.
#![allow(clippy::large_enum_variant)]

View File

@ -100,6 +100,8 @@ mod test_reporting {
home,
ident_ids: &mut ident_ids,
ptr_bytes: 8,
update_mode_counter: 0,
call_specialization_counter: 0,
};
let _mono_expr = Stmt::new(
&mut mono_env,

View File

@ -1,4 +1,4 @@
#![warn(clippy::all, clippy::dbg_macro)]
#![warn(clippy::dbg_macro)]
// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check.
#![allow(clippy::large_enum_variant)]

View File

@ -1,4 +1,4 @@
#![warn(clippy::all, clippy::dbg_macro)]
#![warn(clippy::dbg_macro)]
// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check.
#![allow(clippy::large_enum_variant)]
// we actually want to compare against the literal float bits

View File

@ -1,4 +1,4 @@
#![warn(clippy::all, clippy::dbg_macro)]
#![warn(clippy::dbg_macro)]
// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check.
#![allow(clippy::large_enum_variant)]
pub mod builtin_aliases;

View File

@ -1,4 +1,4 @@
#![warn(clippy::all, clippy::dbg_macro)]
#![warn(clippy::dbg_macro)]
// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check.
#![allow(clippy::large_enum_variant)]

View File

@ -286,9 +286,9 @@ pub fn constrain_expr<'a>(
} => {
// The expression that evaluates to the function being called, e.g. `foo` in
// (foo) bar baz
let expr = env.pool.get(*expr_node_id);
let call_expr = env.pool.get(*expr_node_id);
let opt_symbol = if let Expr2::Var(symbol) = expr {
let opt_symbol = if let Expr2::Var(symbol) = call_expr {
Some(*symbol)
} else {
None
@ -303,7 +303,7 @@ pub fn constrain_expr<'a>(
arity: args.len() as u8,
};
let fn_con = constrain_expr(arena, env, expr, fn_expected, region);
let fn_con = constrain_expr(arena, env, call_expr, fn_expected, region);
// The function's return type
// TODO: don't use expr_var?
@ -431,6 +431,54 @@ pub fn constrain_expr<'a>(
exists(arena, flex_vars, And(and_constraints))
}
Expr2::Access {
expr: expr_id,
field,
field_var,
record_var,
ext_var,
} => {
let ext_type = Type2::Variable(*ext_var);
let field_type = Type2::Variable(*field_var);
let record_field =
types::RecordField::Demanded(env.pool.add(field_type.shallow_clone()));
let record_type = Type2::Record(
PoolVec::new(vec![(*field, record_field)].into_iter(), env.pool),
env.pool.add(ext_type),
);
let record_expected = Expected::NoExpectation(record_type);
let category = Category::Access(field.as_str(env.pool).into());
let record_con = Eq(
Type2::Variable(*record_var),
record_expected.shallow_clone(),
category.clone(),
region,
);
let access_expr = env.pool.get(*expr_id);
let constraint = constrain_expr(arena, env, access_expr, record_expected, region);
let mut flex_vars = BumpVec::with_capacity_in(3, arena);
flex_vars.push(*record_var);
flex_vars.push(*field_var);
flex_vars.push(*ext_var);
let mut and_constraints = BumpVec::with_capacity_in(3, arena);
and_constraints.push(constraint);
and_constraints.push(Eq(field_type, expected, category, region));
and_constraints.push(record_con);
exists(arena, flex_vars, And(and_constraints))
}
_ => todo!("implement constaints for {:?}", expr),
}
}

View File

@ -780,6 +780,10 @@ pub fn to_expr2<'a>(
(expr, output)
}
Defs(loc_defs, loc_ret) => {
todo!("{:?} {:?}", loc_defs, loc_ret)
}
PrecedenceConflict { .. } => {
// use roc_problem::can::RuntimeError::*;
//

View File

@ -1,4 +1,4 @@
#![warn(clippy::all, clippy::dbg_macro)]
#![warn(clippy::dbg_macro)]
// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check.
#![allow(clippy::large_enum_variant, clippy::upper_case_acronyms)]

View File

@ -262,3 +262,15 @@ fn constrain_call_and_accessor() {
"Str",
)
}
#[test]
fn constrain_access() {
infer_eq(
indoc!(
r#"
{ foo: "bar" }.foo
"#
),
"Str",
)
}

View File

@ -4,56 +4,56 @@ app "quicksort"
provides [ quicksort ] to base
quicksort = \originalList ->
quicksortHelp : List (Num a), Nat, Nat -> List (Num a)
quicksortHelp = \list, low, high ->
if low < high then
when partition low high list is
Pair partitionIndex partitioned ->
partitioned
|> quicksortHelp low (partitionIndex - 1)
|> quicksortHelp (partitionIndex + 1) high
else
list
partition : Nat, Nat, List (Num a) -> [ Pair Nat (List (Num a)) ]
partition = \low, high, initialList ->
when List.get initialList high is
Ok pivot ->
when partitionHelp (low - 1) low initialList high pivot is
Pair newI newList ->
Pair (newI + 1) (swap (newI + 1) high newList)
Err _ ->
Pair (low - 1) initialList
partitionHelp : Nat, Nat, List (Num c), Nat, (Num c) -> [ Pair Nat (List (Num c)) ]
partitionHelp = \i, j, list, high, pivot ->
if j < high then
when List.get list j is
Ok value ->
if value <= pivot then
partitionHelp (i + 1) (j + 1) (swap (i + 1) j list) high pivot
else
partitionHelp i (j + 1) list high pivot
Err _ ->
Pair i list
else
Pair i list
swap : Nat, Nat, List a -> List a
swap = \i, j, list ->
when Pair (List.get list i) (List.get list j) is
Pair (Ok atI) (Ok atJ) ->
list
|> List.set i atJ
|> List.set j atI
_ ->
[]
n = List.len originalList
quicksortHelp originalList 0 (n - 1)
quicksortHelp : List (Num a), Nat, Nat -> List (Num a)
quicksortHelp = \list, low, high ->
if low < high then
when partition low high list is
Pair partitionIndex partitioned ->
partitioned
|> quicksortHelp low (partitionIndex - 1)
|> quicksortHelp (partitionIndex + 1) high
else
list
partition : Nat, Nat, List (Num a) -> [ Pair Nat (List (Num a)) ]
partition = \low, high, initialList ->
when List.get initialList high is
Ok pivot ->
when partitionHelp (low - 1) low initialList high pivot is
Pair newI newList ->
Pair (newI + 1) (swap (newI + 1) high newList)
Err _ ->
Pair (low - 1) initialList
partitionHelp : Nat, Nat, List (Num c), Nat, (Num c) -> [ Pair Nat (List (Num c)) ]
partitionHelp = \i, j, list, high, pivot ->
if j < high then
when List.get list j is
Ok value ->
if value <= pivot then
partitionHelp (i + 1) (j + 1) (swap (i + 1) j list) high pivot
else
partitionHelp i (j + 1) list high pivot
Err _ ->
Pair i list
else
Pair i list
swap : Nat, Nat, List a -> List a
swap = \i, j, list ->
when Pair (List.get list i) (List.get list j) is
Pair (Ok atI) (Ok atJ) ->
list
|> List.set i atJ
|> List.set j atI
_ ->
[]

2
vendor/morphic_lib/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
Cargo.lock

9
vendor/morphic_lib/Cargo.toml vendored Normal file
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

706
vendor/morphic_lib/src/bindings.rs vendored Normal file
View 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
View 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
View 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))
}
}
}
}

View 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
View File

@ -0,0 +1,5 @@
#[macro_use]
pub mod bytes_id;
#[macro_use]
pub mod forward_trait;