Skip to content

Commit

Permalink
refactor: Refactor Ptr struct to generic with type Tag (lurk-lab#651)
Browse files Browse the repository at this point in the history
- Refactored `Ptr` struct into a generic `GPtr` struct, introducing type parameter `T` and associating it with `Tag` interface.
- Created `Ptr` and `ContPtr` types derived from `GPtr`.
- Transferred pertinent predicate methods such as `is_nil`, `is_cons`, `is_atom`, `is_list`, `as_cons`, `as_list` to the new `GPtr<F, ExprTag>` implementation.
- Transferred `ContPtr` struct and corresponding methods to `GPtr<F, ContTag>`.
- No modifications made to `ExprTag` and associated enum elements in `tag.rs`.
- Added `std::hash::Hash` trait to `Tag` interface in `tag.rs`.
  • Loading branch information
huitseeker authored Sep 7, 2023
1 parent 899c433 commit c678647
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 100 deletions.
160 changes: 61 additions & 99 deletions src/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::hash::Hash;
use std::marker::PhantomData;

use crate::field::LurkField;
use crate::tag::{ContTag, ExprTag};
use crate::tag::{ContTag, ExprTag, Tag};

/// The internal untagged raw Store pointer
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
Expand Down Expand Up @@ -53,9 +53,9 @@ impl RawPtr {

/// A `Store` pointer
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Ptr<F: LurkField> {
pub struct GPtr<F: LurkField, T: Tag> {
/// An expression tag
pub tag: ExprTag,
pub tag: T,
/// The underlying pointer, which can be null, opaque, or an index
pub raw: RawPtr,
/// PhantomData is needed to consume the `F: LurkField` parameter, since
Expand All @@ -65,97 +65,48 @@ pub struct Ptr<F: LurkField> {
}

#[allow(clippy::derived_hash_with_manual_eq)]
impl<F: LurkField> Hash for Ptr<F> {
impl<F: LurkField, T: Tag> Hash for GPtr<F, T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.tag.hash(state);
self.raw.hash(state);
}
}

impl<F: LurkField> Ptr<F> {
// TODO: Make these methods and the similar ones defined on expression consistent, probably including a shared trait.

// NOTE: Although this could be a type predicate now, when NIL becomes a symbol, it won't be possible.
/// check if a Ptr is `Nil` pointer
pub const fn is_nil(&self) -> bool {
matches!(self.tag, ExprTag::Nil)
// FIXME: check value also, probably
}

/// check if a Ptr is a `Cons` pointer
pub const fn is_cons(&self) -> bool {
matches!(self.tag, ExprTag::Cons)
}

// TODO: Is this still needed?
/// check if a Ptr is atomic pointer
pub const fn is_atom(&self) -> bool {
!self.is_cons()
}

// check if a Ptr is a list pointer
pub const fn is_list(&self) -> bool {
matches!(self.tag, ExprTag::Nil | ExprTag::Cons)
}
pub type Ptr<F> = GPtr<F, ExprTag>;
pub type ContPtr<F> = GPtr<F, ContTag>;

impl<F: LurkField, T: Tag> GPtr<F, T> {
/// check if a Ptr is an opaque pointer
pub const fn is_opaque(&self) -> bool {
self.raw.is_opaque()
}

// TODO: Is this still needed?
pub const fn as_cons(self) -> Option<Self> {
if self.is_cons() {
Some(self)
} else {
None
}
}

// TODO: Is this still needed?
pub const fn as_list(self) -> Option<Self> {
if self.is_list() {
Some(self)
} else {
None
}
}

/// Construct a Ptr from an index
pub fn index(tag: ExprTag, idx: usize) -> Self {
Ptr {
pub fn index(tag: T, idx: usize) -> Self {
GPtr {
tag,
raw: RawPtr::Index(idx),
_f: Default::default(),
}
}

/// Construct a Ptr from an opaque index
pub fn opaque(tag: ExprTag, idx: usize) -> Self {
Ptr {
pub fn opaque(tag: T, idx: usize) -> Self {
GPtr {
tag,
raw: RawPtr::Opaque(idx),
_f: Default::default(),
}
}

/// Construct a null Ptr
pub fn null(tag: ExprTag) -> Self {
Ptr {
pub fn null(tag: T) -> Self {
GPtr {
tag,
raw: RawPtr::Null,
_f: Default::default(),
}
}

#[inline]
pub fn cast(self, tag: ExprTag) -> Self {
Ptr {
tag,
raw: self.raw,
_f: self._f,
}
}
}

impl<F: LurkField> From<char> for Ptr<F> {
Expand All @@ -168,58 +119,69 @@ impl<F: LurkField> From<char> for Ptr<F> {
}
}

/// A pointer to a continuation. Logically this is the same a Ptr and should
/// probably be combined with it in a future refactor
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct ContPtr<F: LurkField> {
pub tag: ContTag,
pub raw: RawPtr,
pub _f: PhantomData<F>,
}
impl<F: LurkField> GPtr<F, ExprTag> {
#[inline]
pub fn cast(self, tag: ExprTag) -> Self {
GPtr {
tag,
raw: self.raw,
_f: self._f,
}
}

#[allow(clippy::derived_hash_with_manual_eq)]
impl<F: LurkField> Hash for ContPtr<F> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.tag.hash(state);
self.raw.hash(state);
// TODO: Is this still needed?
pub const fn as_cons(self) -> Option<Self> {
if self.is_cons() {
Some(self)
} else {
None
}
}
}

impl<F: LurkField> ContPtr<F> {
pub fn new(tag: ContTag, raw: RawPtr) -> Self {
Self {
tag,
raw,
_f: Default::default(),
// TODO: Is this still needed?
pub const fn as_list(self) -> Option<Self> {
if self.is_list() {
Some(self)
} else {
None
}
}
pub const fn is_error(&self) -> bool {
matches!(self.tag, ContTag::Error)

// NOTE: Although this could be a type predicate now, when NIL becomes a symbol, it won't be possible.
/// check if a Ptr is `Nil` pointer
pub const fn is_nil(&self) -> bool {
matches!(self.tag, ExprTag::Nil)
// FIXME: check value also, probably
}

pub fn index(tag: ContTag, idx: usize) -> Self {
ContPtr {
tag,
raw: RawPtr::Index(idx),
_f: Default::default(),
}
/// check if a Ptr is a `Cons` pointer
pub const fn is_cons(&self) -> bool {
matches!(self.tag, ExprTag::Cons)
}

pub fn opaque(tag: ContTag, idx: usize) -> Self {
ContPtr {
tag,
raw: RawPtr::Index(idx),
_f: Default::default(),
}
// TODO: Is this still needed?
/// check if a Ptr is atomic pointer
pub const fn is_atom(&self) -> bool {
!self.is_cons()
}

// check if a Ptr is a list pointer
pub const fn is_list(&self) -> bool {
matches!(self.tag, ExprTag::Nil | ExprTag::Cons)
}
}

pub fn null(tag: ContTag) -> Self {
ContPtr {
impl<F: LurkField> ContPtr<F> {
pub fn new(tag: ContTag, raw: RawPtr) -> Self {
Self {
tag,
raw: RawPtr::Null,
raw,
_f: Default::default(),
}
}
pub const fn is_error(&self) -> bool {
matches!(self.tag, ContTag::Error)
}
}

pub trait TypePredicates {
Expand Down
2 changes: 1 addition & 1 deletion src/tag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::{convert::TryFrom, fmt};
use crate::field::LurkField;
use crate::ptr::TypePredicates;

pub trait Tag: Into<u16> + TryFrom<u16> + Copy + Sized + Eq + fmt::Debug {
pub trait Tag: Into<u16> + TryFrom<u16> + Copy + Sized + std::hash::Hash + Eq + fmt::Debug {
fn from_field<F: LurkField>(f: &F) -> Option<Self>;
fn to_field<F: LurkField>(&self) -> F;

Expand Down

0 comments on commit c678647

Please sign in to comment.