mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 13:59:08 +00:00
Merge remote-tracking branch 'origin/trunk' into specialize-lowlevel
This commit is contained in:
commit
fbb711b2ca
70 changed files with 3513 additions and 126 deletions
100
Cargo.lock
generated
100
Cargo.lock
generated
|
@ -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"
|
||||
|
@ -3134,7 +3184,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",
|
||||
|
@ -3213,6 +3263,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",
|
||||
|
@ -3558,10 +3609,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]]
|
||||
|
@ -4134,12 +4198,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"
|
||||
|
|
|
@ -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.
|
||||
|
||||
===========================================================
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -727,6 +727,42 @@ pub fn listAppend(list: RocList, alignment: usize, element: Opaque, element_widt
|
|||
return output;
|
||||
}
|
||||
|
||||
pub fn listDrop(
|
||||
list: RocList,
|
||||
alignment: usize,
|
||||
element_width: usize,
|
||||
drop_count: usize,
|
||||
dec: Dec,
|
||||
) callconv(.C) RocList {
|
||||
if (list.bytes) |source_ptr| {
|
||||
const size = list.len();
|
||||
const keep_count = size - drop_count;
|
||||
|
||||
var i: usize = 0;
|
||||
const iterations = std.math.min(drop_count, size);
|
||||
|
||||
while (i < iterations) : (i += 1) {
|
||||
const element = source_ptr + i * element_width;
|
||||
dec(element);
|
||||
}
|
||||
|
||||
if (drop_count >= size) {
|
||||
return RocList.empty();
|
||||
}
|
||||
|
||||
const output = RocList.allocate(std.heap.c_allocator, alignment, keep_count, element_width);
|
||||
const target_ptr = output.bytes orelse unreachable;
|
||||
|
||||
@memcpy(target_ptr, source_ptr + drop_count * element_width, keep_count * element_width);
|
||||
|
||||
utils.decref(std.heap.c_allocator, alignment, list.bytes, size * element_width);
|
||||
|
||||
return output;
|
||||
} else {
|
||||
return RocList.empty();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn listRange(width: utils.IntWidth, low: Opaque, high: Opaque) callconv(.C) RocList {
|
||||
const allocator = std.heap.c_allocator;
|
||||
const IntWidth = utils.IntWidth;
|
||||
|
|
|
@ -25,6 +25,7 @@ comptime {
|
|||
exportListFn(list.listReverse, "reverse");
|
||||
exportListFn(list.listSortWith, "sort_with");
|
||||
exportListFn(list.listConcat, "concat");
|
||||
exportListFn(list.listDrop, "drop");
|
||||
}
|
||||
|
||||
// Dict Module
|
||||
|
|
|
@ -76,6 +76,7 @@ pub const LIST_WALK_BACKWARDS: &str = "roc_builtins.list.walk_backwards";
|
|||
pub const LIST_CONTAINS: &str = "roc_builtins.list.contains";
|
||||
pub const LIST_REPEAT: &str = "roc_builtins.list.repeat";
|
||||
pub const LIST_APPEND: &str = "roc_builtins.list.append";
|
||||
pub const LIST_DROP: &str = "roc_builtins.list.drop";
|
||||
pub const LIST_SINGLE: &str = "roc_builtins.list.single";
|
||||
pub const LIST_JOIN: &str = "roc_builtins.list.join";
|
||||
pub const LIST_RANGE: &str = "roc_builtins.list.range";
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -849,6 +849,13 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
|||
Box::new(list_type(flex(TVAR1))),
|
||||
);
|
||||
|
||||
// drop : List elem, Nat -> List elem
|
||||
add_top_level_function_type!(
|
||||
Symbol::LIST_DROP,
|
||||
vec![list_type(flex(TVAR1)), nat_type()],
|
||||
Box::new(list_type(flex(TVAR1))),
|
||||
);
|
||||
|
||||
// prepend : List elem, elem -> List elem
|
||||
add_top_level_function_type!(
|
||||
Symbol::LIST_PREPEND,
|
||||
|
|
|
@ -84,6 +84,7 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option<Def>
|
|||
LIST_MAP => list_map,
|
||||
LIST_MAP2 => list_map2,
|
||||
LIST_MAP3 => list_map3,
|
||||
LIST_DROP => list_drop,
|
||||
LIST_MAP_WITH_INDEX => list_map_with_index,
|
||||
LIST_KEEP_IF => list_keep_if,
|
||||
LIST_KEEP_OKS => list_keep_oks,
|
||||
|
@ -1881,6 +1882,28 @@ fn list_set(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
list_ret_var,
|
||||
)
|
||||
}
|
||||
/// List.drop : List elem, Nat -> List elem
|
||||
fn list_drop(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
let list_var = var_store.fresh();
|
||||
let index_var = var_store.fresh();
|
||||
|
||||
let body = RunLowLevel {
|
||||
op: LowLevel::ListDrop,
|
||||
args: vec![
|
||||
(list_var, Var(Symbol::ARG_1)),
|
||||
(index_var, Var(Symbol::ARG_2)),
|
||||
],
|
||||
ret_var: list_var,
|
||||
};
|
||||
|
||||
defn(
|
||||
symbol,
|
||||
vec![(list_var, Symbol::ARG_1), (index_var, Symbol::ARG_2)],
|
||||
var_store,
|
||||
body,
|
||||
list_var,
|
||||
)
|
||||
}
|
||||
|
||||
/// List.append : List elem, elem -> List elem
|
||||
fn list_append(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)]
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -6,9 +6,9 @@ use crate::llvm::build_dict::{
|
|||
use crate::llvm::build_hash::generic_hash;
|
||||
use crate::llvm::build_list::{
|
||||
allocate_list, empty_list, empty_polymorphic_list, list_append, list_concat, list_contains,
|
||||
list_get_unsafe, list_join, list_keep_errs, list_keep_if, list_keep_oks, list_len, list_map,
|
||||
list_map2, list_map3, list_map_with_index, list_prepend, list_range, list_repeat, list_reverse,
|
||||
list_set, list_single, list_sort_with,
|
||||
list_drop, list_get_unsafe, list_join, list_keep_errs, list_keep_if, list_keep_oks, list_len,
|
||||
list_map, list_map2, list_map3, list_map_with_index, list_prepend, list_range, list_repeat,
|
||||
list_reverse, list_set, list_single, list_sort_with,
|
||||
};
|
||||
use crate::llvm::build_str::{
|
||||
empty_str, str_concat, str_count_graphemes, str_ends_with, str_from_float, str_from_int,
|
||||
|
@ -820,7 +820,7 @@ pub fn build_exp_call<'a, 'ctx, 'env>(
|
|||
)
|
||||
}
|
||||
|
||||
CallType::LowLevel { op } => {
|
||||
CallType::LowLevel { op, update_mode: _ } => {
|
||||
run_low_level(env, layout_ids, scope, parent, layout, *op, arguments)
|
||||
}
|
||||
|
||||
|
@ -4186,6 +4186,27 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
list_append(env, inplace, original_wrapper, elem, elem_layout)
|
||||
}
|
||||
ListDrop => {
|
||||
// List.drop : List elem, Nat -> List elem
|
||||
debug_assert_eq!(args.len(), 2);
|
||||
|
||||
let (list, list_layout) = load_symbol_and_layout(scope, &args[0]);
|
||||
let original_wrapper = list.into_struct_value();
|
||||
|
||||
let count = load_symbol(scope, &args[1]);
|
||||
|
||||
match list_layout {
|
||||
Layout::Builtin(Builtin::EmptyList) => empty_list(env),
|
||||
Layout::Builtin(Builtin::List(_, element_layout)) => list_drop(
|
||||
env,
|
||||
layout_ids,
|
||||
original_wrapper,
|
||||
count.into_int_value(),
|
||||
element_layout,
|
||||
),
|
||||
_ => unreachable!("Invalid layout {:?} in List.drop", list_layout),
|
||||
}
|
||||
}
|
||||
ListPrepend => {
|
||||
// List.prepend : List elem, elem -> List elem
|
||||
debug_assert_eq!(args.len(), 2);
|
||||
|
|
|
@ -322,6 +322,28 @@ pub fn list_append<'a, 'ctx, 'env>(
|
|||
)
|
||||
}
|
||||
|
||||
/// List.drop : List elem, Nat -> List elem
|
||||
pub fn list_drop<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
original_wrapper: StructValue<'ctx>,
|
||||
count: IntValue<'ctx>,
|
||||
element_layout: &Layout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let dec_element_fn = build_dec_wrapper(env, layout_ids, &element_layout);
|
||||
call_bitcode_fn_returns_list(
|
||||
env,
|
||||
&[
|
||||
pass_list_as_i128(env, original_wrapper.into()),
|
||||
alignment_intvalue(env, &element_layout),
|
||||
layout_width(env, &element_layout),
|
||||
count.into(),
|
||||
dec_element_fn.as_global_value().as_pointer_value().into(),
|
||||
],
|
||||
&bitcode::LIST_DROP,
|
||||
)
|
||||
}
|
||||
|
||||
/// List.set : List elem, Int, elem -> List elem
|
||||
pub fn list_set<'a, 'ctx, 'env>(
|
||||
parent: FunctionValue<'ctx>,
|
||||
|
|
|
@ -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" }
|
||||
|
|
|
@ -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)),
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
@ -128,9 +128,7 @@ mod gen_num {
|
|||
af = 31
|
||||
ag = 32
|
||||
|
||||
# This can't be one line because it causes a stack overflow in the frontend :(
|
||||
tmp = a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p + q
|
||||
tmp + r + s + t + u + v + w + x + y + z + aa + ab + ac + ad + ae + af + ag
|
||||
a + b + c + d + e + f + g + h + i + j + k + l + m + n + o + p + q + r + s + t + u + v + w + x + y + z + aa + ab + ac + ad + ae + af + ag
|
||||
"#
|
||||
),
|
||||
528,
|
||||
|
|
|
@ -52,7 +52,7 @@ const DEFAULT_APP_OUTPUT_PATH: &str = "app";
|
|||
const ROC_FILE_EXTENSION: &str = "roc";
|
||||
|
||||
/// Roc-Config file name
|
||||
const PKG_CONFIG_FILE_NAME: &str = "Pkg-Config";
|
||||
const PKG_CONFIG_FILE_NAME: &str = "Package-Config";
|
||||
|
||||
/// The . in between module names like Foo.Bar.Baz
|
||||
const MODULE_SEPARATOR: char = '.';
|
||||
|
@ -1894,7 +1894,7 @@ fn update<'a>(
|
|||
|
||||
let work = state.dependencies.notify(module_id, Phase::SolveTypes);
|
||||
|
||||
// if there is a platform, the Pkg-Config module provides host-exposed,
|
||||
// if there is a platform, the Package-Config module provides host-exposed,
|
||||
// otherwise the App module exposes host-exposed
|
||||
let is_host_exposed = match state.platform_id {
|
||||
None => module_id == state.root_id,
|
||||
|
@ -2060,6 +2060,15 @@ fn update<'a>(
|
|||
|
||||
println!("{}", result);
|
||||
}
|
||||
|
||||
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(
|
||||
|
@ -2313,7 +2322,7 @@ fn load_pkg_config<'a>(
|
|||
let chomped = &bytes[..delta];
|
||||
let header_src = unsafe { std::str::from_utf8_unchecked(chomped) };
|
||||
|
||||
// make a Pkg-Config module that ultimately exposes `main` to the host
|
||||
// make a Package-Config module that ultimately exposes `main` to the host
|
||||
let pkg_config_module_msg = fabricate_pkg_config_module(
|
||||
arena,
|
||||
shorthand,
|
||||
|
@ -2552,7 +2561,7 @@ fn parse_header<'a>(
|
|||
}) => {
|
||||
match package_or_path {
|
||||
PackageOrPath::Path(StrLiteral::PlainLine(package)) => {
|
||||
// check whether we can find a Pkg-Config.roc file
|
||||
// check whether we can find a Package-Config.roc file
|
||||
let mut pkg_config_roc = pkg_config_dir;
|
||||
pkg_config_roc.push(package);
|
||||
pkg_config_roc.push(PKG_CONFIG_FILE_NAME);
|
||||
|
@ -3800,6 +3809,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,
|
||||
|
@ -3861,6 +3872,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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)]
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ pub enum LowLevel {
|
|||
ListKeepOks,
|
||||
ListKeepErrs,
|
||||
ListSortWith,
|
||||
ListDrop,
|
||||
DictSize,
|
||||
DictEmpty,
|
||||
DictInsert,
|
||||
|
@ -124,6 +125,7 @@ impl LowLevel {
|
|||
| ListGetUnsafe
|
||||
| ListSet
|
||||
| ListSetInPlace
|
||||
| ListDrop
|
||||
| ListSingle
|
||||
| ListRepeat
|
||||
| ListReverse
|
||||
|
|
|
@ -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:
|
||||
|
@ -930,6 +938,7 @@ define_builtins! {
|
|||
29 LIST_WALK_UNTIL: "walkUntil"
|
||||
30 LIST_RANGE: "range"
|
||||
31 LIST_SORT_WITH: "sortWith"
|
||||
32 LIST_DROP: "drop"
|
||||
}
|
||||
5 RESULT: "Result" => {
|
||||
0 RESULT_RESULT: "Result" imported // the Result.Result type alias
|
||||
|
|
|
@ -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" }
|
||||
|
|
614
compiler/mono/src/alias_analysis.rs
Normal file
614
compiler/mono/src/alias_analysis.rs
Normal file
|
@ -0,0 +1,614 @@
|
|||
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)
|
||||
}
|
||||
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,
|
||||
),
|
||||
HigherOrderLowLevel { .. } => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
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, &[])
|
||||
}
|
|
@ -382,7 +382,7 @@ impl<'a> BorrowInfState<'a> {
|
|||
self.own_args_using_params(arguments, ps);
|
||||
}
|
||||
|
||||
LowLevel { op } => {
|
||||
LowLevel { op, .. } => {
|
||||
debug_assert!(!op.is_higher_order());
|
||||
|
||||
self.own_var(z);
|
||||
|
@ -747,6 +747,7 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] {
|
|||
// TODO when we have lists with capacity (if ever)
|
||||
// List.append should own its first argument
|
||||
ListAppend => arena.alloc_slice_copy(&[owned, owned]),
|
||||
ListDrop => arena.alloc_slice_copy(&[owned, irrelevant]),
|
||||
|
||||
Eq | NotEq => arena.alloc_slice_copy(&[borrowed, borrowed]),
|
||||
|
||||
|
|
|
@ -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]),
|
||||
});
|
||||
|
||||
|
|
|
@ -441,7 +441,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);
|
||||
|
||||
|
@ -932,7 +932,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, &invoke_live_vars)
|
||||
}
|
||||
|
|
|
@ -777,6 +777,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> {
|
||||
|
@ -788,6 +790,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()
|
||||
}
|
||||
|
@ -1038,7 +1060,7 @@ impl<'a> Call<'a> {
|
|||
|
||||
alloc.text("CallByName ").append(alloc.intersperse(it, " "))
|
||||
}
|
||||
LowLevel { op: lowlevel } => {
|
||||
LowLevel { op: lowlevel, .. } => {
|
||||
let it = arguments.iter().map(|s| symbol_to_doc(alloc, *s));
|
||||
|
||||
alloc
|
||||
|
@ -1065,14 +1087,36 @@ 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,
|
||||
},
|
||||
Foreign {
|
||||
foreign_symbol: ForeignSymbol,
|
||||
|
@ -1080,6 +1124,7 @@ pub enum CallType<'a> {
|
|||
},
|
||||
LowLevel {
|
||||
op: LowLevel,
|
||||
update_mode: UpdateModeId,
|
||||
},
|
||||
HigherOrderLowLevel {
|
||||
op: LowLevel,
|
||||
|
@ -4329,7 +4374,10 @@ pub fn with_hole<'a>(
|
|||
}
|
||||
_ => {
|
||||
let call = self::Call {
|
||||
call_type: CallType::LowLevel { op },
|
||||
call_type: CallType::LowLevel {
|
||||
op,
|
||||
update_mode: env.next_update_mode_id(),
|
||||
},
|
||||
arguments: arg_symbols,
|
||||
};
|
||||
|
||||
|
@ -4547,8 +4595,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 {
|
||||
|
@ -5300,11 +5350,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::Foreign { .. } => None,
|
||||
CallType::LowLevel { .. } => None,
|
||||
|
@ -5774,6 +5826,7 @@ fn force_thunk<'a>(
|
|||
ret_layout: layout,
|
||||
full_layout,
|
||||
arg_layouts: &[],
|
||||
specialization_id: env.next_call_specialization_id(),
|
||||
},
|
||||
arguments: &[],
|
||||
};
|
||||
|
@ -6248,6 +6301,7 @@ fn call_by_name_help<'a>(
|
|||
ret_layout: *ret_layout,
|
||||
full_layout: function_layout,
|
||||
arg_layouts: argument_layouts,
|
||||
specialization_id: env.next_call_specialization_id(),
|
||||
},
|
||||
arguments: field_symbols,
|
||||
};
|
||||
|
@ -6280,6 +6334,7 @@ fn call_by_name_help<'a>(
|
|||
ret_layout: *ret_layout,
|
||||
full_layout: function_layout,
|
||||
arg_layouts: argument_layouts,
|
||||
specialization_id: env.next_call_specialization_id(),
|
||||
},
|
||||
arguments: field_symbols,
|
||||
};
|
||||
|
@ -6332,6 +6387,7 @@ fn call_by_name_help<'a>(
|
|||
ret_layout: *ret_layout,
|
||||
full_layout: function_layout,
|
||||
arg_layouts: argument_layouts,
|
||||
specialization_id: env.next_call_specialization_id(),
|
||||
},
|
||||
arguments: field_symbols,
|
||||
};
|
||||
|
@ -6582,6 +6638,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,
|
||||
};
|
||||
|
@ -6601,6 +6658,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,
|
||||
};
|
||||
|
@ -6624,6 +6682,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,
|
||||
};
|
||||
|
@ -7907,6 +7966,7 @@ fn union_lambda_set_branch_help<'a>(
|
|||
full_layout,
|
||||
ret_layout: return_layout,
|
||||
arg_layouts: argument_layouts,
|
||||
specialization_id: env.next_call_specialization_id(),
|
||||
},
|
||||
arguments: argument_symbols,
|
||||
}),
|
||||
|
@ -8030,6 +8090,7 @@ fn enum_lambda_set_branch<'a>(
|
|||
full_layout,
|
||||
ret_layout: return_layout,
|
||||
arg_layouts: argument_layouts,
|
||||
specialization_id: env.next_call_specialization_id(),
|
||||
},
|
||||
arguments: argument_symbols,
|
||||
}),
|
||||
|
|
|
@ -1915,3 +1915,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(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)]
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)]
|
||||
|
||||
|
|
|
@ -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)]
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)]
|
||||
|
||||
|
|
|
@ -147,6 +147,17 @@ fn list_append() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_drop() {
|
||||
assert_evals_to!(
|
||||
"List.drop [1,2,3] 2",
|
||||
RocList::from_slice(&[3]),
|
||||
RocList<i64>
|
||||
);
|
||||
assert_evals_to!("List.drop [] 1", RocList::from_slice(&[]), RocList<i64>);
|
||||
assert_evals_to!("List.drop [1,2] 5", RocList::from_slice(&[]), RocList<i64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_append_to_empty_list() {
|
||||
assert_evals_to!("List.append [] 3", RocList::from_slice(&[3]), RocList<i64>);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)]
|
||||
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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::*;
|
||||
//
|
||||
|
|
|
@ -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)]
|
||||
|
||||
|
|
|
@ -262,3 +262,15 @@ fn constrain_call_and_accessor() {
|
|||
"Str",
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn constrain_access() {
|
||||
infer_eq(
|
||||
indoc!(
|
||||
r#"
|
||||
{ foo: "bar" }.foo
|
||||
"#
|
||||
),
|
||||
"Str",
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
_ ->
|
||||
[]
|
||||
|
||||
|
|
|
@ -13,4 +13,3 @@ platform examples/shared-quicksort
|
|||
|
||||
mainForHost : List I64 -> List I64
|
||||
mainForHost = \list -> quicksort list
|
||||
|
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