mirror of
https://github.com/HigherOrderCO/Bend.git
synced 2024-11-05 04:51:40 +03:00
[sc-495][sc-494] Update for new hvmc num ops and pre_reduce
This commit is contained in:
parent
319b2464ac
commit
ecb213e91b
23
Cargo.lock
generated
23
Cargo.lock
generated
@ -4,9 +4,9 @@ version = 3
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.10"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b79b82693f705137f8fb9b37871d99e4f9a7df12b917eed79c3d3954830a60b"
|
||||
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
@ -70,9 +70,9 @@ checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.88"
|
||||
version = "1.0.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02f341c093d19155a6e41631ce5971aac4e9a868262212153124c15fa22d1cdc"
|
||||
checksum = "a0ba8f7aaa012f30d5b2861462f6708eccd49c3c39863fe083a308035f63d723"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
@ -202,10 +202,11 @@ checksum = "809e18805660d7b6b2e2b9f316a5099521b5998d5cba4dda11b5157a21aaef03"
|
||||
[[package]]
|
||||
name = "hvm-core"
|
||||
version = "0.2.19"
|
||||
source = "git+https://github.com/HigherOrderCO/hvm-core#0433f52cd51f3b9c8db3630bf338d378d5b2908d"
|
||||
source = "git+https://github.com/HigherOrderCO/hvm-core#32f80ba12145a318d6c84047576c4b4cd01a1760"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"nohash-hasher",
|
||||
"stacker",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -228,9 +229,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.2.4"
|
||||
version = "2.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "967d6dd42f16dbf0eb8040cb9e477933562684d3918f7d253f2ff9087fb3e7a3"
|
||||
checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.14.3",
|
||||
@ -238,9 +239,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "insta"
|
||||
version = "1.35.1"
|
||||
version = "1.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c985c1bef99cf13c58fade470483d81a2bfe846ebde60ed28cc2dddec2df9e2"
|
||||
checksum = "0a7c22c4d34ef4788c351e971c52bfdfe7ea2766f8c5466bc175dd46e52ac22e"
|
||||
dependencies = [
|
||||
"console",
|
||||
"lazy_static",
|
||||
@ -431,9 +432,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.4.0"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
|
||||
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi-util",
|
||||
|
@ -1,2 +1 @@
|
||||
pub mod pre_reduce;
|
||||
pub mod prune;
|
||||
|
@ -1,71 +0,0 @@
|
||||
// Reduce the compiled networks, solving any annihilations and commutations.
|
||||
// This is a useful optimization on its own, but also required by an hvm-core optimization.
|
||||
|
||||
use std::sync::Mutex;
|
||||
|
||||
use hvmc::{ast::Book, dispatch_dyn_net, host::Host, run::Def};
|
||||
|
||||
use crate::CORE_BUILTINS;
|
||||
use hvmc::run::Port;
|
||||
|
||||
/// A Def that pushes all interactions to its inner Vec.
|
||||
struct InertDef(Mutex<Vec<(Port, Port)>>);
|
||||
|
||||
impl hvmc::run::AsDef for InertDef {
|
||||
unsafe fn call<M: hvmc::run::Mode>(
|
||||
def: *const hvmc::run::Def<Self>,
|
||||
_: &mut hvmc::run::Net<M>,
|
||||
port: Port,
|
||||
) {
|
||||
let def = unsafe { &*def };
|
||||
def.data.0.lock().unwrap().push((Port::new_ref(def), port));
|
||||
}
|
||||
}
|
||||
|
||||
/// Reduces the definitions in the book individually, except for main.
|
||||
///
|
||||
/// It does not reduce interactions that use builtin defs, as they are
|
||||
/// assumed to be side-effectful
|
||||
pub fn pre_reduce_book(book: &mut Book, entrypoint: &str) -> Result<(), String> {
|
||||
/// Maximum amount of rewrites that
|
||||
const MAX_RWTS: usize = 100_000;
|
||||
// Create a host
|
||||
// with inert definitions in the place
|
||||
// of core builtins, to prevent them from being reduced
|
||||
let mut host = Host::default();
|
||||
for builtin in CORE_BUILTINS {
|
||||
let def = InertDef(Default::default());
|
||||
host.insert_def(builtin, hvmc::host::DefRef::Owned(Box::new(Def::new(hvmc::run::LabSet::ALL, def))));
|
||||
}
|
||||
host.insert_book(book);
|
||||
|
||||
for (nam, net) in book.iter_mut() {
|
||||
// Skip unnecessary work
|
||||
if net.redexes.is_empty() || *nam == entrypoint {
|
||||
continue;
|
||||
}
|
||||
|
||||
let area = hvmc::run::Heap::new_words(1 << 18);
|
||||
let mut rt = hvmc::run::DynNet::new(&area, false);
|
||||
dispatch_dyn_net!(&mut rt => {
|
||||
rt.boot(host.defs.get(nam).expect("No function."));
|
||||
rt.expand();
|
||||
rt.reduce(MAX_RWTS);
|
||||
});
|
||||
|
||||
// Move interactions with inert defs back into the net redexes array
|
||||
for def in host.defs.values() {
|
||||
if let Some(def) = def.downcast_ref::<InertDef>() {
|
||||
let mut stored_redexes = def.data.0.lock().unwrap();
|
||||
dispatch_dyn_net!(&mut rt => {
|
||||
rt.redexes.extend(core::mem::take(&mut *stored_redexes));
|
||||
})
|
||||
}
|
||||
}
|
||||
// Place the reduced net back into the def map
|
||||
dispatch_dyn_net!(&mut rt => {
|
||||
*net = host.readback(rt);
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
@ -27,13 +27,10 @@ fn used_defs_in_tree(tree: &Tree, used_defs: &mut HashSet<String>, to_visit: &mu
|
||||
to_visit.push(nam.clone());
|
||||
}
|
||||
}
|
||||
Tree::Ctr { lft, rgt, .. } | Tree::Op2 { lft, rgt, .. } | Tree::Mat { sel: lft, ret: rgt } => {
|
||||
Tree::Ctr { lft, rgt, .. } | Tree::Op { rhs: lft, out: rgt, .. } | Tree::Mat { sel: lft, ret: rgt } => {
|
||||
used_defs_in_tree(lft, used_defs, to_visit);
|
||||
used_defs_in_tree(rgt, used_defs, to_visit);
|
||||
}
|
||||
Tree::Op1 { rgt, .. } => {
|
||||
used_defs_in_tree(rgt, used_defs, to_visit);
|
||||
}
|
||||
Tree::Var { .. } | Tree::Num { .. } | Tree::Era => (),
|
||||
}
|
||||
}
|
||||
|
11
src/lib.rs
11
src/lib.rs
@ -9,7 +9,7 @@ use hvmc::{
|
||||
run::{DynNet, Heap, Rewrites},
|
||||
stdlib::LogDef,
|
||||
};
|
||||
use hvmc_net::{pre_reduce::pre_reduce_book, prune::prune_defs};
|
||||
use hvmc_net::prune::prune_defs;
|
||||
use net::{hvmc_to_net::hvmc_to_net, net_to_hvmc::nets_to_hvmc};
|
||||
use std::{
|
||||
str::FromStr,
|
||||
@ -99,7 +99,7 @@ pub fn compile_book(
|
||||
|
||||
let mut core_book = nets_to_hvmc(nets)?;
|
||||
if opts.pre_reduce {
|
||||
pre_reduce_book(&mut core_book, book.hvmc_entrypoint())?;
|
||||
core_book.pre_reduce(&|x| x == book.hvmc_entrypoint(), 1 << 24, 100_000)?;
|
||||
}
|
||||
if opts.prune {
|
||||
prune_defs(&mut core_book, book.hvmc_entrypoint().to_string());
|
||||
@ -220,14 +220,15 @@ pub fn count_nodes<'l>(net: &'l hvmc::ast::Net) -> usize {
|
||||
}
|
||||
while let Some(tree) = visit.pop() {
|
||||
match tree {
|
||||
ast::Tree::Ctr { lft, rgt, .. } | ast::Tree::Op2 { lft, rgt, .. } => {
|
||||
ast::Tree::Ctr { lft, rgt, .. } => {
|
||||
count += 1;
|
||||
visit.push(lft);
|
||||
visit.push(rgt);
|
||||
}
|
||||
ast::Tree::Op1 { rgt, .. } => {
|
||||
ast::Tree::Op { rhs, out, .. } => {
|
||||
count += 1;
|
||||
visit.push(rgt);
|
||||
visit.push(rhs);
|
||||
visit.push(out);
|
||||
}
|
||||
ast::Tree::Mat { sel, ret } => {
|
||||
count += 1;
|
||||
|
@ -85,21 +85,11 @@ fn tree_to_inodes(tree: &Tree, tree_root: String, net_root: &str, n_vars: &mut N
|
||||
let var = new_var(n_vars);
|
||||
inodes.push(INode { kind, ports: [subtree_root, var.clone(), var] });
|
||||
}
|
||||
Tree::Op1 { opr, lft, rgt } => {
|
||||
// Add port 1 as a new Num node.
|
||||
let lft_name = new_var(n_vars);
|
||||
let num_name = new_var(n_vars);
|
||||
inodes.push(INode { kind: Num { val: *lft }, ports: [lft_name.clone(), num_name.clone(), num_name] });
|
||||
// Swap ports 0 and 1 and transform into OP2.
|
||||
let kind = Op2 { opr: *opr };
|
||||
let rgt = process_node_subtree(rgt, net_root, &mut subtrees, n_vars);
|
||||
inodes.push(INode { kind, ports: [lft_name, subtree_root, rgt] });
|
||||
}
|
||||
Tree::Op2 { opr, lft, rgt } => {
|
||||
let kind = Op2 { opr: *opr };
|
||||
let lft = process_node_subtree(lft, net_root, &mut subtrees, n_vars);
|
||||
let rgt = process_node_subtree(rgt, net_root, &mut subtrees, n_vars);
|
||||
inodes.push(INode { kind, ports: [subtree_root, lft, rgt] });
|
||||
Tree::Op { op, rhs, out } => {
|
||||
let kind = Op2 { opr: *op };
|
||||
let rhs = process_node_subtree(rhs, net_root, &mut subtrees, n_vars);
|
||||
let out = process_node_subtree(out, net_root, &mut subtrees, n_vars);
|
||||
inodes.push(INode { kind, ports: [subtree_root, rhs, out] });
|
||||
}
|
||||
Tree::Mat { sel, ret } => {
|
||||
let kind = Mat;
|
||||
|
@ -61,10 +61,10 @@ fn net_tree_to_hvmc_tree(inet: &INet, tree_root: NodeId, port_to_var_id: &mut Ha
|
||||
},
|
||||
NodeKind::Ref { def_name } => Tree::Ref { nam: def_name.to_string() },
|
||||
NodeKind::Num { val } => Tree::Num { val: *val },
|
||||
NodeKind::Op2 { opr } => Tree::Op2 {
|
||||
opr: *opr,
|
||||
lft: Box::new(var_or_subtree(inet, Port(tree_root, 1), port_to_var_id)),
|
||||
rgt: Box::new(var_or_subtree(inet, Port(tree_root, 2), port_to_var_id)),
|
||||
NodeKind::Op2 { opr } => Tree::Op {
|
||||
op: *opr,
|
||||
rhs: Box::new(var_or_subtree(inet, Port(tree_root, 1), port_to_var_id)),
|
||||
out: Box::new(var_or_subtree(inet, Port(tree_root, 2), port_to_var_id)),
|
||||
},
|
||||
NodeKind::Mat => Tree::Mat {
|
||||
sel: Box::new(var_or_subtree(inet, Port(tree_root, 1), port_to_var_id)),
|
||||
|
@ -151,23 +151,22 @@ impl fmt::Display for NumCtr {
|
||||
impl fmt::Display for Op {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Op::ADD => write!(f, "+"),
|
||||
Op::SUB => write!(f, "-"),
|
||||
Op::MUL => write!(f, "*"),
|
||||
Op::DIV => write!(f, "/"),
|
||||
Op::MOD => write!(f, "%"),
|
||||
Op::EQ => write!(f, "=="),
|
||||
Op::NE => write!(f, "!="),
|
||||
Op::LT => write!(f, "<"),
|
||||
Op::GT => write!(f, ">"),
|
||||
Op::LTE => write!(f, "<="),
|
||||
Op::GTE => write!(f, ">="),
|
||||
Op::AND => write!(f, "&"),
|
||||
Op::OR => write!(f, "|"),
|
||||
Op::XOR => write!(f, "^"),
|
||||
Op::LSH => write!(f, "<<"),
|
||||
Op::RSH => write!(f, ">>"),
|
||||
Op::NOT => write!(f, "~"),
|
||||
Op::Add => write!(f, "+"),
|
||||
Op::Sub => write!(f, "-"),
|
||||
Op::Mul => write!(f, "*"),
|
||||
Op::Div => write!(f, "/"),
|
||||
Op::Mod => write!(f, "%"),
|
||||
Op::Eq => write!(f, "=="),
|
||||
Op::Ne => write!(f, "!="),
|
||||
Op::Lt => write!(f, "<"),
|
||||
Op::Gt => write!(f, ">"),
|
||||
Op::Lte => write!(f, "<="),
|
||||
Op::Gte => write!(f, ">="),
|
||||
Op::And => write!(f, "&"),
|
||||
Op::Or => write!(f, "|"),
|
||||
Op::Xor => write!(f, "^"),
|
||||
Op::Shl => write!(f, "<<"),
|
||||
Op::Shr => write!(f, ">>"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -163,23 +163,22 @@ pub enum Tag {
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum Op {
|
||||
ADD,
|
||||
SUB,
|
||||
MUL,
|
||||
DIV,
|
||||
MOD,
|
||||
EQ,
|
||||
NE,
|
||||
LT,
|
||||
GT,
|
||||
LTE,
|
||||
GTE,
|
||||
AND,
|
||||
OR,
|
||||
XOR,
|
||||
LSH,
|
||||
RSH,
|
||||
NOT,
|
||||
Add,
|
||||
Sub,
|
||||
Mul,
|
||||
Div,
|
||||
Mod,
|
||||
Eq,
|
||||
Ne,
|
||||
Lt,
|
||||
Gt,
|
||||
Lte,
|
||||
Gte,
|
||||
And,
|
||||
Or,
|
||||
Xor,
|
||||
Shl,
|
||||
Shr,
|
||||
}
|
||||
|
||||
/// Pattern types.
|
||||
@ -387,7 +386,7 @@ impl Term {
|
||||
if val == 0 {
|
||||
arg
|
||||
} else {
|
||||
Term::Opx { op: Op::SUB, fst: Box::new(arg), snd: Box::new(Term::Num { val }) }
|
||||
Term::Opx { op: Op::Sub, fst: Box::new(arg), snd: Box::new(Term::Num { val }) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -395,7 +394,7 @@ impl Term {
|
||||
if val == 0 {
|
||||
arg
|
||||
} else {
|
||||
Term::Opx { op: Op::ADD, fst: Box::new(arg), snd: Box::new(Term::Num { val }) }
|
||||
Term::Opx { op: Op::Add, fst: Box::new(arg), snd: Box::new(Term::Num { val }) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,8 +186,8 @@ impl<'a> Reader<'a> {
|
||||
2 => {
|
||||
let fst = self.read_term(self.net.enter_port(Port(node, 0)));
|
||||
let snd = self.read_term(self.net.enter_port(Port(node, 1)));
|
||||
|
||||
Term::Opx { op: Op::from_hvmc_label(*opr), fst: Box::new(fst), snd: Box::new(snd) }
|
||||
let (opr, fst, snd) = if is_op_swapped(*opr) { (opr.swap(), snd, fst) } else { (*opr, fst, snd) };
|
||||
Term::Opx { op: Op::from_hvmc_label(opr), fst: Box::new(fst), snd: Box::new(snd) }
|
||||
}
|
||||
_ => {
|
||||
self.error(ReadbackError::InvalidNumericOp);
|
||||
@ -437,27 +437,42 @@ impl Op {
|
||||
pub fn from_hvmc_label(value: hvmc::ops::Op) -> Op {
|
||||
use hvmc::ops::Op as RtOp;
|
||||
match value {
|
||||
RtOp::Add => Op::ADD,
|
||||
RtOp::Sub => Op::SUB,
|
||||
RtOp::Mul => Op::MUL,
|
||||
RtOp::Div => Op::DIV,
|
||||
RtOp::Mod => Op::MOD,
|
||||
RtOp::Eq => Op::EQ,
|
||||
RtOp::Ne => Op::NE,
|
||||
RtOp::Lt => Op::LT,
|
||||
RtOp::Gt => Op::GT,
|
||||
RtOp::Lte => Op::LTE,
|
||||
RtOp::Gte => Op::GTE,
|
||||
RtOp::And => Op::AND,
|
||||
RtOp::Or => Op::OR,
|
||||
RtOp::Xor => Op::XOR,
|
||||
RtOp::Lsh => Op::LSH,
|
||||
RtOp::Rsh => Op::RSH,
|
||||
RtOp::Not => Op::NOT,
|
||||
RtOp::Add => Op::Add,
|
||||
RtOp::Sub => Op::Sub,
|
||||
RtOp::Mul => Op::Mul,
|
||||
RtOp::Div => Op::Div,
|
||||
RtOp::Mod => Op::Mod,
|
||||
RtOp::Eq => Op::Eq,
|
||||
RtOp::Ne => Op::Ne,
|
||||
RtOp::Lt => Op::Lt,
|
||||
RtOp::Gt => Op::Gt,
|
||||
RtOp::Lte => Op::Lte,
|
||||
RtOp::Gte => Op::Gte,
|
||||
RtOp::And => Op::And,
|
||||
RtOp::Or => Op::Or,
|
||||
RtOp::Xor => Op::Xor,
|
||||
RtOp::Shl => Op::Shl,
|
||||
RtOp::Shr => Op::Shr,
|
||||
RtOp::SubS => unreachable!(),
|
||||
RtOp::DivS => unreachable!(),
|
||||
RtOp::ModS => unreachable!(),
|
||||
RtOp::ShlS => unreachable!(),
|
||||
RtOp::ShrS => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_op_swapped(op: hvmc::ops::Op) -> bool {
|
||||
matches!(
|
||||
op,
|
||||
hvmc::ops::Op::ShlS
|
||||
| hvmc::ops::Op::ShrS
|
||||
| hvmc::ops::Op::SubS
|
||||
| hvmc::ops::Op::DivS
|
||||
| hvmc::ops::Op::ModS
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ReadbackError {
|
||||
InvalidNumericMatch,
|
||||
|
@ -174,23 +174,22 @@ where
|
||||
I: ValueInput<'a, Token = Token, Span = SimpleSpan>,
|
||||
{
|
||||
select! {
|
||||
Token::Add => Op::ADD,
|
||||
Token::Sub => Op::SUB,
|
||||
Token::Asterisk => Op::MUL,
|
||||
Token::Div => Op::DIV,
|
||||
Token::Mod => Op::MOD,
|
||||
Token::EqualsEquals => Op::EQ,
|
||||
Token::NotEquals => Op::NE,
|
||||
Token::Ltn => Op::LT,
|
||||
Token::Gtn => Op::GT,
|
||||
Token::Lte => Op::LTE,
|
||||
Token::Gte => Op::GTE,
|
||||
Token::And => Op::AND,
|
||||
Token::Or => Op::OR,
|
||||
Token::Xor => Op::XOR,
|
||||
Token::Tilde => Op::NOT,
|
||||
Token::Shl => Op::LSH,
|
||||
Token::Shr => Op::RSH,
|
||||
Token::Add => Op::Add,
|
||||
Token::Sub => Op::Sub,
|
||||
Token::Asterisk => Op::Mul,
|
||||
Token::Div => Op::Div,
|
||||
Token::Mod => Op::Mod,
|
||||
Token::EqualsEquals => Op::Eq,
|
||||
Token::NotEquals => Op::Ne,
|
||||
Token::Ltn => Op::Lt,
|
||||
Token::Gtn => Op::Gt,
|
||||
Token::Lte => Op::Lte,
|
||||
Token::Gte => Op::Gte,
|
||||
Token::And => Op::And,
|
||||
Token::Or => Op::Or,
|
||||
Token::Xor => Op::Xor,
|
||||
Token::Shl => Op::Shl,
|
||||
Token::Shr => Op::Shr,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -312,23 +312,22 @@ impl Op {
|
||||
pub fn to_hvmc_label(self) -> hvmc::ops::Op {
|
||||
use hvmc::ops::Op as RtOp;
|
||||
match self {
|
||||
Op::ADD => RtOp::Add,
|
||||
Op::SUB => RtOp::Sub,
|
||||
Op::MUL => RtOp::Mul,
|
||||
Op::DIV => RtOp::Div,
|
||||
Op::MOD => RtOp::Mod,
|
||||
Op::EQ => RtOp::Eq,
|
||||
Op::NE => RtOp::Ne,
|
||||
Op::LT => RtOp::Lt,
|
||||
Op::GT => RtOp::Gt,
|
||||
Op::LTE => RtOp::Lte,
|
||||
Op::GTE => RtOp::Gte,
|
||||
Op::AND => RtOp::And,
|
||||
Op::OR => RtOp::Or,
|
||||
Op::XOR => RtOp::Xor,
|
||||
Op::LSH => RtOp::Lsh,
|
||||
Op::RSH => RtOp::Rsh,
|
||||
Op::NOT => RtOp::Not,
|
||||
Op::Add => RtOp::Add,
|
||||
Op::Sub => RtOp::Sub,
|
||||
Op::Mul => RtOp::Mul,
|
||||
Op::Div => RtOp::Div,
|
||||
Op::Mod => RtOp::Mod,
|
||||
Op::Eq => RtOp::Eq,
|
||||
Op::Ne => RtOp::Ne,
|
||||
Op::Lt => RtOp::Lt,
|
||||
Op::Gt => RtOp::Gt,
|
||||
Op::Lte => RtOp::Lte,
|
||||
Op::Gte => RtOp::Gte,
|
||||
Op::And => RtOp::And,
|
||||
Op::Or => RtOp::Or,
|
||||
Op::Xor => RtOp::Xor,
|
||||
Op::Shl => RtOp::Shl,
|
||||
Op::Shr => RtOp::Shr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,4 +2,4 @@
|
||||
source: tests/golden_tests.rs
|
||||
input_file: tests/golden_tests/run_file/lam_op2_nested.hvm
|
||||
---
|
||||
λa (+ (* a a) (+ (+ 2 a) 3))
|
||||
λa (+ (* a a) (+ (+ a 2) 3))
|
||||
|
Loading…
Reference in New Issue
Block a user