From 12509b2c5458a04b8a8cb243dcc08582c02b5366 Mon Sep 17 00:00:00 2001 From: Enrico Zandomeni Borba Date: Wed, 3 Apr 2024 12:57:10 -0400 Subject: [PATCH 01/11] whitespace --- src/run/interact.rs | 48 ++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/run/interact.rs b/src/run/interact.rs index 6b0b37eb..0781d20f 100644 --- a/src/run/interact.rs +++ b/src/run/interact.rs @@ -46,7 +46,7 @@ impl<'a, M: Mode> Net<'a, M> { /// Annihilates two binary agents. /// /// ```text - /// + /// /// a2 | | a1 /// _|___|_ /// \ / @@ -68,7 +68,7 @@ impl<'a, M: Mode> Net<'a, M> { /// / \ /// | | /// b1 | | b2 - /// + /// /// ``` #[inline(never)] pub fn anni2(&mut self, a: Port, b: Port) { @@ -83,7 +83,7 @@ impl<'a, M: Mode> Net<'a, M> { /// Commutes two binary agents. /// /// ```text - /// + /// /// a2 | | a1 /// _|___|_ /// \ / @@ -115,7 +115,7 @@ impl<'a, M: Mode> Net<'a, M> { /// \ / \ / /// | | /// b1 | | b2 - /// + /// /// ``` #[inline(never)] pub fn comm22(&mut self, a: Port, b: Port) { @@ -146,7 +146,7 @@ impl<'a, M: Mode> Net<'a, M> { /// Commutes a nilary agent and a binary agent. /// /// ```text - /// + /// /// a (---) /// | /// | @@ -161,7 +161,7 @@ impl<'a, M: Mode> Net<'a, M> { /// a (---) (---) a /// | | /// b1 | | b2 - /// + /// /// ``` #[inline(never)] pub fn comm02(&mut self, a: Port, b: Port) { @@ -229,27 +229,27 @@ impl<'a, M: Mode> Net<'a, M> { /// Interacts a number and a binary numeric operation node. /// /// ```text - /// | - /// b (n) | b (n) - /// | | | - /// | | | - /// / \ | / \ - /// a /op \ | a /op \ - /// /_____\ | /_____\ - /// | | | | | - /// (m) | a2 | a1 | | a2 - /// | + /// | + /// b (n) | b (n) + /// | | | + /// | | | + /// / \ | / \ + /// a /op \ | a /op \ + /// /_____\ | /_____\ + /// | | | | | + /// (m) | a2 | a1 | | a2 + /// | /// --------------------------- | --------------------------- op_num /// | _ _ _ /// | / \ - /// | | (n) | - /// | _|___|_ | - /// | \ / | - /// | x \op$/ | - /// (n op m) | \ / | - /// | | | | - /// | a2 | a1 | | a2 - /// | + /// | | (n) | + /// | _|___|_ | + /// | \ / | + /// | x \op$/ | + /// (n op m) | \ / | + /// | | | | + /// | a2 | a1 | | a2 + /// | /// ``` #[inline(never)] pub fn op_num(&mut self, a: Port, b: Port) { From a9a1332ac18da6625274bf50cbfa7c11fd6fbf4b Mon Sep 17 00:00:00 2001 From: Enrico Zandomeni Borba Date: Thu, 4 Apr 2024 06:44:18 -0400 Subject: [PATCH 02/11] variable-width integer operations --- src/ast.rs | 14 ++- src/compile.rs | 2 +- src/host/encode.rs | 6 +- src/ops.rs | 236 +++++++++++++++++++++++++++--------- src/run/instruction.rs | 10 +- src/run/interact.rs | 13 +- src/run/port.rs | 10 +- src/trace.rs | 2 +- src/transform/eta_reduce.rs | 2 +- tests/numeric.rs | 40 +++--- 10 files changed, 231 insertions(+), 104 deletions(-) diff --git a/src/ast.rs b/src/ast.rs index 3179dcb1..ad89d1bf 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -57,7 +57,7 @@ pub enum Tree { /// A nilary eraser node. Era, /// A native 60-bit integer. - Num { val: u64 }, + Num { val: i64 }, /// A nilary node, referencing a named net. Ref { nam: String }, /// A n-ary interaction combinator. @@ -303,9 +303,15 @@ impl<'i> Parser<'i> { // Num = "#" Int Some('#') => { self.advance_char(); - Ok(Tree::Num { val: self.parse_int()? }) + match self.peek_char() { + Some('-') => { + self.advance_char(); + Ok(Tree::Num { val: -(self.parse_int()? as i64) }) + } + _ => Ok(Tree::Num { val: self.parse_int()? as i64 }), + } } - // Op = "<" Op Tree Tree ">" | "<" Int Op Tree ">" + // Op = "<" Op Tree Tree ">" Some('<') => { self.advance_char(); let op = self.parse_op()?; @@ -372,7 +378,7 @@ impl<'i> Parser<'i> { /// See `ops.rs` for the available operators. fn parse_op(&mut self) -> Result { - let op = self.take_while(|c| "+-=*/%<>|&^!?$".contains(c)); + let op = self.take_while(|c| "ui81632.+-=*/%<>|&^!?$".contains(c)); op.parse().map_err(|_| format!("Unknown operator: {op:?}")) } diff --git a/src/compile.rs b/src/compile.rs index c02c9287..dae5eb9c 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -23,7 +23,7 @@ fn _compile_host(host: &Host) -> Result { .map(|(raw_name, def)| (raw_name, sanitize_name(raw_name), def)); writeln!(code, "#![allow(non_upper_case_globals, unused_imports)]")?; - writeln!(code, "use crate::{{host::{{Host, DefRef}}, run::*, ops::Op::*}};")?; + writeln!(code, "use crate::{{host::{{Host, DefRef}}, run::*, ops::{{Op, Ty::*, IntOp::*}}}};")?; writeln!(code)?; writeln!(code, "pub fn host() -> Host {{")?; diff --git a/src/host/encode.rs b/src/host/encode.rs index 31bd7717..cff8ce2d 100644 --- a/src/host/encode.rs +++ b/src/host/encode.rs @@ -126,7 +126,7 @@ trait Encoder { fn make_const(&mut self, port: Port) -> Self::Trg; fn ctr(&mut self, lab: Lab, trg: Self::Trg) -> (Self::Trg, Self::Trg); fn op(&mut self, op: Op, trg: Self::Trg) -> (Self::Trg, Self::Trg); - fn op_num(&mut self, op: Op, trg: Self::Trg, rhs: u64) -> Self::Trg; + fn op_num(&mut self, op: Op, trg: Self::Trg, rhs: i64) -> Self::Trg; fn mat(&mut self, trg: Self::Trg) -> (Self::Trg, Self::Trg); fn wires(&mut self) -> (Self::Trg, Self::Trg, Self::Trg, Self::Trg); } @@ -164,7 +164,7 @@ impl Encoder for InterpretedDef { self.instr.push(Instruction::Op { op, trg, rhs, out }); (rhs, out) } - fn op_num(&mut self, op: Op, trg: Self::Trg, rhs: u64) -> Self::Trg { + fn op_num(&mut self, op: Op, trg: Self::Trg, rhs: i64) -> Self::Trg { let out = self.new_trg_id(); self.instr.push(Instruction::OpNum { op, trg, rhs, out }); out @@ -202,7 +202,7 @@ impl<'a, M: Mode> Encoder for run::Net<'a, M> { fn op(&mut self, op: Op, trg: Self::Trg) -> (Self::Trg, Self::Trg) { self.do_op(op, trg) } - fn op_num(&mut self, op: Op, trg: Self::Trg, rhs: u64) -> Self::Trg { + fn op_num(&mut self, op: Op, trg: Self::Trg, rhs: i64) -> Self::Trg { self.do_op_num(op, trg, rhs) } fn mat(&mut self, trg: Self::Trg) -> (Self::Trg, Self::Trg) { diff --git a/src/ops.rs b/src/ops.rs index 5f5c3ba4..dd0e88d2 100644 --- a/src/ops.rs +++ b/src/ops.rs @@ -1,30 +1,79 @@ use crate::util::bi_enum; +use std::{ + cmp::{Eq, Ord}, + fmt::Display, + str::FromStr, +}; + +trait Num: Eq + Ord + Sized { + const ZERO: Self; + const ONE: Self; + + fn add(a: Self, b: Self) -> Self; + fn sub(a: Self, b: Self) -> Self; + fn mul(a: Self, b: Self) -> Self; + fn div(a: Self, b: Self) -> Self; + fn rem(a: Self, b: Self) -> Self; + fn and(a: Self, b: Self) -> Self; + fn or(a: Self, b: Self) -> Self; + fn xor(a: Self, b: Self) -> Self; + fn shl(a: Self, b: Self) -> Self; + fn shr(a: Self, b: Self) -> Self; + + fn from_bool(b: bool) -> Self { + if b { Self::ONE } else { Self::ZERO } + } +} + +macro_rules! impl_num { + ( $($ty:ty),+ ) => { + $( + impl Num for $ty { + const ZERO: $ty = 0; + const ONE: $ty = 1; + + fn add(a: $ty, b: $ty) -> $ty { a.wrapping_add(b) } + fn sub(a: $ty, b: $ty) -> $ty { a.wrapping_sub(b) } + fn mul(a: $ty, b: $ty) -> $ty { a.wrapping_mul(b) } + fn div(a: $ty, b: $ty) -> $ty { a.checked_div(b).unwrap_or(0) } + fn rem(a: $ty, b: $ty) -> $ty { a.checked_rem(b).unwrap_or(0) } + fn and(a: $ty, b: $ty) -> $ty { a & b } + fn or(a: $ty, b: $ty) -> $ty { a | b } + fn xor(a: $ty, b: $ty) -> $ty { a ^ b } + fn shl(a: $ty, b: $ty) -> $ty { a.wrapping_shl(b as u32) } + fn shr(a: $ty, b: $ty) -> $ty { a.wrapping_shr(b as u32) } + } + )* + } +} + +impl_num! { u8, u16, u32, u64, i8, i16, i32 } bi_enum! { - #[repr(u16)] - /// A native operation on 60-bit integers. + #[repr(u8)] + /// Native operations on variable-width integers. /// /// Each operation has a swapped counterpart (accessible with `.swap()`), /// where the order of the operands is swapped. /// /// Operations without an already-named counterpart (e.g. `Add <-> Add` and /// `Lt <-> Gt`) are suffixed with `$`/`S`: `(-$ 1 2) = (- 2 1) = 1`. - #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] - pub enum Op { + #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub enum IntOp { "+": Add = 0, "-": Sub = 1, "-$": SubS = 2, "*": Mul = 3, "/": Div = 4, "/$": DivS = 5, - "%": Mod = 6, - "%$": ModS = 7, + "%": Rem = 6, + "%$": RemS = 7, "==": Eq = 8, "!=": Ne = 9, "<": Lt = 10, ">": Gt = 11, - "<=": Lte = 12, - ">=": Gte = 13, + "<=": Le = 12, + ">=": Ge = 13, "&": And = 14, "|": Or = 15, "^": Xor = 16, @@ -35,63 +84,136 @@ bi_enum! { } } -use Op::*; - -impl Op { +impl IntOp { /// Returns this operation's swapped counterpart. /// /// For all `op, a, b`, `op.swap().op(a, b) == op.op(b, a)`. #[inline] - pub fn swap(self) -> Self { + fn swap(self) -> Self { match self { - Add => Add, - Sub => SubS, - SubS => Sub, - Mul => Mul, - Div => DivS, - DivS => Div, - Mod => ModS, - ModS => Mod, - Eq => Eq, - Ne => Ne, - Lt => Gt, - Gt => Lt, - Lte => Gte, - Gte => Lte, - And => And, - Or => Or, - Xor => Xor, - Shl => ShlS, - ShlS => Shl, - Shr => ShrS, - ShrS => Shr, + Self::Add => Self::Add, + Self::Sub => Self::SubS, + Self::SubS => Self::Sub, + Self::Mul => Self::Mul, + Self::Div => Self::DivS, + Self::DivS => Self::Div, + Self::Rem => Self::RemS, + Self::RemS => Self::Rem, + Self::Eq => Self::Eq, + Self::Ne => Self::Ne, + Self::Lt => Self::Gt, + Self::Gt => Self::Lt, + Self::Le => Self::Ge, + Self::Ge => Self::Le, + Self::And => Self::And, + Self::Or => Self::Or, + Self::Xor => Self::Xor, + Self::Shl => Self::ShlS, + Self::ShlS => Self::Shl, + Self::Shr => Self::ShrS, + Self::ShrS => Self::Shr, } } - #[inline] - pub fn op(self, a: u64, b: u64) -> u64 { - const U60: u64 = 0xFFF_FFFF_FFFF_FFFF; + + fn op(self, a: T, b: T) -> T { match self { - Add => a.wrapping_add(b) & U60, - Sub => a.wrapping_sub(b) & U60, - SubS => b.wrapping_sub(a) & U60, - Mul => a.wrapping_mul(b) & U60, - Div => a.checked_div(b).unwrap_or(0), - DivS => b.checked_div(a).unwrap_or(0), - Mod => a.checked_rem(b).unwrap_or(0), - ModS => b.checked_rem(a).unwrap_or(0), - Eq => (a == b) as u64, - Ne => (a != b) as u64, - Lt => (a < b) as u64, - Gt => (a > b) as u64, - Lte => (a <= b) as u64, - Gte => (a >= b) as u64, - And => a & b, - Or => a | b, - Xor => a ^ b, - Shl => (a << b) & U60, - ShlS => (b << a) & U60, - Shr => a >> b, - ShrS => b >> a, + Self::Add => T::add(a, b), + Self::Sub => T::sub(a, b), + Self::SubS => T::sub(b, a), + Self::Mul => T::mul(a, b), + Self::Div => T::div(a, b), + Self::DivS => T::div(b, a), + Self::Rem => T::rem(a, b), + Self::RemS => T::rem(b, a), + Self::Eq => T::from_bool(a == b), + Self::Ne => T::from_bool(a != b), + Self::Lt => T::from_bool(a < b), + Self::Le => T::from_bool(a <= b), + Self::Gt => T::from_bool(a > b), + Self::Ge => T::from_bool(a >= b), + Self::And => T::and(a, b), + Self::Or => T::or(a, b), + Self::Xor => T::xor(a, b), + Self::Shl => T::shl(a, b), + Self::ShlS => T::shl(b, a), + Self::Shr => T::shr(a, b), + Self::ShrS => T::shr(b, a), + } + } +} + +bi_enum! { + #[repr(u8)] + #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub enum Ty { + "u8": U8 = 0, + "u16": U16 = 1, + "u32": U32 = 2, + "u60": U60 = 3, + "i8": I8 = 4, + "i16": I16 = 5, + "i32": I32 = 6, + } +} + +#[repr(C)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Op { + pub ty: Ty, + pub op: IntOp, +} + +impl From for Op { + fn from(value: u16) -> Self { + unsafe { std::mem::transmute(value) } + } +} + +impl From for u16 { + fn from(op: Op) -> Self { + unsafe { std::mem::transmute(op) } + } +} + +impl Display for Op { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self.ty { + Ty::U60 => write!(f, "{}", self.op), + _ => write!(f, "{}.{}", self.ty, self.op), + } + } +} + +impl FromStr for Op { + type Err = (); + + fn from_str(s: &str) -> Result { + match s.split('.').collect::>().as_slice() { + [ty, op] => Ok(Self { ty: Ty::from_str(ty)?, op: IntOp::from_str(op)? }), + [op] => Ok(Self { ty: Ty::U60, op: IntOp::from_str(op)? }), + + _ => Err(()), + } + } +} + +impl Op { + pub fn swap(self) -> Self { + Self { op: self.op.swap(), ty: self.ty } + } + + #[inline] + pub fn op(self, a: i64, b: i64) -> i64 { + const U60: i64 = 0xFFF_FFFF_FFFF_FFFF; + + match self.ty { + Ty::U8 => self.op.op(a as u8, b as u8) as i64, + Ty::U16 => self.op.op(a as u16, b as u16) as i64, + Ty::U32 => self.op.op(a as u32, b as u32) as i64, + Ty::U60 => self.op.op(a as u64, b as u64) as i64 & U60, + Ty::I8 => self.op.op(a as i8, b as i8) as i64, + Ty::I16 => self.op.op(a as i16, b as i16) as i64, + Ty::I32 => self.op.op(a as i32, b as i32) as i64, } } } diff --git a/src/run/instruction.rs b/src/run/instruction.rs index b0090f38..4390eb11 100644 --- a/src/run/instruction.rs +++ b/src/run/instruction.rs @@ -58,7 +58,7 @@ pub enum Instruction { /// ```rust,ignore /// let out = net.do_op_num(lab, trg, rhs); /// ``` - OpNum { op: Op, trg: TrgId, rhs: u64, out: TrgId }, + OpNum { op: Op, trg: TrgId, rhs: i64, out: TrgId }, /// See [`Net::do_mat`]. /// ```rust,ignore /// let (lft, rgt) = net.do_mat(trg); @@ -137,14 +137,14 @@ impl<'a, M: Mode> Net<'a, M> { let port = trg.target(); if !M::LAZY && port.tag() == Num { self.free_trg(trg); - let n = self.create_node(Op, op.swap() as Lab); + let n = self.create_node(Op, op.swap().into()); n.p1.wire().set_target(Port::new_num(port.num())); (Trg::port(n.p0), Trg::port(n.p2)) } else if !M::LAZY && port == Port::ERA { self.free_trg(trg); (Trg::port(Port::ERA), Trg::port(Port::ERA)) } else { - let n = self.create_node(Op, op as Lab); + let n = self.create_node(Op, op.into()); self.link_trg_port(trg, n.p0); (Trg::port(n.p1), Trg::port(n.p2)) } @@ -152,7 +152,7 @@ impl<'a, M: Mode> Net<'a, M> { /// `trg ~ ` #[inline(always)] - pub(crate) fn do_op_num(&mut self, op: Op, trg: Trg, rhs: u64) -> Trg { + pub(crate) fn do_op_num(&mut self, op: Op, trg: Trg, rhs: i64) -> Trg { let port = trg.target(); if !M::LAZY && port.tag() == Num { self.rwts.oper += 1; @@ -162,7 +162,7 @@ impl<'a, M: Mode> Net<'a, M> { self.free_trg(trg); Trg::port(Port::ERA) } else { - let n = self.create_node(Op, op as Lab); + let n = self.create_node(Op, op.into()); self.link_trg_port(trg, n.p0); n.p1.wire().set_target(Port::new_num(rhs)); Trg::port(n.p2) diff --git a/src/run/interact.rs b/src/run/interact.rs index 0781d20f..e7f48c7a 100644 --- a/src/run/interact.rs +++ b/src/run/interact.rs @@ -46,7 +46,7 @@ impl<'a, M: Mode> Net<'a, M> { /// Annihilates two binary agents. /// /// ```text - /// + /// /// a2 | | a1 /// _|___|_ /// \ / @@ -68,7 +68,6 @@ impl<'a, M: Mode> Net<'a, M> { /// / \ /// | | /// b1 | | b2 - /// /// ``` #[inline(never)] pub fn anni2(&mut self, a: Port, b: Port) { @@ -83,7 +82,7 @@ impl<'a, M: Mode> Net<'a, M> { /// Commutes two binary agents. /// /// ```text - /// + /// /// a2 | | a1 /// _|___|_ /// \ / @@ -115,7 +114,6 @@ impl<'a, M: Mode> Net<'a, M> { /// \ / \ / /// | | /// b1 | | b2 - /// /// ``` #[inline(never)] pub fn comm22(&mut self, a: Port, b: Port) { @@ -146,7 +144,7 @@ impl<'a, M: Mode> Net<'a, M> { /// Commutes a nilary agent and a binary agent. /// /// ```text - /// + /// /// a (---) /// | /// | @@ -161,7 +159,6 @@ impl<'a, M: Mode> Net<'a, M> { /// a (---) (---) a /// | | /// b1 | | b2 - /// /// ``` #[inline(never)] pub fn comm02(&mut self, a: Port, b: Port) { @@ -255,7 +252,7 @@ impl<'a, M: Mode> Net<'a, M> { pub fn op_num(&mut self, a: Port, b: Port) { trace!(self.tracer, a, b); let a = a.consume_node(); - let op = unsafe { Op::from_unchecked(a.lab) }; + let op = Op::from(a.lab); let a1 = a.p1.load_target(); if a1.tag() == Num { self.rwts.oper += 1; @@ -264,7 +261,7 @@ impl<'a, M: Mode> Net<'a, M> { self.link_wire_port(a.p2, Port::new_num(out)); } else { let op = op.swap(); - let x = self.create_node(Op, op as u16); + let x = self.create_node(Op, op.into()); trace!(self.tracer, x.p0); self.link_port_port(x.p1, b); self.link_wire_port(a.p2, x.p2); diff --git a/src/run/port.rs b/src/run/port.rs index 34e6da95..d77ad3dc 100644 --- a/src/run/port.rs +++ b/src/run/port.rs @@ -130,8 +130,8 @@ impl Port { /// Creates a new [`Num`] port with a given 60-bit numeric value. #[inline(always)] - pub const fn new_num(val: u64) -> Self { - Port((val << 4) | (Num as u64)) + pub const fn new_num(val: i64) -> Self { + Port((val << 4) as u64 | (Num as u64)) } /// Creates a new [`Ref`] port corresponding to a given definition. @@ -167,13 +167,13 @@ impl Port { /// ports. #[inline(always)] pub fn op(&self) -> Op { - unsafe { Op::from_unchecked(self.lab()) } + self.lab().into() } /// Accesses the numeric value of this port; this is valid for [`Num`] ports. #[inline(always)] - pub const fn num(&self) -> u64 { - self.0 >> 4 + pub const fn num(&self) -> i64 { + (self.0 >> 4) as i64 } /// Accesses the wire leaving this port; this is valid for [`Var`] ports and diff --git a/src/trace.rs b/src/trace.rs index 7bb961d1..8905d1cb 100644 --- a/src/trace.rs +++ b/src/trace.rs @@ -362,7 +362,7 @@ impl TraceArg for Trg { impl TraceArg for Op { fn to_word(&self) -> u64 { - *self as u64 + u16::from(*self) as u64 } fn from_word(word: u64) -> impl Debug { unsafe { Op::try_from(word as u16).unwrap_unchecked() } diff --git a/src/transform/eta_reduce.rs b/src/transform/eta_reduce.rs index b057f50a..11745145 100644 --- a/src/transform/eta_reduce.rs +++ b/src/transform/eta_reduce.rs @@ -75,7 +75,7 @@ impl Net { enum NodeType { Ctr(u16), Var(isize), - Num(u64), + Num(i64), Era, Other, Hole, diff --git a/tests/numeric.rs b/tests/numeric.rs index cfa03578..3560016f 100644 --- a/tests/numeric.rs +++ b/tests/numeric.rs @@ -1,21 +1,23 @@ use hvmc::{ ast::{Book, Net}, - ops::Op, + ops::IntOp, }; use insta::{assert_debug_snapshot, assert_snapshot}; use loaders::*; mod loaders; -fn op_net(lnum: u32, op: Op, rnum: u32) -> Book { - let code = format!("@main = root & #{lnum} ~ <{op} #{rnum} root>"); +fn op_net_u32(lnum: u32, op: IntOp, rnum: u32) -> Book { + let code = format!("@main = root & #{lnum} ~ "); println!("Code: {code:?}"); parse_core(&code) } +use IntOp::*; + #[test] fn test_add() { - let net = op_net(10, Op::Add, 2); + let net = op_net_u32(10, Add, 2); let (rwts, net) = normal(net, Some(128)); assert_snapshot!(Net::to_string(&net), @"#12"); assert_debug_snapshot!(rwts.total(), @"3"); @@ -23,98 +25,98 @@ fn test_add() { #[test] fn test_sub() { - let net = op_net(10, Op::Sub, 2); + let net = op_net_u32(10, Sub, 2); let (_rwts, net) = normal(net, Some(128)); assert_snapshot!(Net::to_string(&net), @"#8"); } #[test] fn test_mul() { - let net = op_net(10, Op::Mul, 2); + let net = op_net_u32(10, Mul, 2); let (_rwts, net) = normal(net, Some(128)); assert_snapshot!(Net::to_string(&net), @"#20"); } #[test] fn test_div() { - let net = op_net(10, Op::Div, 2); + let net = op_net_u32(10, Div, 2); let (_rwts, net) = normal(net, Some(128)); assert_snapshot!(Net::to_string(&net), @"#5"); } #[test] -fn test_mod() { - let net = op_net(10, Op::Mod, 2); +fn test_rem() { + let net = op_net_u32(10, Rem, 2); let (_rwts, net) = normal(net, Some(128)); assert_snapshot!(Net::to_string(&net), @"#0"); } #[test] fn test_eq() { - let net = op_net(10, Op::Eq, 2); + let net = op_net_u32(10, Eq, 2); let (_rwts, net) = normal(net, Some(128)); assert_snapshot!(Net::to_string(&net), @"#0"); } #[test] fn test_ne() { - let net = op_net(10, Op::Ne, 2); + let net = op_net_u32(10, Ne, 2); let (_rwts, net) = normal(net, Some(128)); assert_snapshot!(Net::to_string(&net), @"#1"); } #[test] fn test_lt() { - let net = op_net(10, Op::Lt, 2); + let net = op_net_u32(10, Lt, 2); let (_rwts, net) = normal(net, Some(128)); assert_snapshot!(Net::to_string(&net), @"#0"); } #[test] fn test_gt() { - let net = op_net(10, Op::Gt, 2); + let net = op_net_u32(10, Gt, 2); let (_rwts, net) = normal(net, Some(128)); assert_snapshot!(Net::to_string(&net), @"#1"); } #[test] fn test_and() { - let net = op_net(10, Op::And, 2); + let net = op_net_u32(10, And, 2); let (_rwts, net) = normal(net, Some(128)); assert_snapshot!(Net::to_string(&net), @"#2"); } #[test] fn test_or() { - let net = op_net(10, Op::Or, 2); + let net = op_net_u32(10, Or, 2); let (_rwts, net) = normal(net, Some(128)); assert_snapshot!(Net::to_string(&net), @"#10"); } #[test] fn test_xor() { - let net = op_net(10, Op::Xor, 2); + let net = op_net_u32(10, Xor, 2); let (_rwts, net) = normal(net, Some(128)); assert_snapshot!(Net::to_string(&net), @"#8"); } #[test] fn test_lsh() { - let net = op_net(10, Op::Shl, 2); + let net = op_net_u32(10, Shl, 2); let (_rwts, net) = normal(net, Some(128)); assert_snapshot!(Net::to_string(&net), @"#40"); } #[test] fn test_rsh() { - let net = op_net(10, Op::Shr, 2); + let net = op_net_u32(10, Shr, 2); let (_rwts, net) = normal(net, Some(128)); assert_snapshot!(Net::to_string(&net), @"#2"); } #[test] fn test_div_by_0() { - let net = op_net(9, Op::Div, 0); + let net = op_net_u32(9, Div, 0); let (rwts, net) = normal(net, Some(128)); assert_snapshot!(Net::to_string(&net), @"#0"); assert_debug_snapshot!(rwts.total(), @"3"); From cb74ec2537a1131a1b828b23254a4298b094991f Mon Sep 17 00:00:00 2001 From: Enrico Zandomeni Borba Date: Thu, 4 Apr 2024 09:46:11 -0400 Subject: [PATCH 03/11] spacing --- src/run/interact.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/run/interact.rs b/src/run/interact.rs index e7f48c7a..f271d86c 100644 --- a/src/run/interact.rs +++ b/src/run/interact.rs @@ -46,7 +46,7 @@ impl<'a, M: Mode> Net<'a, M> { /// Annihilates two binary agents. /// /// ```text - /// + /// /// a2 | | a1 /// _|___|_ /// \ / @@ -68,6 +68,7 @@ impl<'a, M: Mode> Net<'a, M> { /// / \ /// | | /// b1 | | b2 + /// /// ``` #[inline(never)] pub fn anni2(&mut self, a: Port, b: Port) { @@ -82,7 +83,7 @@ impl<'a, M: Mode> Net<'a, M> { /// Commutes two binary agents. /// /// ```text - /// + /// /// a2 | | a1 /// _|___|_ /// \ / @@ -114,6 +115,7 @@ impl<'a, M: Mode> Net<'a, M> { /// \ / \ / /// | | /// b1 | | b2 + /// /// ``` #[inline(never)] pub fn comm22(&mut self, a: Port, b: Port) { @@ -144,7 +146,7 @@ impl<'a, M: Mode> Net<'a, M> { /// Commutes a nilary agent and a binary agent. /// /// ```text - /// + /// /// a (---) /// | /// | @@ -159,6 +161,7 @@ impl<'a, M: Mode> Net<'a, M> { /// a (---) (---) a /// | | /// b1 | | b2 + /// /// ``` #[inline(never)] pub fn comm02(&mut self, a: Port, b: Port) { @@ -198,6 +201,7 @@ impl<'a, M: Mode> Net<'a, M> { /// | | | | | /// a1 | | a2 | a1 | | a2 /// | + /// /// ``` #[inline(never)] pub fn mat_num(&mut self, a: Port, b: Port) { @@ -247,6 +251,7 @@ impl<'a, M: Mode> Net<'a, M> { /// | | | | /// | a2 | a1 | | a2 /// | + /// /// ``` #[inline(never)] pub fn op_num(&mut self, a: Port, b: Port) { From edbd7515ea2ab0948045ddc80073c2978f45514d Mon Sep 17 00:00:00 2001 From: Enrico Zandomeni Borba Date: Thu, 4 Apr 2024 09:46:17 -0400 Subject: [PATCH 04/11] as i64 >> --- src/run/port.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/run/port.rs b/src/run/port.rs index d77ad3dc..bd8dbccb 100644 --- a/src/run/port.rs +++ b/src/run/port.rs @@ -173,7 +173,7 @@ impl Port { /// Accesses the numeric value of this port; this is valid for [`Num`] ports. #[inline(always)] pub const fn num(&self) -> i64 { - (self.0 >> 4) as i64 + self.0 as i64 >> 4 } /// Accesses the wire leaving this port; this is valid for [`Var`] ports and From fcf74e6cef2be4352387fb55f5acc6f11064db15 Mon Sep 17 00:00:00 2001 From: Enrico Zandomeni Borba Date: Thu, 4 Apr 2024 10:13:57 -0400 Subject: [PATCH 05/11] "checked" conversions from u16 <-> Op --- src/ops.rs | 28 ++++++++++++++++------------ src/run/interact.rs | 13 ++++--------- src/run/port.rs | 2 +- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/ops.rs b/src/ops.rs index dd0e88d2..4228fafc 100644 --- a/src/ops.rs +++ b/src/ops.rs @@ -163,18 +163,6 @@ pub struct Op { pub op: IntOp, } -impl From for Op { - fn from(value: u16) -> Self { - unsafe { std::mem::transmute(value) } - } -} - -impl From for u16 { - fn from(op: Op) -> Self { - unsafe { std::mem::transmute(op) } - } -} - impl Display for Op { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self.ty { @@ -184,6 +172,22 @@ impl Display for Op { } } +impl TryFrom for Op { + type Error = (); + + fn try_from(value: u16) -> Result { + let [ty, op] = value.to_be_bytes(); + + Ok(Self { ty: Ty::try_from(ty)?, op: IntOp::try_from(op)? }) + } +} + +impl From for u16 { + fn from(op: Op) -> Self { + (op.ty as u16) << 8 | op.op as u16 + } +} + impl FromStr for Op { type Err = (); diff --git a/src/run/interact.rs b/src/run/interact.rs index f271d86c..a9fc4e60 100644 --- a/src/run/interact.rs +++ b/src/run/interact.rs @@ -46,7 +46,7 @@ impl<'a, M: Mode> Net<'a, M> { /// Annihilates two binary agents. /// /// ```text - /// + /// /// a2 | | a1 /// _|___|_ /// \ / @@ -68,7 +68,6 @@ impl<'a, M: Mode> Net<'a, M> { /// / \ /// | | /// b1 | | b2 - /// /// ``` #[inline(never)] pub fn anni2(&mut self, a: Port, b: Port) { @@ -83,7 +82,7 @@ impl<'a, M: Mode> Net<'a, M> { /// Commutes two binary agents. /// /// ```text - /// + /// /// a2 | | a1 /// _|___|_ /// \ / @@ -115,7 +114,6 @@ impl<'a, M: Mode> Net<'a, M> { /// \ / \ / /// | | /// b1 | | b2 - /// /// ``` #[inline(never)] pub fn comm22(&mut self, a: Port, b: Port) { @@ -146,7 +144,7 @@ impl<'a, M: Mode> Net<'a, M> { /// Commutes a nilary agent and a binary agent. /// /// ```text - /// + /// /// a (---) /// | /// | @@ -161,7 +159,6 @@ impl<'a, M: Mode> Net<'a, M> { /// a (---) (---) a /// | | /// b1 | | b2 - /// /// ``` #[inline(never)] pub fn comm02(&mut self, a: Port, b: Port) { @@ -201,7 +198,6 @@ impl<'a, M: Mode> Net<'a, M> { /// | | | | | /// a1 | | a2 | a1 | | a2 /// | - /// /// ``` #[inline(never)] pub fn mat_num(&mut self, a: Port, b: Port) { @@ -251,13 +247,12 @@ impl<'a, M: Mode> Net<'a, M> { /// | | | | /// | a2 | a1 | | a2 /// | - /// /// ``` #[inline(never)] pub fn op_num(&mut self, a: Port, b: Port) { trace!(self.tracer, a, b); let a = a.consume_node(); - let op = Op::from(a.lab); + let op = Op::try_from(a.lab).unwrap(); let a1 = a.p1.load_target(); if a1.tag() == Num { self.rwts.oper += 1; diff --git a/src/run/port.rs b/src/run/port.rs index bd8dbccb..0ec363f4 100644 --- a/src/run/port.rs +++ b/src/run/port.rs @@ -167,7 +167,7 @@ impl Port { /// ports. #[inline(always)] pub fn op(&self) -> Op { - self.lab().into() + self.lab().try_into().unwrap() } /// Accesses the numeric value of this port; this is valid for [`Num`] ports. From 9a22ad5e5ccc225deb8382640ab6b5f4d135bffc Mon Sep 17 00:00:00 2001 From: Enrico Zandomeni Borba Date: Thu, 4 Apr 2024 10:50:41 -0400 Subject: [PATCH 06/11] unwrap_unchecked --- src/run/interact.rs | 2 +- src/run/port.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/run/interact.rs b/src/run/interact.rs index a9fc4e60..c011595c 100644 --- a/src/run/interact.rs +++ b/src/run/interact.rs @@ -252,7 +252,7 @@ impl<'a, M: Mode> Net<'a, M> { pub fn op_num(&mut self, a: Port, b: Port) { trace!(self.tracer, a, b); let a = a.consume_node(); - let op = Op::try_from(a.lab).unwrap(); + let op = unsafe { Op::try_from(a.lab).unwrap_unchecked() }; let a1 = a.p1.load_target(); if a1.tag() == Num { self.rwts.oper += 1; diff --git a/src/run/port.rs b/src/run/port.rs index 0ec363f4..d0f2eac5 100644 --- a/src/run/port.rs +++ b/src/run/port.rs @@ -167,7 +167,7 @@ impl Port { /// ports. #[inline(always)] pub fn op(&self) -> Op { - self.lab().try_into().unwrap() + unsafe { self.lab().try_into().unwrap_unchecked() } } /// Accesses the numeric value of this port; this is valid for [`Num`] ports. From c8a2b3d9a1acb408eb8ac0862bb03e4584107a0e Mon Sep 17 00:00:00 2001 From: Enrico Zandomeni Borba Date: Thu, 4 Apr 2024 15:23:31 -0400 Subject: [PATCH 07/11] comment spaces --- src/run/interact.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/run/interact.rs b/src/run/interact.rs index c011595c..2c4025ff 100644 --- a/src/run/interact.rs +++ b/src/run/interact.rs @@ -46,7 +46,6 @@ impl<'a, M: Mode> Net<'a, M> { /// Annihilates two binary agents. /// /// ```text - /// /// a2 | | a1 /// _|___|_ /// \ / @@ -82,7 +81,6 @@ impl<'a, M: Mode> Net<'a, M> { /// Commutes two binary agents. /// /// ```text - /// /// a2 | | a1 /// _|___|_ /// \ / @@ -144,7 +142,6 @@ impl<'a, M: Mode> Net<'a, M> { /// Commutes a nilary agent and a binary agent. /// /// ```text - /// /// a (---) /// | /// | From 6cc6210fe98509182a0719121fb0c04d96501993 Mon Sep 17 00:00:00 2001 From: Enrico Zandomeni Borba Date: Fri, 5 Apr 2024 14:58:15 -0400 Subject: [PATCH 08/11] test and comment --- src/ast.rs | 2 +- src/ops.rs | 2 +- tests/programs/ops.hvmc | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 tests/programs/ops.hvmc diff --git a/src/ast.rs b/src/ast.rs index ad89d1bf..58680432 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -378,7 +378,7 @@ impl<'i> Parser<'i> { /// See `ops.rs` for the available operators. fn parse_op(&mut self) -> Result { - let op = self.take_while(|c| "ui81632.+-=*/%<>|&^!?$".contains(c)); + let op = self.take_while(|c| "ui0123456789.+-=*/%<>|&^!?$".contains(c)); op.parse().map_err(|_| format!("Unknown operator: {op:?}")) } diff --git a/src/ops.rs b/src/ops.rs index 4228fafc..dd13df77 100644 --- a/src/ops.rs +++ b/src/ops.rs @@ -51,7 +51,7 @@ impl_num! { u8, u16, u32, u64, i8, i16, i32 } bi_enum! { #[repr(u8)] - /// Native operations on variable-width integers. + /// Native operations on mixed-width integers (u8, u16, u32, u60, i8, i16, i32). /// /// Each operation has a swapped counterpart (accessible with `.swap()`), /// where the order of the operands is swapped. diff --git a/tests/programs/ops.hvmc b/tests/programs/ops.hvmc new file mode 100644 index 00000000..a6216f43 --- /dev/null +++ b/tests/programs/ops.hvmc @@ -0,0 +1,33 @@ +// numbers are printed as `i64`, so over/underflows in `u60` arithmetic might +// change the sign when printed + +@main = x + // underflow + & x ~ [n x] & #0 ~ // 255 + & x ~ [n x] & #0 ~ // 65535 + & x ~ [n x] & #0 ~ // 4294967295 + & x ~ [n x] & #0 ~ // -1 + + // max + & x ~ [n x] & #1 ~ // 255 + & x ~ [n x] & #1 ~ // 65535 + & x ~ [n x] & #1 ~ // 4294967295 + & x ~ [n x] & #1 ~ // -1 + + // overflow + & x ~ [n x] & #1 ~ // 0 + & x ~ [n x] & #1 ~ // 0 + & x ~ [n x] & #1 ~ // 0 + & x ~ [n x] & #1 ~ // 0 + + // sign extension + & x ~ [n x] & #0 ~ // -1 + & x ~ [n x] & #0 ~ // -1 + & x ~ [n x] & #0 ~ // -1 + + // signed overflow + & x ~ [n x] & #2 ~ // -2 + & x ~ [n x] & #2 ~ // -2 + & x ~ [n x] & #2 ~ // -2 + + & x ~ * From 903b0fcab5309662e4fce64301a9645d039508eb Mon Sep 17 00:00:00 2001 From: Enrico Zandomeni Borba Date: Fri, 5 Apr 2024 14:59:37 -0400 Subject: [PATCH 09/11] Cargo.toml version --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5aec7373..df6e4aa4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -280,7 +280,7 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hvm-core" -version = "0.2.22" +version = "0.2.24" dependencies = [ "arrayvec", "clap", diff --git a/Cargo.toml b/Cargo.toml index 1d03d41d..e3263181 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hvm-core" -version = "0.2.22" +version = "0.2.24" edition = "2021" description = "HVM-Core is a massively parallel Interaction Combinator evaluator." license = "MIT" From 21c91fd60c72c4eda6e9e6699464962c148a4001 Mon Sep 17 00:00:00 2001 From: Enrico Zandomeni Borba Date: Fri, 5 Apr 2024 15:09:32 -0400 Subject: [PATCH 10/11] snapshots --- .../tests__pre_reduce_run@ops.hvmc.snap | 20 +++++++++++++++++++ tests/snapshots/tests__run@ops.hvmc.snap | 12 +++++++++++ 2 files changed, 32 insertions(+) create mode 100644 tests/snapshots/tests__pre_reduce_run@ops.hvmc.snap create mode 100644 tests/snapshots/tests__run@ops.hvmc.snap diff --git a/tests/snapshots/tests__pre_reduce_run@ops.hvmc.snap b/tests/snapshots/tests__pre_reduce_run@ops.hvmc.snap new file mode 100644 index 00000000..7c515965 --- /dev/null +++ b/tests/snapshots/tests__pre_reduce_run@ops.hvmc.snap @@ -0,0 +1,20 @@ +--- +source: tests/tests.rs +expression: output +input_file: tests/programs/ops.hvmc +--- +[#255 [#65535 [#4294967295 [#-1 [#255 [#65535 [#4294967295 [#-1 [#0 [#0 [#0 [#0 [#-1 [#-1 [#-1 [#-2 [#-2 [#-2 *]]]]]]]]]]]]]]]]]] +pre-reduce: +RWTS : 0 +- ANNI : 0 +- COMM : 0 +- ERAS : 0 +- DREF : 0 +- OPER : 0 +run: +RWTS : 56 +- ANNI : 0 +- COMM : 0 +- ERAS : 0 +- DREF : 38 +- OPER : 18 diff --git a/tests/snapshots/tests__run@ops.hvmc.snap b/tests/snapshots/tests__run@ops.hvmc.snap new file mode 100644 index 00000000..6644da9b --- /dev/null +++ b/tests/snapshots/tests__run@ops.hvmc.snap @@ -0,0 +1,12 @@ +--- +source: tests/tests.rs +expression: output +input_file: tests/programs/ops.hvmc +--- +[#255 [#65535 [#4294967295 [#-1 [#255 [#65535 [#4294967295 [#-1 [#0 [#0 [#0 [#0 [#-1 [#-1 [#-1 [#-2 [#-2 [#-2 *]]]]]]]]]]]]]]]]]] +RWTS : 56 +- ANNI : 0 +- COMM : 0 +- ERAS : 0 +- DREF : 38 +- OPER : 18 From fa5fe2ca94cfb2422d6e9bdcf6fd6d977537bd8f Mon Sep 17 00:00:00 2001 From: Enrico Zandomeni Borba Date: Sat, 6 Apr 2024 07:09:15 -0400 Subject: [PATCH 11/11] move numeric.rs tests into tests/programs/ops.hvmc --- tests/numeric.rs | 123 ------------------ tests/programs/ops.hvmc | 47 ++++--- .../tests__pre_reduce_run@ops.hvmc.snap | 8 +- tests/snapshots/tests__run@ops.hvmc.snap | 8 +- 4 files changed, 40 insertions(+), 146 deletions(-) delete mode 100644 tests/numeric.rs diff --git a/tests/numeric.rs b/tests/numeric.rs deleted file mode 100644 index 3560016f..00000000 --- a/tests/numeric.rs +++ /dev/null @@ -1,123 +0,0 @@ -use hvmc::{ - ast::{Book, Net}, - ops::IntOp, -}; -use insta::{assert_debug_snapshot, assert_snapshot}; -use loaders::*; - -mod loaders; - -fn op_net_u32(lnum: u32, op: IntOp, rnum: u32) -> Book { - let code = format!("@main = root & #{lnum} ~ "); - println!("Code: {code:?}"); - parse_core(&code) -} - -use IntOp::*; - -#[test] -fn test_add() { - let net = op_net_u32(10, Add, 2); - let (rwts, net) = normal(net, Some(128)); - assert_snapshot!(Net::to_string(&net), @"#12"); - assert_debug_snapshot!(rwts.total(), @"3"); -} - -#[test] -fn test_sub() { - let net = op_net_u32(10, Sub, 2); - let (_rwts, net) = normal(net, Some(128)); - assert_snapshot!(Net::to_string(&net), @"#8"); -} - -#[test] -fn test_mul() { - let net = op_net_u32(10, Mul, 2); - let (_rwts, net) = normal(net, Some(128)); - assert_snapshot!(Net::to_string(&net), @"#20"); -} - -#[test] -fn test_div() { - let net = op_net_u32(10, Div, 2); - let (_rwts, net) = normal(net, Some(128)); - assert_snapshot!(Net::to_string(&net), @"#5"); -} - -#[test] -fn test_rem() { - let net = op_net_u32(10, Rem, 2); - let (_rwts, net) = normal(net, Some(128)); - assert_snapshot!(Net::to_string(&net), @"#0"); -} - -#[test] -fn test_eq() { - let net = op_net_u32(10, Eq, 2); - let (_rwts, net) = normal(net, Some(128)); - assert_snapshot!(Net::to_string(&net), @"#0"); -} - -#[test] -fn test_ne() { - let net = op_net_u32(10, Ne, 2); - let (_rwts, net) = normal(net, Some(128)); - assert_snapshot!(Net::to_string(&net), @"#1"); -} - -#[test] -fn test_lt() { - let net = op_net_u32(10, Lt, 2); - let (_rwts, net) = normal(net, Some(128)); - assert_snapshot!(Net::to_string(&net), @"#0"); -} - -#[test] -fn test_gt() { - let net = op_net_u32(10, Gt, 2); - let (_rwts, net) = normal(net, Some(128)); - assert_snapshot!(Net::to_string(&net), @"#1"); -} - -#[test] -fn test_and() { - let net = op_net_u32(10, And, 2); - let (_rwts, net) = normal(net, Some(128)); - assert_snapshot!(Net::to_string(&net), @"#2"); -} - -#[test] -fn test_or() { - let net = op_net_u32(10, Or, 2); - let (_rwts, net) = normal(net, Some(128)); - assert_snapshot!(Net::to_string(&net), @"#10"); -} - -#[test] -fn test_xor() { - let net = op_net_u32(10, Xor, 2); - let (_rwts, net) = normal(net, Some(128)); - assert_snapshot!(Net::to_string(&net), @"#8"); -} - -#[test] -fn test_lsh() { - let net = op_net_u32(10, Shl, 2); - let (_rwts, net) = normal(net, Some(128)); - assert_snapshot!(Net::to_string(&net), @"#40"); -} - -#[test] -fn test_rsh() { - let net = op_net_u32(10, Shr, 2); - let (_rwts, net) = normal(net, Some(128)); - assert_snapshot!(Net::to_string(&net), @"#2"); -} - -#[test] -fn test_div_by_0() { - let net = op_net_u32(9, Div, 0); - let (rwts, net) = normal(net, Some(128)); - assert_snapshot!(Net::to_string(&net), @"#0"); - assert_debug_snapshot!(rwts.total(), @"3"); -} diff --git a/tests/programs/ops.hvmc b/tests/programs/ops.hvmc index a6216f43..fd6e3114 100644 --- a/tests/programs/ops.hvmc +++ b/tests/programs/ops.hvmc @@ -3,31 +3,48 @@ @main = x // underflow - & x ~ [n x] & #0 ~ // 255 - & x ~ [n x] & #0 ~ // 65535 - & x ~ [n x] & #0 ~ // 4294967295 - & x ~ [n x] & #0 ~ // -1 + & x ~ [n x] & #0 ~ // 255 + & x ~ [n x] & #0 ~ // 65535 + & x ~ [n x] & #0 ~ // 4294967295 + & x ~ [n x] & #0 ~ // -1 // max - & x ~ [n x] & #1 ~ // 255 - & x ~ [n x] & #1 ~ // 65535 - & x ~ [n x] & #1 ~ // 4294967295 - & x ~ [n x] & #1 ~ // -1 + & x ~ [n x] & #1 ~ // 255 + & x ~ [n x] & #1 ~ // 65535 + & x ~ [n x] & #1 ~ // 4294967295 + & x ~ [n x] & #1 ~ // -1 // overflow - & x ~ [n x] & #1 ~ // 0 - & x ~ [n x] & #1 ~ // 0 - & x ~ [n x] & #1 ~ // 0 - & x ~ [n x] & #1 ~ // 0 + & x ~ [n x] & #1 ~ // 0 + & x ~ [n x] & #1 ~ // 0 + & x ~ [n x] & #1 ~ // 0 + & x ~ [n x] & #1 ~ // 0 // sign extension - & x ~ [n x] & #0 ~ // -1 - & x ~ [n x] & #0 ~ // -1 - & x ~ [n x] & #0 ~ // -1 + & x ~ [n x] & #0 ~ // -1 + & x ~ [n x] & #0 ~ // -1 + & x ~ [n x] & #0 ~ // -1 // signed overflow & x ~ [n x] & #2 ~ // -2 & x ~ [n x] & #2 ~ // -2 & x ~ [n x] & #2 ~ // -2 + // all ops + & x ~ [n x] & #10 ~ // 12 + & x ~ [n x] & #10 ~ // 8 + & x ~ [n x] & #10 ~ // 20 + & x ~ [n x] & #10 ~ // 5 + & x ~ [n x] & #10 ~ // 0 + & x ~ [n x] & #10 ~ // 0 + & x ~ [n x] & #10 ~ // 1 + & x ~ [n x] & #10 ~ // 0 + & x ~ [n x] & #10 ~ #2 n> // 1 + & x ~ [n x] & #10 ~ // 2 + & x ~ [n x] & #10 ~ // 10 + & x ~ [n x] & #10 ~ // 8 + & x ~ [n x] & #10 ~ // 40 + & x ~ [n x] & #10 ~ > #2 n> // 2 + & x ~ [n x] & #9 ~ // 0 + & x ~ * diff --git a/tests/snapshots/tests__pre_reduce_run@ops.hvmc.snap b/tests/snapshots/tests__pre_reduce_run@ops.hvmc.snap index 7c515965..f98ffcbe 100644 --- a/tests/snapshots/tests__pre_reduce_run@ops.hvmc.snap +++ b/tests/snapshots/tests__pre_reduce_run@ops.hvmc.snap @@ -3,7 +3,7 @@ source: tests/tests.rs expression: output input_file: tests/programs/ops.hvmc --- -[#255 [#65535 [#4294967295 [#-1 [#255 [#65535 [#4294967295 [#-1 [#0 [#0 [#0 [#0 [#-1 [#-1 [#-1 [#-2 [#-2 [#-2 *]]]]]]]]]]]]]]]]]] +[#255 [#65535 [#4294967295 [#-1 [#255 [#65535 [#4294967295 [#-1 [#0 [#0 [#0 [#0 [#-1 [#-1 [#-1 [#-2 [#-2 [#-2 [#12 [#8 [#20 [#5 [#0 [#0 [#1 [#0 [#1 [#2 [#10 [#8 [#40 [#2 [#0 *]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] pre-reduce: RWTS : 0 - ANNI : 0 @@ -12,9 +12,9 @@ RWTS : 0 - DREF : 0 - OPER : 0 run: -RWTS : 56 +RWTS : 101 - ANNI : 0 - COMM : 0 - ERAS : 0 -- DREF : 38 -- OPER : 18 +- DREF : 68 +- OPER : 33 diff --git a/tests/snapshots/tests__run@ops.hvmc.snap b/tests/snapshots/tests__run@ops.hvmc.snap index 6644da9b..269a6029 100644 --- a/tests/snapshots/tests__run@ops.hvmc.snap +++ b/tests/snapshots/tests__run@ops.hvmc.snap @@ -3,10 +3,10 @@ source: tests/tests.rs expression: output input_file: tests/programs/ops.hvmc --- -[#255 [#65535 [#4294967295 [#-1 [#255 [#65535 [#4294967295 [#-1 [#0 [#0 [#0 [#0 [#-1 [#-1 [#-1 [#-2 [#-2 [#-2 *]]]]]]]]]]]]]]]]]] -RWTS : 56 +[#255 [#65535 [#4294967295 [#-1 [#255 [#65535 [#4294967295 [#-1 [#0 [#0 [#0 [#0 [#-1 [#-1 [#-1 [#-2 [#-2 [#-2 [#12 [#8 [#20 [#5 [#0 [#0 [#1 [#0 [#1 [#2 [#10 [#8 [#40 [#2 [#0 *]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] +RWTS : 101 - ANNI : 0 - COMM : 0 - ERAS : 0 -- DREF : 38 -- OPER : 18 +- DREF : 68 +- OPER : 33