use crate::panic::{RuntimeError, runtime_error};
use crate::place::Ptr;
use crate::trace::{Trace, Tracer};
use crate::value::GoValue;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct Env(usize);
impl Env {
pub const NONE: Env = Env(0);
#[inline]
pub fn of<P>(p: Ptr<P>) -> Env {
Env(p.addr() as usize)
}
#[inline]
pub fn addr(self) -> u64 {
self.0 as u64
}
#[inline]
pub fn cast<P>(self) -> Ptr<P> {
unsafe { Ptr::from_addr(self.0) }
}
}
impl Trace for Env {
#[inline]
fn trace(&self, t: &mut Tracer<'_>) {
t.edge(self.0);
}
}
pub struct Func<F: Copy + 'static> {
code: Option<F>,
env: Env,
}
impl<F: Copy> Clone for Func<F> {
fn clone(&self) -> Self {
*self
}
}
impl<F: Copy> Copy for Func<F> {}
impl<F: Copy> GoValue for Func<F> {
#[inline]
fn zero() -> Self {
Func {
code: None,
env: Env::NONE,
}
}
}
impl<F: Copy> Trace for Func<F> {
#[inline]
fn trace(&self, t: &mut Tracer<'_>) {
self.env.trace(t);
}
}
impl<F: Copy> PartialEq for Func<F> {
fn eq(&self, other: &Self) -> bool {
self.is_nil() == other.is_nil()
}
}
impl<F: Copy> Func<F> {
#[inline]
pub fn new(code: F, env: Env) -> Self {
Func {
code: Some(code),
env,
}
}
#[inline]
pub fn is_nil(self) -> bool {
self.code.is_none()
}
#[inline]
pub fn code(self) -> F {
match self.code {
Some(f) => f,
None => runtime_error(RuntimeError::NilDeref),
}
}
#[inline]
pub fn env(self) -> Env {
self.env
}
pub fn addr(self) -> u64 {
self.env.0 as u64
}
}