Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 6 additions & 14 deletions crates/rue-hir/src/environment.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::cmp::Reverse;

use indexmap::IndexMap;
use num_bigint::BigUint;

use crate::SymbolId;

Expand All @@ -16,7 +17,6 @@ pub enum Environment {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum PathError {
SymbolNotFound,
PathTooLarge,
}

impl Environment {
Expand Down Expand Up @@ -93,23 +93,15 @@ impl Environment {
)
}

pub fn path(&self, symbol_id: SymbolId) -> Result<u32, PathError> {
pub fn path(&self, symbol_id: SymbolId) -> Result<BigUint, PathError> {
let ops = self
.get_pair_ops(symbol_id)
.ok_or(PathError::SymbolNotFound)?;
let mut path: u32 = 1;
let mut path = BigUint::from(1u8);
for op in ops.into_iter().rev() {
match op {
PairOp::First => {
path = path.checked_mul(2).ok_or(PathError::PathTooLarge)?;
}
PairOp::Rest => {
path = path
.checked_mul(2)
.ok_or(PathError::PathTooLarge)?
.checked_add(1)
.ok_or(PathError::PathTooLarge)?;
}
path <<= 1;
if matches!(op, PairOp::Rest) {
path += 1u8;
}
}
Ok(path)
Expand Down
12 changes: 4 additions & 8 deletions crates/rue-hir/src/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ impl<'d, 'a, 'g> Lowerer<'d, 'a, 'g> {
let mut expr = self.lower_hir(&function_env, function.body);

if symbol == self.main && function.kind == FunctionKind::External {
let entire_env = self.arena.alloc(Lir::Path(1));
let entire_env = self.arena.alloc(Lir::Path(1u8.into()));
return self.arena.alloc(Lir::Run(expr, entire_env));
}

Expand All @@ -151,7 +151,7 @@ impl<'d, 'a, 'g> Lowerer<'d, 'a, 'g> {
{
map.insert(symbol, self.arena.alloc(Lir::Quote(expr)));
let reference = self.lower_symbol_reference(&function_env, symbol);
let entire_env = self.arena.alloc(Lir::Path(1));
let entire_env = self.arena.alloc(Lir::Path(1u8.into()));
expr = self.arena.alloc(Lir::Run(reference, entire_env));
}

Expand All @@ -167,7 +167,7 @@ impl<'d, 'a, 'g> Lowerer<'d, 'a, 'g> {
let rest = if param_group.is_empty() {
self.arena.alloc(Lir::Atom(vec![]))
} else {
self.arena.alloc(Lir::Path(1))
self.arena.alloc(Lir::Path(1u8.into()))
};

let group_env =
Expand Down Expand Up @@ -525,10 +525,6 @@ impl<'d, 'a, 'g> Lowerer<'d, 'a, 'g> {
"clvm path in environment not found for symbol {}",
self.db.debug_symbol(symbol)
),
PathError::PathTooLarge => panic!(
"calculated clvm path too large for symbol {}",
self.db.debug_symbol(symbol)
),
},
)))
}
Expand Down Expand Up @@ -598,7 +594,7 @@ impl<'d, 'a, 'g> Lowerer<'d, 'a, 'g> {
bind_env = Self::apply_group(bind_env, group, true);
}

let rest = self.arena.alloc(Lir::Path(1));
let rest = self.arena.alloc(Lir::Path(1u8.into()));
let group_env = self.lower_group_environment(&bind_env, group, rest, false, None, true);

expr = self.arena.alloc(Lir::Run(expr, group_env));
Expand Down
18 changes: 8 additions & 10 deletions crates/rue-lir/src/codegen.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use clvm_traits::{ToClvm, clvm_list, clvm_quote, clvm_tuple};
use clvmr::{Allocator, NodePtr};
use id_arena::Arena;
use num_bigint::BigUint;

use crate::{ClvmOp, Lir, LirId, Result, bigint_atom};
use crate::{ClvmOp, Lir, LirId, Result, path_to_atom};

#[derive(Debug, Default, Clone, Copy)]
pub struct CodegenOptions {
Expand Down Expand Up @@ -41,15 +42,12 @@ fn codegen_impl(
Ok(clvm_quote!(arg).to_clvm(allocator)?)
}
Lir::Path(path) => {
let mut atom = bigint_atom((*path).into());
while !atom.is_empty() && atom[0] == 0 {
atom = atom[1..].to_vec();
}
let atom = path_to_atom(path);
Ok(allocator.new_atom(&atom)?)
}
Lir::Run(callee, env) => {
if options.optimize_static_pairs
&& matches!(arena[*env], Lir::Path(1))
&& matches!(&arena[*env], Lir::Path(path) if path == &BigUint::from(1u8))
&& is_static_value(arena, *callee)
{
return codegen_static_value(arena, allocator, *callee);
Expand Down Expand Up @@ -503,7 +501,7 @@ mod tests {
#[test]
fn test_path() {
let mut arena = Arena::new();
let lir = arena.alloc(Lir::Path(1));
let lir = arena.alloc(Lir::Path(1u8.into()));
check(&arena, lir, expect!["1"]);
}

Expand Down Expand Up @@ -543,7 +541,7 @@ mod tests {
let args = arena.alloc(Lir::Cons(two, args));
let add = arena.alloc(Lir::Atom(vec![16]));
let program = arena.alloc(Lir::Cons(add, args));
let env = arena.alloc(Lir::Path(1));
let env = arena.alloc(Lir::Path(1u8.into()));
let lir = arena.alloc(Lir::Run(program, env));

check_with_options(
Expand All @@ -558,7 +556,7 @@ mod tests {
#[test]
fn test_closure() {
let mut arena = Arena::new();
let path = arena.alloc(Lir::Path(2));
let path = arena.alloc(Lir::Path(2u8.into()));
let add = arena.alloc(Lir::Add(vec![path, path]));
let function = arena.alloc(Lir::Quote(add));
let capture = arena.alloc(Lir::Atom(vec![0x10]));
Expand Down Expand Up @@ -609,7 +607,7 @@ mod tests {
check(&arena, lir, expect![[r#"(c (q . "first") (q . "rest"))"#]]);
check_with_options(&arena, lir, true, expect![[r#"(q "first" . "rest")"#]]);

let path = arena.alloc(Lir::Path(2));
let path = arena.alloc(Lir::Path(2u8.into()));
let lir = arena.alloc(Lir::Cons(path, lir));
check_with_options(
&arena,
Expand Down
3 changes: 2 additions & 1 deletion crates/rue-lir/src/lir.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use clvm_traits::{ToClvm, ToClvmError};
use clvmr::{Allocator, NodePtr};
use id_arena::Id;
use num_bigint::BigUint;

use crate::bigint_atom;

Expand All @@ -9,7 +10,7 @@ pub type LirId = Id<Lir>;
#[derive(Debug, Clone)]
pub enum Lir {
Atom(Vec<u8>),
Path(u32),
Path(BigUint),
Quote(LirId),
Run(LirId, LirId),
Closure(LirId, Vec<LirId>, bool),
Expand Down
20 changes: 11 additions & 9 deletions crates/rue-lir/src/optimize/ops.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::num::Saturating;

use id_arena::Arena;
use num_bigint::{BigInt, Sign};
use num_bigint::{BigInt, BigUint, Sign};
use num_integer::Integer;
use sha2::{Digest, Sha256};
use sha3::Keccak256;
Expand All @@ -18,7 +18,7 @@ pub fn opt_atom(arena: &mut Arena<Lir>, atom: Vec<u8>) -> LirId {
}

// There's no way to optimize a path
pub fn opt_path(arena: &mut Arena<Lir>, path: u32) -> LirId {
pub fn opt_path(arena: &mut Arena<Lir>, path: BigUint) -> LirId {
arena.alloc(Lir::Path(path))
}

Expand All @@ -32,7 +32,9 @@ pub fn opt_quote(arena: &mut Arena<Lir>, value: LirId) -> LirId {
// We can also skip quoting if the program has no path, since it's not going to rely on the environment
pub fn opt_run(arena: &mut Arena<Lir>, callee: LirId, env: LirId) -> LirId {
if let Lir::Quote(value) = arena[callee].clone() {
if let Lir::Path(1) = arena[env].clone() {
if let Lir::Path(path) = arena[env].clone()
&& path == BigUint::from(1u8)
{
return value;
}

Expand Down Expand Up @@ -66,7 +68,7 @@ pub fn opt_closure(
// If the value is a divmod, we can optimize it to a div since that's the first output
pub fn opt_first(arena: &mut Arena<Lir>, value: LirId) -> LirId {
match arena[value].clone() {
Lir::Path(path) => arena.alloc(Lir::Path(first_path(path))),
Lir::Path(path) => arena.alloc(Lir::Path(first_path(&path))),
Lir::Divmod(left, right) => opt_div(arena, left, right),
_ => arena.alloc(Lir::First(value)),
}
Expand All @@ -77,7 +79,7 @@ pub fn opt_first(arena: &mut Arena<Lir>, value: LirId) -> LirId {
// If the value is a divmod, we can optimize it to a remainder since that's the rest output
pub fn opt_rest(arena: &mut Arena<Lir>, value: LirId) -> LirId {
match arena[value].clone() {
Lir::Path(path) => arena.alloc(Lir::Path(rest_path(path))),
Lir::Path(path) => arena.alloc(Lir::Path(rest_path(&path))),
Lir::Divmod(left, right) => opt_mod(arena, left, right),
_ => arena.alloc(Lir::Rest(value)),
}
Expand All @@ -87,10 +89,10 @@ pub fn opt_rest(arena: &mut Arena<Lir>, value: LirId) -> LirId {
pub fn opt_cons(arena: &mut Arena<Lir>, first: LirId, rest: LirId) -> LirId {
if let Lir::Path(f_path) = arena[first].clone()
&& let Lir::Path(r_path) = arena[rest].clone()
&& let Some(parent) = parent_path(f_path)
&& Some(parent) == parent_path(r_path)
&& first_path(parent) == f_path
&& rest_path(parent) == r_path
&& let Some(parent) = parent_path(&f_path)
&& parent_path(&r_path).as_ref() == Some(&parent)
&& first_path(&parent) == f_path
&& rest_path(&parent) == r_path
{
return arena.alloc(Lir::Path(parent));
}
Expand Down
Loading
Loading