mirror of
https://github.com/roc-lang/roc.git
synced 2024-11-13 09:49:11 +03:00
Merge branch 'trunk' into str-refcount
This commit is contained in:
commit
cc0fd32f27
8
Cargo.lock
generated
8
Cargo.lock
generated
@ -2325,6 +2325,7 @@ dependencies = [
|
||||
"roc_problem",
|
||||
"roc_region",
|
||||
"roc_solve",
|
||||
"roc_std",
|
||||
"roc_types",
|
||||
"roc_unify",
|
||||
"roc_uniq",
|
||||
@ -2484,6 +2485,13 @@ dependencies = [
|
||||
"roc_unify",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "roc_std"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "roc_types"
|
||||
version = "0.1.0"
|
||||
|
@ -26,6 +26,7 @@ members = [
|
||||
"vendor/pretty",
|
||||
"editor",
|
||||
"cli",
|
||||
"roc_std",
|
||||
"docs"
|
||||
]
|
||||
|
||||
|
@ -52,3 +52,4 @@ quickcheck_macros = "0.8"
|
||||
tokio = { version = "0.2", features = ["blocking", "fs", "sync", "rt-threaded"] }
|
||||
bumpalo = { version = "3.2", features = ["collections"] }
|
||||
libc = "0.2"
|
||||
roc_std = { path = "../../roc_std" }
|
||||
|
@ -1,25 +1,19 @@
|
||||
use std::ffi::CString;
|
||||
use std::os::raw::c_char;
|
||||
use RocCallResult::*;
|
||||
|
||||
#[repr(C)]
|
||||
union Payload<T: Copy> {
|
||||
success: T,
|
||||
failure: *mut c_char,
|
||||
#[repr(u64)]
|
||||
pub enum RocCallResult<T> {
|
||||
Success(T),
|
||||
Failure(*mut c_char),
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct RocCallResult<T: Copy> {
|
||||
pub flag: u64,
|
||||
payload: Payload<T>,
|
||||
}
|
||||
|
||||
impl<T: Copy> Into<Result<T, String>> for RocCallResult<T> {
|
||||
impl<T: Sized> Into<Result<T, String>> for RocCallResult<T> {
|
||||
fn into(self) -> Result<T, String> {
|
||||
if self.flag == 0 {
|
||||
Ok(unsafe { self.payload.success })
|
||||
} else {
|
||||
Err(unsafe {
|
||||
let raw = CString::from_raw(self.payload.failure);
|
||||
match self {
|
||||
Success(value) => Ok(value),
|
||||
Failure(failure) => Err({
|
||||
let raw = unsafe { CString::from_raw(failure) };
|
||||
|
||||
let result = format!("{:?}", raw);
|
||||
|
||||
@ -27,7 +21,7 @@ impl<T: Copy> Into<Result<T, String>> for RocCallResult<T> {
|
||||
std::mem::forget(raw);
|
||||
|
||||
result
|
||||
})
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,31 +14,148 @@ mod helpers;
|
||||
#[cfg(test)]
|
||||
mod gen_list {
|
||||
use crate::helpers::with_larger_debug_stack;
|
||||
//use roc_std::roclist;
|
||||
use roc_std::RocList;
|
||||
|
||||
#[test]
|
||||
fn roc_list_construction() {
|
||||
let list = RocList::from_slice(&vec![1i64; 23]);
|
||||
assert_eq!(&list, &list);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_list_literal() {
|
||||
assert_evals_to!("[]", &[], &'static [i64]);
|
||||
assert_evals_to!("[]", RocList::from_slice(&[]), RocList<i64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn int_singleton_list_literal() {
|
||||
assert_evals_to!("[1]", &[1], &'static [i64]);
|
||||
assert_evals_to!("[1, 2]", RocList::from_slice(&[1, 2]), RocList<i64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn int_list_literal() {
|
||||
assert_evals_to!("[ 12, 9, 6, 3 ]", &[12, 9, 6, 3], &'static [i64]);
|
||||
assert_evals_to!("[ 12, 9 ]", RocList::from_slice(&[12, 9]), RocList<i64>);
|
||||
assert_evals_to!(
|
||||
"[ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 ]",
|
||||
RocList::from_slice(&(vec![1i64; 23])),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bool_list_literal() {
|
||||
// NOTE: make sure to explicitly declare the elements to be of type bool, or
|
||||
// use both True and False; only using one of them causes the list to in practice be
|
||||
// of type `List [ True ]` or `List [ False ]`, those are tag unions with one constructor
|
||||
// and not fields, and don't have a runtime representation.
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
false : Bool
|
||||
false = False
|
||||
|
||||
[ false ]
|
||||
"#
|
||||
),
|
||||
RocList::from_slice(&(vec![false; 1])),
|
||||
RocList<bool>
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
"[ True, False, True ]",
|
||||
RocList::from_slice(&[true, false, true]),
|
||||
RocList<bool>
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
false : Bool
|
||||
false = False
|
||||
|
||||
[false ]
|
||||
"#
|
||||
),
|
||||
RocList::from_slice(&(vec![false; 1])),
|
||||
RocList<bool>
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
true : Bool
|
||||
true = True
|
||||
|
||||
List.repeat 23 true
|
||||
"#
|
||||
),
|
||||
RocList::from_slice(&(vec![true; 23])),
|
||||
RocList<bool>
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
true : Bool
|
||||
true = True
|
||||
|
||||
List.repeat 23 { x: true, y: true }
|
||||
"#
|
||||
),
|
||||
RocList::from_slice(&(vec![[true, true]; 23])),
|
||||
RocList<[bool; 2]>
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
true : Bool
|
||||
true = True
|
||||
|
||||
List.repeat 23 { x: true, y: true, a: true, b: true, c: true, d : true, e: true, f: true }
|
||||
"#
|
||||
),
|
||||
RocList::from_slice(&(vec![[true, true, true, true, true, true, true, true]; 23])),
|
||||
RocList<[bool; 8]>
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn variously_sized_list_literals() {
|
||||
assert_evals_to!("[]", RocList::from_slice(&[]), RocList<i64>);
|
||||
assert_evals_to!("[1]", RocList::from_slice(&[1]), RocList<i64>);
|
||||
assert_evals_to!("[1, 2]", RocList::from_slice(&[1, 2]), RocList<i64>);
|
||||
assert_evals_to!("[1, 2, 3]", RocList::from_slice(&[1, 2, 3]), RocList<i64>);
|
||||
assert_evals_to!(
|
||||
"[1, 2, 3, 4]",
|
||||
RocList::from_slice(&[1, 2, 3, 4]),
|
||||
RocList<i64>
|
||||
);
|
||||
assert_evals_to!(
|
||||
"[1, 2, 3, 4, 5]",
|
||||
RocList::from_slice(&[1, 2, 3, 4, 5]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_append() {
|
||||
assert_evals_to!("List.append [1] 2", &[1, 2], &'static [i64]);
|
||||
assert_evals_to!("List.append [1, 1] 2", &[1, 1, 2], &'static [i64]);
|
||||
assert_evals_to!(
|
||||
"List.append [1] 2",
|
||||
RocList::from_slice(&[1, 2]),
|
||||
RocList<i64>
|
||||
);
|
||||
assert_evals_to!(
|
||||
"List.append [1, 1] 2",
|
||||
RocList::from_slice(&[1, 1, 2]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_append_to_empty_list() {
|
||||
assert_evals_to!("List.append [] 3", &[3], &'static [i64]);
|
||||
assert_evals_to!("List.append [] 3", RocList::from_slice(&[3]), RocList<i64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -53,8 +170,8 @@ mod gen_list {
|
||||
List.append (List.append initThrees 3) 3
|
||||
"#
|
||||
),
|
||||
&[3, 3],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[3, 3]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
@ -62,8 +179,8 @@ mod gen_list {
|
||||
fn list_append_bools() {
|
||||
assert_evals_to!(
|
||||
"List.append [ True, False ] True",
|
||||
&[true, false, true],
|
||||
&'static [bool]
|
||||
RocList::from_slice(&[true, false, true]),
|
||||
RocList<bool>
|
||||
);
|
||||
}
|
||||
|
||||
@ -71,15 +188,19 @@ mod gen_list {
|
||||
fn list_append_longer_list() {
|
||||
assert_evals_to!(
|
||||
"List.append [ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 ] 23",
|
||||
&[11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_prepend() {
|
||||
assert_evals_to!("List.prepend [] 1", &[1], &'static [i64]);
|
||||
assert_evals_to!("List.prepend [2] 1", &[1, 2], &'static [i64]);
|
||||
assert_evals_to!("List.prepend [] 1", RocList::from_slice(&[1]), RocList<i64>);
|
||||
assert_evals_to!(
|
||||
"List.prepend [2] 1",
|
||||
RocList::from_slice(&[1, 2]),
|
||||
RocList<i64>
|
||||
);
|
||||
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
@ -91,8 +212,8 @@ mod gen_list {
|
||||
List.prepend (List.prepend init 4) 6
|
||||
"#
|
||||
),
|
||||
&[6, 4],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[6, 4]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
@ -100,8 +221,8 @@ mod gen_list {
|
||||
fn list_prepend_bools() {
|
||||
assert_evals_to!(
|
||||
"List.prepend [ True, False ] True",
|
||||
&[true, true, false],
|
||||
&'static [bool]
|
||||
RocList::from_slice(&[true, true, false]),
|
||||
RocList<bool>
|
||||
);
|
||||
}
|
||||
|
||||
@ -109,8 +230,10 @@ mod gen_list {
|
||||
fn list_prepend_big_list() {
|
||||
assert_evals_to!(
|
||||
"List.prepend [ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 100, 100, 100, 100 ] 9",
|
||||
&[9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 100, 100, 100, 100],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[
|
||||
9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 100, 100, 100, 100
|
||||
]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
@ -153,8 +276,8 @@ mod gen_list {
|
||||
List.keepIf empty (\x -> True)
|
||||
"#
|
||||
),
|
||||
&[],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
@ -171,8 +294,8 @@ mod gen_list {
|
||||
List.keepIf [] alwaysTrue
|
||||
"#
|
||||
),
|
||||
&[],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
@ -192,8 +315,8 @@ mod gen_list {
|
||||
List.keepIf oneThroughEight alwaysTrue
|
||||
"#
|
||||
),
|
||||
&[1, 2, 3, 4, 5, 6, 7, 8],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[1, 2, 3, 4, 5, 6, 7, 8]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
@ -209,8 +332,8 @@ mod gen_list {
|
||||
List.keepIf [1,2,3,4,5,6,7,8] alwaysFalse
|
||||
"#
|
||||
),
|
||||
&[],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
@ -226,8 +349,8 @@ mod gen_list {
|
||||
List.keepIf [1,2,3,4,5,6,7,8] intIsLessThanThree
|
||||
"#
|
||||
),
|
||||
&[1, 2],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[1, 2]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
@ -246,8 +369,8 @@ mod gen_list {
|
||||
// List.keepIf ["Hello", "Hello", "Goodbye"] strIsHello
|
||||
// "#
|
||||
// ),
|
||||
// &["Hello", "Hello"],
|
||||
// &'static [&'static str]
|
||||
// RocList::from_slice(&["Hello", "Hello"]),
|
||||
// RocList<&'static str>
|
||||
// );
|
||||
// }
|
||||
|
||||
@ -263,8 +386,8 @@ mod gen_list {
|
||||
List.map empty (\x -> x)
|
||||
"#
|
||||
),
|
||||
&[],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
@ -280,8 +403,8 @@ mod gen_list {
|
||||
List.map nonEmpty (\x -> x)
|
||||
"#
|
||||
),
|
||||
&[1],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[1]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
@ -297,8 +420,8 @@ mod gen_list {
|
||||
List.map nonEmpty (\x -> x + 1)
|
||||
"#
|
||||
),
|
||||
&[2],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[2]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
@ -314,8 +437,10 @@ mod gen_list {
|
||||
List.map nonEmpty (\x -> x * 2)
|
||||
"#
|
||||
),
|
||||
&[2, 4, 6, 8, 10, 2, 4, 6, 8, 10, 2, 4, 6, 8, 10, 2, 4, 6, 8, 10, 2, 4, 6, 8, 10],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[
|
||||
2, 4, 6, 8, 10, 2, 4, 6, 8, 10, 2, 4, 6, 8, 10, 2, 4, 6, 8, 10, 2, 4, 6, 8, 10
|
||||
]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
@ -332,8 +457,8 @@ mod gen_list {
|
||||
List.map nonEmpty (\x -> x > 0)
|
||||
"#
|
||||
),
|
||||
&[true, true, false, true, true],
|
||||
&'static [bool]
|
||||
RocList::from_slice(&[true, true, false, true, true]),
|
||||
RocList<bool>
|
||||
);
|
||||
}
|
||||
|
||||
@ -353,8 +478,8 @@ mod gen_list {
|
||||
List.map nonEmpty greaterThanOne
|
||||
"#
|
||||
),
|
||||
&[true, true, false, true, true],
|
||||
&'static [bool]
|
||||
RocList::from_slice(&[true, true, false, true, true]),
|
||||
RocList<bool>
|
||||
);
|
||||
}
|
||||
|
||||
@ -366,27 +491,31 @@ mod gen_list {
|
||||
List.map [] (\x -> x > 0)
|
||||
"#
|
||||
),
|
||||
&[],
|
||||
&'static [bool]
|
||||
RocList::from_slice(&[]),
|
||||
RocList<bool>
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_join_empty_list() {
|
||||
assert_evals_to!("List.join []", &[], &'static [i64]);
|
||||
assert_evals_to!("List.join []", RocList::from_slice(&[]), RocList<i64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_join_one_list() {
|
||||
assert_evals_to!("List.join [ [1, 2, 3 ] ]", &[1, 2, 3], &'static [i64]);
|
||||
assert_evals_to!(
|
||||
"List.join [ [1, 2, 3 ] ]",
|
||||
RocList::from_slice(&[1, 2, 3]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_join_two_non_empty_lists() {
|
||||
assert_evals_to!(
|
||||
"List.join [ [1, 2, 3 ] , [4 ,5, 6] ]",
|
||||
&[1, 2, 3, 4, 5, 6],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[1, 2, 3, 4, 5, 6]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
@ -394,8 +523,8 @@ mod gen_list {
|
||||
fn list_join_two_non_empty_lists_of_float() {
|
||||
assert_evals_to!(
|
||||
"List.join [ [ 1.2, 1.1 ], [ 2.1, 2.2 ] ]",
|
||||
&[1.2, 1.1, 2.1, 2.2],
|
||||
&'static [f64]
|
||||
RocList::from_slice(&[1.2, 1.1, 2.1, 2.2]),
|
||||
RocList<f64>
|
||||
);
|
||||
}
|
||||
|
||||
@ -416,11 +545,11 @@ mod gen_list {
|
||||
]
|
||||
"#
|
||||
),
|
||||
&[
|
||||
RocList::from_slice(&[
|
||||
1.2, 1.1, 2.1, 2.2, 3.0, 4.0, 5.0, 6.1, 9.0, 3.0, 4.0, 5.0, 6.1, 9.0, 3.0, 4.0,
|
||||
5.0, 6.1, 9.0, 3.0, 4.0, 5.0, 6.1, 9.0, 3.0, 4.0, 5.0, 6.1, 9.0
|
||||
],
|
||||
&'static [f64]
|
||||
]),
|
||||
RocList<f64>
|
||||
);
|
||||
}
|
||||
|
||||
@ -436,35 +565,47 @@ mod gen_list {
|
||||
List.join [ [ 0.2, 11.11 ], empty ]
|
||||
"#
|
||||
),
|
||||
&[0.2, 11.11],
|
||||
&'static [f64]
|
||||
RocList::from_slice(&[0.2, 11.11]),
|
||||
RocList<f64>
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_join_all_empty_lists() {
|
||||
assert_evals_to!("List.join [ [], [], [] ]", &[], &'static [f64]);
|
||||
assert_evals_to!(
|
||||
"List.join [ [], [], [] ]",
|
||||
RocList::from_slice(&[]),
|
||||
RocList<f64>
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_join_one_empty_list() {
|
||||
assert_evals_to!(
|
||||
"List.join [ [ 1.2, 1.1 ], [] ]",
|
||||
&[1.2, 1.1],
|
||||
&'static [f64]
|
||||
RocList::from_slice(&[1.2, 1.1]),
|
||||
RocList<f64>
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_single() {
|
||||
assert_evals_to!("List.single 1", &[1], &'static [i64]);
|
||||
assert_evals_to!("List.single 5.6", &[5.6], &'static [f64]);
|
||||
assert_evals_to!("List.single 1", RocList::from_slice(&[1]), RocList<i64>);
|
||||
assert_evals_to!("List.single 5.6", RocList::from_slice(&[5.6]), RocList<f64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_repeat() {
|
||||
assert_evals_to!("List.repeat 5 1", &[1, 1, 1, 1, 1], &'static [i64]);
|
||||
assert_evals_to!("List.repeat 4 2", &[2, 2, 2, 2], &'static [i64]);
|
||||
assert_evals_to!(
|
||||
"List.repeat 5 1",
|
||||
RocList::from_slice(&[1, 1, 1, 1, 1]),
|
||||
RocList<i64>
|
||||
);
|
||||
assert_evals_to!(
|
||||
"List.repeat 4 2",
|
||||
RocList::from_slice(&[2, 2, 2, 2]),
|
||||
RocList<i64>
|
||||
);
|
||||
|
||||
assert_evals_to!("List.repeat 2 []", &[&[], &[]], &'static [&'static [i64]]);
|
||||
assert_evals_to!(
|
||||
@ -483,8 +624,8 @@ mod gen_list {
|
||||
|
||||
assert_evals_to!(
|
||||
"List.repeat 15 4",
|
||||
&[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
@ -492,11 +633,15 @@ mod gen_list {
|
||||
fn list_reverse() {
|
||||
assert_evals_to!(
|
||||
"List.reverse [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ]",
|
||||
&[12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]),
|
||||
RocList<i64>
|
||||
);
|
||||
assert_evals_to!("List.reverse [1, 2, 3]", &[3, 2, 1], &'static [i64]);
|
||||
assert_evals_to!("List.reverse [4]", &[4], &'static [i64]);
|
||||
assert_evals_to!(
|
||||
"List.reverse [1, 2, 3]",
|
||||
RocList::from_slice(&[3, 2, 1]),
|
||||
RocList<i64>
|
||||
);
|
||||
assert_evals_to!("List.reverse [4]", RocList::from_slice(&[4]), RocList<i64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -511,14 +656,14 @@ mod gen_list {
|
||||
List.reverse emptyList
|
||||
"#
|
||||
),
|
||||
&[],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_reverse_empty_list() {
|
||||
assert_evals_to!("List.reverse []", &[], &'static [i64]);
|
||||
assert_evals_to!("List.reverse []", RocList::from_slice(&[]), RocList<i64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -537,14 +682,14 @@ mod gen_list {
|
||||
List.concat firstList secondList
|
||||
"#
|
||||
),
|
||||
&[],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_concat_two_empty_lists() {
|
||||
assert_evals_to!("List.concat [] []", &[], &'static [i64]);
|
||||
assert_evals_to!("List.concat [] []", RocList::from_slice(&[]), RocList<i64>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -563,32 +708,40 @@ mod gen_list {
|
||||
List.concat firstList secondList
|
||||
"#
|
||||
),
|
||||
&[],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_concat_second_list_is_empty() {
|
||||
assert_evals_to!("List.concat [ 12, 13 ] []", &[12, 13], &'static [i64]);
|
||||
assert_evals_to!(
|
||||
"List.concat [ 12, 13 ] []",
|
||||
RocList::from_slice(&[12, 13]),
|
||||
RocList<i64>
|
||||
);
|
||||
assert_evals_to!(
|
||||
"List.concat [ 34, 43 ] [ 64, 55, 66 ]",
|
||||
&[34, 43, 64, 55, 66],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[34, 43, 64, 55, 66]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_concat_first_list_is_empty() {
|
||||
assert_evals_to!("List.concat [] [ 23, 24 ]", &[23, 24], &'static [i64]);
|
||||
assert_evals_to!(
|
||||
"List.concat [] [ 23, 24 ]",
|
||||
RocList::from_slice(&[23, 24]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_concat_two_non_empty_lists() {
|
||||
assert_evals_to!(
|
||||
"List.concat [1, 2 ] [ 3, 4 ]",
|
||||
&[1, 2, 3, 4],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[1, 2, 3, 4]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
@ -596,8 +749,8 @@ mod gen_list {
|
||||
fn list_concat_two_bigger_non_empty_lists() {
|
||||
assert_evals_to!(
|
||||
"List.concat [ 1.1, 2.2 ] [ 3.3, 4.4, 5.5 ]",
|
||||
&[1.1, 2.2, 3.3, 4.4, 5.5],
|
||||
&'static [f64]
|
||||
RocList::from_slice(&[1.1, 2.2, 3.3, 4.4, 5.5]),
|
||||
RocList<f64>
|
||||
);
|
||||
}
|
||||
|
||||
@ -614,12 +767,10 @@ mod gen_list {
|
||||
|
||||
expected.extend(vec2);
|
||||
|
||||
let expected_slice: &[i64] = expected.as_ref();
|
||||
|
||||
assert_evals_to!(
|
||||
&format!("List.concat {} {}", slice_str1, slice_str2),
|
||||
expected_slice,
|
||||
&'static [i64]
|
||||
RocList::from_slice(&expected),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
@ -849,8 +1000,8 @@ mod gen_list {
|
||||
fn set_unique_int_list() {
|
||||
assert_evals_to!(
|
||||
"List.set [ 12, 9, 7, 1, 5 ] 2 33",
|
||||
&[12, 9, 33, 1, 5],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[12, 9, 33, 1, 5]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
@ -858,8 +1009,8 @@ mod gen_list {
|
||||
fn set_unique_list_oob() {
|
||||
assert_evals_to!(
|
||||
"List.set [ 3, 17, 4.1 ] 1337 9.25",
|
||||
&[3.0, 17.0, 4.1],
|
||||
&'static [f64]
|
||||
RocList::from_slice(&[3.0, 17.0, 4.1]),
|
||||
RocList<f64>
|
||||
);
|
||||
}
|
||||
|
||||
@ -948,8 +1099,8 @@ mod gen_list {
|
||||
wrapLen [ 1, 7, 9 ]
|
||||
"#
|
||||
),
|
||||
&[3],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[3]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
@ -964,6 +1115,8 @@ mod gen_list {
|
||||
wrapFirst [ 1, 2 ]
|
||||
"#
|
||||
),
|
||||
// RocList::from_slice(&[1]),
|
||||
// RocList<i64>
|
||||
&[1],
|
||||
&'static [i64]
|
||||
);
|
||||
@ -986,8 +1139,8 @@ mod gen_list {
|
||||
dupe [ 1, 2 ]
|
||||
"#
|
||||
),
|
||||
&[1, 1],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[1, 1]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1009,8 +1162,8 @@ mod gen_list {
|
||||
swap 0 1 [ 1, 2 ]
|
||||
"#
|
||||
),
|
||||
&[2, 1],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[2, 1]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1061,8 +1214,8 @@ mod gen_list {
|
||||
// [ 1,3 ]
|
||||
// "#
|
||||
// ),
|
||||
// &[2, 1],
|
||||
// &'static [i64]
|
||||
// RocList::from_slice(&[2, 1]),
|
||||
// RocList<i64>
|
||||
// );
|
||||
// }
|
||||
|
||||
@ -1100,8 +1253,8 @@ mod gen_list {
|
||||
// [ 1,3 ]
|
||||
// "#
|
||||
// ),
|
||||
// &[2, 1],
|
||||
// &'static [i64]
|
||||
// RocList::from_slice(&[2, 1]),
|
||||
// RocList<i64>
|
||||
// );
|
||||
// }
|
||||
|
||||
@ -1170,8 +1323,8 @@ mod gen_list {
|
||||
quicksort [ 7, 4, 21, 19 ]
|
||||
"#
|
||||
),
|
||||
&[4, 7, 19, 21],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[4, 7, 19, 21]),
|
||||
RocList<i64>
|
||||
);
|
||||
})
|
||||
}
|
||||
@ -1243,8 +1396,8 @@ mod gen_list {
|
||||
quicksort [ 7, 4, 21, 19 ]
|
||||
"#
|
||||
),
|
||||
&[19, 7, 4, 21],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[19, 7, 4, 21]),
|
||||
RocList<i64>
|
||||
);
|
||||
})
|
||||
}
|
||||
@ -1368,8 +1521,8 @@ mod gen_list {
|
||||
id x
|
||||
"#
|
||||
),
|
||||
&[1, 2, 3],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[1, 2, 3]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1387,8 +1540,8 @@ mod gen_list {
|
||||
id x
|
||||
"#
|
||||
),
|
||||
&[0, 2, 3],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[0, 2, 3]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1404,8 +1557,8 @@ mod gen_list {
|
||||
Pair v _ -> v
|
||||
"#
|
||||
),
|
||||
&[1, 2, 3],
|
||||
&'static [i64]
|
||||
RocList::from_slice(&[1, 2, 3]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -396,7 +396,11 @@ macro_rules! assert_llvm_evals_to {
|
||||
let (main_fn_name, errors, execution_engine) =
|
||||
$crate::helpers::eval::helper_without_uniqueness(&arena, $src, $leak, &context);
|
||||
|
||||
let transform = |success| assert_eq!($transform(success), $expected);
|
||||
let transform = |success| {
|
||||
let expected = $expected;
|
||||
let given = $transform(success);
|
||||
assert_eq!(&given, &expected);
|
||||
};
|
||||
run_jit_function!(execution_engine, main_fn_name, $ty, transform, errors)
|
||||
};
|
||||
|
||||
|
12
roc_std/Cargo.toml
Normal file
12
roc_std/Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "roc_std"
|
||||
version = "0.1.0"
|
||||
authors = ["Richard Feldman <oss@rtfeldman.com>"]
|
||||
repository = "https://github.com/rtfeldman/roc"
|
||||
readme = "README.md"
|
||||
edition = "2018"
|
||||
description = "Rust representations of Roc data structures"
|
||||
license = "Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
libc = "0.2"
|
221
roc_std/src/lib.rs
Normal file
221
roc_std/src/lib.rs
Normal file
@ -0,0 +1,221 @@
|
||||
#![crate_type = "lib"]
|
||||
#![no_std]
|
||||
use core::fmt;
|
||||
|
||||
// A list of C functions that are being imported
|
||||
extern "C" {
|
||||
pub fn printf(format: *const u8, ...) -> i32;
|
||||
}
|
||||
|
||||
const REFCOUNT_1: usize = isize::MIN as usize;
|
||||
|
||||
//#[macro_export]
|
||||
//macro_rules! roclist {
|
||||
// () => (
|
||||
// $crate::RocList::empty()
|
||||
// );
|
||||
// ($($x:expr),+ $(,)?) => (
|
||||
// $crate::RocList::from_slice(&[$($x),+])
|
||||
// );
|
||||
//}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct RocList<T> {
|
||||
elements: *mut T,
|
||||
length: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Storage {
|
||||
ReadOnly,
|
||||
Refcounted(usize),
|
||||
Capacity(usize),
|
||||
}
|
||||
|
||||
impl<T> RocList<T> {
|
||||
pub fn len(&self) -> usize {
|
||||
self.length
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.length == 0
|
||||
}
|
||||
|
||||
pub fn empty() -> Self {
|
||||
RocList {
|
||||
length: 0,
|
||||
elements: core::ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self, index: usize) -> Option<&T> {
|
||||
if index < self.len() {
|
||||
Some(unsafe {
|
||||
let raw = self.elements.add(index);
|
||||
|
||||
&*raw
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn storage(&self) -> Option<Storage> {
|
||||
use core::cmp::Ordering::*;
|
||||
|
||||
if self.length == 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let value = *self.get_storage_ptr();
|
||||
|
||||
// NOTE doesn't work with elements of 16 or more bytes
|
||||
match usize::cmp(&0, &value) {
|
||||
Equal => Some(Storage::ReadOnly),
|
||||
Less => Some(Storage::Refcounted(value)),
|
||||
Greater => Some(Storage::Capacity(value)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_storage_ptr(&self) -> *const usize {
|
||||
let elem_alignment = core::mem::align_of::<T>();
|
||||
|
||||
unsafe {
|
||||
if elem_alignment <= core::mem::align_of::<usize>() {
|
||||
let ptr = self.elements as *const usize;
|
||||
ptr.offset(-1)
|
||||
} else {
|
||||
let ptr = self.elements as *const (usize, usize);
|
||||
(ptr.offset(-1)) as *const usize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_storage_ptr_mut(&mut self) -> *mut usize {
|
||||
self.get_storage_ptr() as *mut usize
|
||||
}
|
||||
|
||||
fn get_element_ptr<Q>(elements: *const Q) -> *const usize {
|
||||
let elem_alignment = core::mem::align_of::<T>();
|
||||
|
||||
unsafe {
|
||||
if elem_alignment <= core::mem::align_of::<usize>() {
|
||||
let ptr = elements as *const usize;
|
||||
ptr.offset(1)
|
||||
} else {
|
||||
let ptr = elements as *const (usize, usize);
|
||||
(ptr.offset(1)) as *const usize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_slice_with_capacity(slice: &[T], capacity: usize) -> RocList<T>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
assert!(slice.len() <= capacity);
|
||||
|
||||
let ptr = slice.as_ptr();
|
||||
let element_bytes = capacity * core::mem::size_of::<T>();
|
||||
|
||||
let padding = {
|
||||
if core::mem::align_of::<T>() <= core::mem::align_of::<usize>() {
|
||||
// aligned on usize (8 bytes on 64-bit systems)
|
||||
0
|
||||
} else {
|
||||
// aligned on 2*usize (16 bytes on 64-bit systems)
|
||||
core::mem::size_of::<usize>()
|
||||
}
|
||||
};
|
||||
|
||||
let num_bytes = core::mem::size_of::<usize>() + padding + element_bytes;
|
||||
|
||||
let elements = unsafe {
|
||||
let raw_ptr = libc::malloc(num_bytes);
|
||||
|
||||
// write the capacity
|
||||
let capacity_ptr = raw_ptr as *mut usize;
|
||||
*capacity_ptr = capacity;
|
||||
|
||||
let raw_ptr = Self::get_element_ptr(raw_ptr as *mut T);
|
||||
|
||||
{
|
||||
// NOTE: using a memcpy here causes weird issues
|
||||
let target_ptr = raw_ptr as *mut T;
|
||||
let source_ptr = ptr as *const T;
|
||||
let length = slice.len() as isize;
|
||||
for index in 0..length {
|
||||
*target_ptr.offset(index) = *source_ptr.offset(index);
|
||||
}
|
||||
}
|
||||
|
||||
raw_ptr as *mut T
|
||||
};
|
||||
|
||||
RocList {
|
||||
length: slice.len(),
|
||||
elements,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_slice(slice: &[T]) -> RocList<T>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
Self::from_slice_with_capacity(slice, slice.len())
|
||||
}
|
||||
|
||||
pub fn as_slice(&self) -> &[T] {
|
||||
unsafe { core::slice::from_raw_parts(self.elements, self.length) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Debug> fmt::Debug for RocList<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// RocList { storage: Refcounted(3), elements: [ 1,2,3,4] }
|
||||
f.debug_struct("RocList")
|
||||
.field("storage", &self.storage())
|
||||
.field("elements", &self.as_slice())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PartialEq> PartialEq for RocList<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
if self.length != other.length {
|
||||
return false;
|
||||
}
|
||||
|
||||
for i in 0..(self.length as isize) {
|
||||
unsafe {
|
||||
if *self.elements.offset(i) != *other.elements.offset(i) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Eq> Eq for RocList<T> {}
|
||||
|
||||
impl<T> Drop for RocList<T> {
|
||||
fn drop(&mut self) {
|
||||
use Storage::*;
|
||||
match self.storage() {
|
||||
None | Some(ReadOnly) => {}
|
||||
Some(Capacity(_)) | Some(Refcounted(REFCOUNT_1)) => unsafe {
|
||||
libc::free(self.get_storage_ptr() as *mut libc::c_void);
|
||||
},
|
||||
Some(Refcounted(rc)) => {
|
||||
let sptr = self.get_storage_ptr_mut();
|
||||
unsafe {
|
||||
*sptr = rc - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user