From ecbbc132d37c4459a6e59a8a1e105f529aee0e1c Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Fri, 30 Mar 2018 16:39:49 +0200 Subject: [PATCH] feat(vm): Add the std.byte module --- src/import.rs | 1 + src/lib.rs | 1 + std/byte.glu | 63 +++++++++++++++++++++++++++++++++++++++ tests/pass/arithmetic.glu | 8 ++--- vm/src/primitives.rs | 22 +++++++++----- 5 files changed, 81 insertions(+), 14 deletions(-) create mode 100644 std/byte.glu diff --git a/src/import.rs b/src/import.rs index 8566770387..704a088032 100644 --- a/src/import.rs +++ b/src/import.rs @@ -70,6 +70,7 @@ static STD_LIBS: &[(&str, &str)] = &std_libs!( "bool", "float", "int", + "byte", "char", "io", "list", diff --git a/src/lib.rs b/src/lib.rs index 3c6694b659..dfb7852677 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -594,6 +594,7 @@ impl VmBuilder { .unwrap_or_else(|err| panic!("{}", err)); add_extern_module(&vm, "std.prim", ::vm::primitives::load); + add_extern_module(&vm, "std.byte.prim", ::vm::primitives::load_byte); add_extern_module(&vm, "std.int.prim", ::vm::primitives::load_int); add_extern_module(&vm, "std.float.prim", ::vm::primitives::load_float); add_extern_module(&vm, "std.string.prim", ::vm::primitives::load_string); diff --git a/std/byte.glu b/std/byte.glu new file mode 100644 index 0000000000..50c1c876ea --- /dev/null +++ b/std/byte.glu @@ -0,0 +1,63 @@ +let { Semigroup, Monoid, Group, Eq, Ord, Ordering, Num, Show } = import! std.prelude + +let additive = + let semigroup : Semigroup Byte = { + append = \x y -> x #Byte+ y + } + + let monoid : Monoid Byte = { + semigroup = semigroup, + empty = 0b, + } + + let group : Group Byte = { + monoid = monoid, + inverse = \x -> 0b #Byte- x, + } + + { semigroup, monoid, group } + +let multiplicative = + let semigroup : Semigroup Byte = { + append = \x y -> x #Byte* y + } + + let monoid : Monoid Byte = { + semigroup = semigroup, + empty = 1b, + } + + { semigroup, monoid } + +let eq : Eq Byte = { + (==) = \l r -> l #Byte== r +} + +let ord : Ord Byte = { + eq = eq, + compare = \l r -> if l #Byte< r then LT else if l #Byte== r then EQ else GT, +} + +let num : Num Byte = { + ord = ord, + (+) = additive.semigroup.append, + (-) = \l r -> l #Byte- r, + (*) = multiplicative.semigroup.append, + (/) = \l r -> l #Byte/ r, + negate = additive.group.inverse, +} + +let show : Show Byte = { + show = (import! std.prim).show_byte +} + +{ + additive, + multiplicative, + eq, + ord, + num, + show, + .. + import! std.byte.prim +} diff --git a/tests/pass/arithmetic.glu b/tests/pass/arithmetic.glu index 20a543948e..50ef3d1529 100644 --- a/tests/pass/arithmetic.glu +++ b/tests/pass/arithmetic.glu @@ -7,18 +7,16 @@ let float = import! std.float let byte @ { ? } = import! std.byte let byte_tests = - let { (+), (-), (*) } = int.num group "byte" [ test "arithmetic" <| \_ -> assert_eq 2b 2b *> assert_eq 12b (10b + 2b) *> assert_eq 123b (50b * 2b + 9b * 3b - 4b), - test "from_int" <| \_ -> assert_eq (byte.from_float 2.0) 2, - test "from_int_saturate" <| \_ -> assert_eq (byte.from_int 200) 256, + test "from_int" <| \_ -> assert_eq (byte.from_int 2) 2b, + test "from_int_truncate" <| \_ -> assert_eq (byte.from_int 2000) 208b, ] let int_tests = - let { (+), (-), (*) } = int.num group "int" [ test "arithmetic" <| \_ -> assert_eq 2 2 @@ -30,11 +28,9 @@ let int_tests = ] let float_tests = - let { (+), (-), (*) } = float.num group "float" [ test "float" <| \_ -> assert_eq 91.0 (50.0 * 2.0 - 3.0 * 3.0), test "from_int" <| \_ -> assert_eq (float.from_int 2) 2.0, - test "from_byte" <| \_ -> assert_eq (float.from_byte 2b) 2.0, ] group "arithmetic" [byte_tests, int_tests, float_tests] diff --git a/vm/src/primitives.rs b/vm/src/primitives.rs index 11feb97761..c10a48d592 100644 --- a/vm/src/primitives.rs +++ b/vm/src/primitives.rs @@ -234,6 +234,10 @@ fn show_char(c: char) -> String { format!("{}", c) } +fn show_byte(c: u8) -> String { + format!("{}", c) +} + extern "C" fn error(_: &Thread) -> Status { // We expect a string as an argument to this function but we only return Status::Error // and let the caller take care of printing the message @@ -360,9 +364,9 @@ pub fn load_byte(vm: &Thread) -> Result { min_value => std::byte::prim::min_value(), max_value => std::byte::prim::max_value(), count_ones => primitive!(1 std::byte::prim::count_ones), - count_zeroes => primitive!(1 std::byte::prim::count_zeroes), - leading_zeroes => primitive!(1 std::byte::prim::leading_zeroes), - trailing_zeroes => primitive!(1 std::byte::prim::trailing_zeroes), + count_zeros => primitive!(1 std::byte::prim::count_zeros), + leading_zeros => primitive!(1 std::byte::prim::leading_zeros), + trailing_zeros => primitive!(1 std::byte::prim::trailing_zeros), rotate_left => primitive!(2 std::byte::prim::rotate_left), rotate_right => primitive!(2 std::byte::prim::rotate_right), swap_bytes => primitive!(1 std::byte::prim::swap_bytes), @@ -371,8 +375,8 @@ pub fn load_byte(vm: &Thread) -> Result { to_be => primitive!(1 std::byte::prim::to_be), to_le => primitive!(1 std::byte::prim::to_le), pow => primitive!(2 std::byte::prim::pow), - from_float => named_primitive!(1, "std.byte.prim.from_int", |i: VmInt| i as u8), - parse => named_primitive!(1, "std.byte.prim.parse", parse::) + from_int => named_primitive!(1, "std.byte.prim.from_int", |i: VmInt| i as u8), + parse => named_primitive!(1, "std.byte.prim.parse", parse::) }, ) } @@ -386,9 +390,9 @@ pub fn load_int(vm: &Thread) -> Result { min_value => std::int::prim::min_value(), max_value => std::int::prim::max_value(), count_ones => primitive!(1 std::int::prim::count_ones), - count_zeroes => primitive!(1 std::int::prim::count_zeroes), - leading_zeroes => primitive!(1 std::int::prim::leading_zeroes), - trailing_zeroes => primitive!(1 std::int::prim::trailing_zeroes), + count_zeros => primitive!(1 std::int::prim::count_zeros), + leading_zeros => primitive!(1 std::int::prim::leading_zeros), + trailing_zeros => primitive!(1 std::int::prim::trailing_zeros), rotate_left => primitive!(2 std::int::prim::rotate_left), rotate_right => primitive!(2 std::int::prim::rotate_right), swap_bytes => primitive!(1 std::int::prim::swap_bytes), @@ -401,6 +405,7 @@ pub fn load_int(vm: &Thread) -> Result { signum => primitive!(1 std::int::prim::signum), is_positive => primitive!(1 std::int::prim::is_positive), is_negative => primitive!(1 std::int::prim::is_negative), + from_byte => named_primitive!(1, "std.int.prim.from_byte", |b: u8| b as VmInt), from_float => named_primitive!(1, "std.int.prim.from_float", |f: f64| f as VmInt), parse => named_primitive!(1, "std.int.prim.parse", parse::) }, @@ -494,6 +499,7 @@ pub fn load(vm: &Thread) -> Result { record! { show_int => primitive!(1 std::prim::show_int), show_float => primitive!(1 std::prim::show_float), + show_byte => primitive!(1 std::prim::show_byte), show_char => primitive!(1 std::prim::show_char), string_compare => named_primitive!(2, "std.prim.string_compare", str::cmp), string_eq => named_primitive!(2, "std.prim.string_eq", ::eq),