feat: initial parallel impl
This commit is contained in:
@@ -7,74 +7,94 @@ use hashbrown::{HashMap, HashSet};
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::engine::Engine;
|
||||
use crate::error::{Error, Result};
|
||||
use crate::ty::public::Symbol;
|
||||
|
||||
use super::super::public as p;
|
||||
use super::Value;
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Constructor, Clone, PartialEq)]
|
||||
pub struct AttrSet<'gc> {
|
||||
data: HashMap<EcoString, Value<'gc>>,
|
||||
pub struct AttrSet {
|
||||
data: HashMap<EcoString, Value>,
|
||||
}
|
||||
|
||||
impl<'gc> From<HashMap<EcoString, Value<'gc>>> for AttrSet<'gc> {
|
||||
fn from(data: HashMap<EcoString, Value<'gc>>) -> Self {
|
||||
impl From<HashMap<EcoString, Value>> for AttrSet {
|
||||
fn from(data: HashMap<EcoString, Value>) -> Self {
|
||||
Self { data }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> Deref for AttrSet<'gc> {
|
||||
type Target = HashMap<EcoString, Value<'gc>>;
|
||||
impl Deref for AttrSet {
|
||||
type Target = HashMap<EcoString, Value>;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.data
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> AttrSet<'gc> {
|
||||
impl AttrSet {
|
||||
pub fn with_capacity(cap: usize) -> Self {
|
||||
AttrSet {
|
||||
data: HashMap::with_capacity(cap),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push_attr_force(&mut self, sym: EcoString, val: Value<'gc>) {
|
||||
pub fn push_attr_force(&mut self, sym: EcoString, val: Value) {
|
||||
self.data.insert(sym, val);
|
||||
}
|
||||
|
||||
pub fn push_attr(&mut self, sym: EcoString, val: Value<'gc>) {
|
||||
pub fn push_attr(&mut self, sym: EcoString, val: Value) {
|
||||
if self.data.get(&sym).is_some() {
|
||||
todo!()
|
||||
}
|
||||
self.data.insert(sym, val);
|
||||
}
|
||||
|
||||
pub fn select(&self, sym: &EcoString) -> Option<Value<'gc>> {
|
||||
self.data.get(sym).cloned()
|
||||
pub fn select(&self, mut path: impl DoubleEndedIterator<Item = Result<EcoString>>) -> Result<Value> {
|
||||
// .ok_or_else(|| Error::EvalError())),
|
||||
let mut data = &self.data;
|
||||
let last = path.nth_back(0).unwrap();
|
||||
for item in path {
|
||||
let item = item?;
|
||||
let Some(Value::AttrSet(attrs)) = data.get(&item) else {
|
||||
return Err(Error::EvalError(format!("{} not found", Symbol::from(item))))
|
||||
};
|
||||
data = attrs.as_inner();
|
||||
}
|
||||
let last = last?;
|
||||
data.get(&last).cloned().ok_or_else(|| Error::EvalError(format!("{} not found", Symbol::from(last))))
|
||||
}
|
||||
|
||||
pub fn has_attr(&self, sym: &EcoString) -> bool {
|
||||
self.data.get(sym).is_some()
|
||||
pub fn has_attr(&self, path: impl IntoIterator<Item = Result<EcoString>>) -> Result<bool> {
|
||||
let mut data = &self.data;
|
||||
for item in path {
|
||||
let Some(Value::AttrSet(attrs)) = data.get(&item?) else {
|
||||
return Ok(false)
|
||||
};
|
||||
data = attrs.as_inner();
|
||||
}
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
pub fn update(&mut self, other: &AttrSet<'gc>) {
|
||||
pub fn update(&mut self, other: &AttrSet) {
|
||||
for (k, v) in other.data.iter() {
|
||||
self.push_attr_force(k.clone(), v.clone())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_inner(&self) -> &HashMap<EcoString, Value<'gc>> {
|
||||
pub fn as_inner(&self) -> &HashMap<EcoString, Value> {
|
||||
&self.data
|
||||
}
|
||||
|
||||
pub fn into_inner(self: Rc<Self>) -> Rc<HashMap<EcoString, Value<'gc>>> {
|
||||
pub fn into_inner(self: Rc<Self>) -> Rc<HashMap<EcoString, Value>> {
|
||||
unsafe { std::mem::transmute(self) }
|
||||
}
|
||||
|
||||
pub fn from_inner(data: HashMap<EcoString, Value<'gc>>) -> Self {
|
||||
pub fn from_inner(data: HashMap<EcoString, Value>) -> Self {
|
||||
Self { data }
|
||||
}
|
||||
|
||||
pub fn eq_impl(&self, other: &AttrSet<'gc>) -> bool {
|
||||
pub fn eq_impl(&self, other: &AttrSet) -> bool {
|
||||
self.data.iter().len() == other.data.iter().len()
|
||||
&& std::iter::zip(
|
||||
self.data.iter().sorted_by(|(a, _), (b, _)| a.cmp(b)),
|
||||
@@ -83,7 +103,7 @@ impl<'gc> AttrSet<'gc> {
|
||||
.all(|((_, v1), (_, v2))| v1.eq_impl(v2))
|
||||
}
|
||||
|
||||
pub fn to_public(&self, engine: &'gc Engine, seen: &mut HashSet<Value<'gc>>) -> p::Value {
|
||||
pub fn to_public(&self, engine: &Engine, seen: &mut HashSet<Value>) -> p::Value {
|
||||
p::Value::AttrSet(p::AttrSet::new(
|
||||
self.data
|
||||
.iter()
|
||||
|
||||
@@ -5,11 +5,11 @@ use crate::env::VmEnv;
|
||||
use crate::ir;
|
||||
pub struct Func<'gc> {
|
||||
pub func: &'gc ir::Func,
|
||||
pub env: Rc<VmEnv<'gc>>,
|
||||
pub env: Rc<VmEnv>,
|
||||
}
|
||||
|
||||
impl<'gc> Func<'gc> {
|
||||
pub fn new(func: &'gc ir::Func, env: Rc<VmEnv<'gc>>) -> Self {
|
||||
pub fn new(func: &'gc ir::Func, env: Rc<VmEnv>) -> Self {
|
||||
Self {
|
||||
func,
|
||||
env,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
use std::ops::Deref;
|
||||
use std::rc::Weak;
|
||||
|
||||
use ecow::EcoVec;
|
||||
use hashbrown::HashSet;
|
||||
|
||||
use crate::env::VmEnv;
|
||||
@@ -9,50 +11,64 @@ use crate::engine::Engine;
|
||||
use super::Value;
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct List<'gc> {
|
||||
data: Vec<Value<'gc>>,
|
||||
pub struct List {
|
||||
data: EcoVec<Value>,
|
||||
}
|
||||
|
||||
impl<'gc> Default for List<'gc> {
|
||||
impl Default for List {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> List<'gc> {
|
||||
impl<'gc, T: Into<EcoVec<Value>>> From<T> for List {
|
||||
fn from(value: T) -> Self {
|
||||
Self { data: value.into() }
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for List {
|
||||
type Target = [Value];
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.data
|
||||
}
|
||||
}
|
||||
|
||||
impl List {
|
||||
pub fn new() -> Self {
|
||||
List { data: Vec::new() }
|
||||
List { data: EcoVec::new() }
|
||||
}
|
||||
|
||||
pub fn with_capacity(cap: usize) -> Self {
|
||||
List {
|
||||
data: Vec::with_capacity(cap),
|
||||
data: EcoVec::with_capacity(cap),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push(&mut self, elem: Value<'gc>) {
|
||||
pub fn push(&mut self, elem: Value) {
|
||||
self.data.push(elem);
|
||||
}
|
||||
|
||||
pub fn concat(&mut self, other: &List<'gc>) {
|
||||
pub fn concat(&mut self, other: &List) {
|
||||
for elem in other.data.iter() {
|
||||
self.data.push(elem.clone());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn capture(&mut self, env: &Weak<VmEnv<'gc>>) {
|
||||
pub fn capture(&mut self, env: &Weak<VmEnv>) {
|
||||
self.data.iter().for_each(|v| {
|
||||
if let Value::Thunk(ref thunk) = v.clone() {
|
||||
thunk.capture_env_weak(env.clone());
|
||||
todo!()
|
||||
// thunk.capture_env_weak(env.clone());
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn into_inner(self) -> Vec<Value<'gc>> {
|
||||
pub fn into_inner(self) -> EcoVec<Value> {
|
||||
self.data
|
||||
}
|
||||
|
||||
pub fn to_public(&self, engine: &'gc Engine, seen: &mut HashSet<Value<'gc>>) -> p::Value {
|
||||
pub fn to_public(&self, engine: &Engine, seen: &mut HashSet<Value>) -> p::Value {
|
||||
p::Value::List(p::List::new(
|
||||
self.data
|
||||
.iter()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use std::cell::RefCell;
|
||||
use std::hash::Hash;
|
||||
use std::rc::{Rc, Weak};
|
||||
use std::sync::RwLock;
|
||||
|
||||
use derive_more::{IsVariant, Unwrap};
|
||||
use ecow::EcoString;
|
||||
@@ -21,39 +22,84 @@ mod primop;
|
||||
mod string;
|
||||
|
||||
pub use attrset::*;
|
||||
pub use func::*;
|
||||
pub use list::List;
|
||||
pub use primop::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum EnvRef {
|
||||
Strong(Rc<VmEnv>),
|
||||
Weak(Weak<VmEnv>)
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ThunkRef {
|
||||
pub idx: usize,
|
||||
pub env: Option<EnvRef>
|
||||
}
|
||||
|
||||
pub enum Thunk {
|
||||
Expr(ThunkRef),
|
||||
Suspended,
|
||||
Value(Value)
|
||||
}
|
||||
|
||||
impl Thunk {
|
||||
pub fn new(idx: usize) -> Self {
|
||||
Thunk::Expr(ThunkRef::new(idx))
|
||||
}
|
||||
|
||||
pub fn force(&mut self, engine: &Engine) -> Result<Value> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl ThunkRef {
|
||||
pub fn new(idx: usize) -> Self {
|
||||
ThunkRef { idx, env: None }
|
||||
}
|
||||
|
||||
pub fn capture(&mut self, env: EnvRef) {
|
||||
let _ = self.env.insert(env);
|
||||
}
|
||||
}
|
||||
|
||||
impl EnvRef {
|
||||
pub fn upgrade(&mut self) {
|
||||
if let EnvRef::Weak(weak) = &*self {
|
||||
*self = EnvRef::Strong(weak.upgrade().unwrap())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(IsVariant, Unwrap, Clone)]
|
||||
pub enum Value<'gc> {
|
||||
pub enum Value {
|
||||
Int(i64),
|
||||
Float(f64),
|
||||
Bool(bool),
|
||||
String(EcoString),
|
||||
Null,
|
||||
Thunk(Thunk<'gc>),
|
||||
AttrSet(Rc<AttrSet<'gc>>),
|
||||
List(Rc<List<'gc>>),
|
||||
Thunk(Rc<RwLock<Thunk>>),
|
||||
AttrSet(Rc<AttrSet>),
|
||||
List(List),
|
||||
Catchable(EcoString),
|
||||
PrimOp(Rc<PrimOp>),
|
||||
PartialPrimOp(Rc<PartialPrimOp<'gc>>),
|
||||
Func(Rc<Func<'gc>>),
|
||||
PartialPrimOp(Rc<PartialPrimOp>),
|
||||
Func(Rc<RwLock<ThunkRef>>),
|
||||
}
|
||||
|
||||
impl Hash for Value<'_> {
|
||||
impl Hash for Value {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
use Value::*;
|
||||
std::mem::discriminant(self).hash(state);
|
||||
match self {
|
||||
AttrSet(x) => Rc::as_ptr(x).hash(state),
|
||||
List(x) => Rc::as_ptr(x).hash(state),
|
||||
List(x) => x.as_ptr().hash(state),
|
||||
_ => 0.hash(state),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> Value<'gc> {
|
||||
impl Value {
|
||||
fn eq_impl(&self, other: &Self) -> bool {
|
||||
use Value::*;
|
||||
match (self, other) {
|
||||
@@ -71,37 +117,37 @@ impl<'gc> Value<'gc> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> PartialEq for Value<'gc> {
|
||||
impl PartialEq for Value {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
use Value::*;
|
||||
match (self, other) {
|
||||
(AttrSet(a), AttrSet(b)) => Rc::as_ptr(a).eq(&Rc::as_ptr(b)),
|
||||
(List(a), List(b)) => Rc::as_ptr(a).eq(&Rc::as_ptr(b)),
|
||||
(List(a), List(b)) => a.as_ptr().eq(&b.as_ptr()),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Value<'_> {}
|
||||
impl Eq for Value {}
|
||||
|
||||
#[derive(IsVariant, Unwrap, Clone)]
|
||||
pub enum ValueAsRef<'v, 'gc> {
|
||||
pub enum ValueAsRef<'v> {
|
||||
Int(i64),
|
||||
Float(f64),
|
||||
Bool(bool),
|
||||
String(&'v str),
|
||||
String(&'v EcoString),
|
||||
Null,
|
||||
Thunk(&'v Thunk<'gc>),
|
||||
AttrSet(&'v AttrSet<'gc>),
|
||||
List(&'v List<'gc>),
|
||||
Thunk(&'v RwLock<Thunk>),
|
||||
AttrSet(&'v AttrSet),
|
||||
List(&'v List),
|
||||
Catchable(&'v str),
|
||||
PrimOp(&'v PrimOp),
|
||||
PartialPrimOp(&'v PartialPrimOp<'gc>),
|
||||
Func(&'v Func<'gc>),
|
||||
PartialPrimOp(&'v PartialPrimOp),
|
||||
Func(&'v RwLock<ThunkRef>),
|
||||
}
|
||||
|
||||
impl<'gc, 'v> Value<'gc> {
|
||||
pub fn as_ref(&'v self) -> ValueAsRef<'v, 'gc> {
|
||||
impl Value {
|
||||
pub fn as_ref(&self) -> ValueAsRef {
|
||||
use Value::*;
|
||||
use ValueAsRef as R;
|
||||
match self {
|
||||
@@ -120,7 +166,7 @@ impl<'gc, 'v> Value<'gc> {
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'gc> Value<'gc> {
|
||||
impl Value {
|
||||
pub fn ok(self) -> Result<Self> {
|
||||
Ok(self)
|
||||
}
|
||||
@@ -151,15 +197,15 @@ impl<'gc> Value<'gc> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn call(&mut self, arg: Self, vm: &Engine) -> Result<()> {
|
||||
pub fn call(&mut self, arg: Self, engine: &Engine) -> Result<()> {
|
||||
use Value::*;
|
||||
if matches!(arg, Value::Catchable(_)) {
|
||||
*self = arg;
|
||||
return Ok(());
|
||||
}
|
||||
*self = match self {
|
||||
PrimOp(func) => func.call(arg, vm),
|
||||
PartialPrimOp(func) => func.call(arg, vm),
|
||||
PrimOp(func) => func.call(arg, engine),
|
||||
PartialPrimOp(func) => func.call(arg, engine),
|
||||
Catchable(_) => return Ok(()),
|
||||
_ => todo!(),
|
||||
}?;
|
||||
@@ -293,7 +339,7 @@ impl<'gc> Value<'gc> {
|
||||
|
||||
pub fn push(&mut self, elem: Self) -> &mut Self {
|
||||
if let Value::List(list) = self {
|
||||
Rc::make_mut(list).push(elem);
|
||||
list.push(elem);
|
||||
} else if let Value::Catchable(_) = self {
|
||||
} else if let Value::Catchable(_) = elem {
|
||||
*self = elem;
|
||||
@@ -310,7 +356,7 @@ impl<'gc> Value<'gc> {
|
||||
}
|
||||
match (self, other) {
|
||||
(Value::List(a), Value::List(b)) => {
|
||||
Rc::make_mut(a).concat(&b);
|
||||
a.concat(&b);
|
||||
}
|
||||
(Value::Catchable(_), _) => (),
|
||||
_ => todo!(),
|
||||
@@ -343,11 +389,10 @@ impl<'gc> Value<'gc> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn select(&mut self, sym: &EcoString) -> Result<&mut Self> {
|
||||
pub fn select(&mut self, path: impl DoubleEndedIterator<Item = Result<EcoString>>) -> Result<&mut Self> {
|
||||
let val = match self {
|
||||
Value::AttrSet(attrs) => attrs
|
||||
.select(sym)
|
||||
.ok_or_else(|| Error::EvalError(format!("{} not found", Symbol::from(sym.as_str())))),
|
||||
.select(path),
|
||||
Value::Catchable(_) => return Ok(self),
|
||||
_ => Err(Error::EvalError(format!(
|
||||
"cannot select from {:?}",
|
||||
@@ -358,9 +403,9 @@ impl<'gc> Value<'gc> {
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn select_with_default(&mut self, sym: &EcoString, default: Self) -> Result<&mut Self> {
|
||||
pub fn select_with_default(&mut self, path: impl DoubleEndedIterator<Item = Result<EcoString>>, default: Self) -> Result<&mut Self> {
|
||||
let val = match self {
|
||||
Value::AttrSet(attrs) => attrs.select(sym).unwrap_or(default),
|
||||
Value::AttrSet(attrs) => attrs.select(path).unwrap_or(default),
|
||||
Value::Catchable(_) => return Ok(self),
|
||||
_ => {
|
||||
return Err(Error::EvalError(format!(
|
||||
@@ -373,15 +418,15 @@ impl<'gc> Value<'gc> {
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn has_attr(&mut self, sym: &EcoString) -> &mut Self {
|
||||
pub fn has_attr(&mut self, path: impl IntoIterator<Item = Result<EcoString>>) -> Result<()> {
|
||||
if let Value::AttrSet(attrs) = self {
|
||||
let val = Value::Bool(attrs.has_attr(sym));
|
||||
let val = Value::Bool(attrs.has_attr(path)?);
|
||||
*self = val;
|
||||
} else if let Value::Catchable(_) = self {
|
||||
} else {
|
||||
*self = Value::Bool(false);
|
||||
}
|
||||
self
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn coerce_to_string(&mut self) -> &mut Self {
|
||||
@@ -393,7 +438,18 @@ impl<'gc> Value<'gc> {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn to_public(&self, vm: &'gc Engine, seen: &mut HashSet<Value<'gc>>) -> p::Value {
|
||||
pub fn force(&mut self, engine: &Engine) -> Result<&mut Self> {
|
||||
if let Value::Thunk(thunk) = &*self {
|
||||
let val = {
|
||||
let mut thunk = thunk.write().unwrap();
|
||||
thunk.force(engine)
|
||||
}?;
|
||||
*self = val;
|
||||
}
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn to_public(&self, engine: &Engine, seen: &mut HashSet<Value>) -> p::Value {
|
||||
use self::Value::*;
|
||||
use p::Value;
|
||||
if seen.contains(self) {
|
||||
@@ -402,11 +458,11 @@ impl<'gc> Value<'gc> {
|
||||
match self {
|
||||
AttrSet(attrs) => {
|
||||
seen.insert(self.clone());
|
||||
attrs.to_public(vm, seen)
|
||||
attrs.to_public(engine, seen)
|
||||
}
|
||||
List(list) => {
|
||||
seen.insert(self.clone());
|
||||
list.to_public(vm, seen)
|
||||
list.to_public(engine, seen)
|
||||
}
|
||||
Catchable(catchable) => Value::Catchable(catchable.clone().into()),
|
||||
Int(x) => Value::Const(Const::Int(*x)),
|
||||
@@ -422,90 +478,3 @@ impl<'gc> Value<'gc> {
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Clone)]
|
||||
pub struct Thunk<'gc> {
|
||||
pub thunk: Rc<RefCell<_Thunk<'gc>>>,
|
||||
}
|
||||
|
||||
// TODO: impl
|
||||
type OpCodes = ();
|
||||
|
||||
#[derive(IsVariant, Unwrap)]
|
||||
pub enum _Thunk<'gc> {
|
||||
Code(&'gc OpCodes, Option<Env<'gc>>),
|
||||
Suspended,
|
||||
Value(Value<'gc>),
|
||||
}
|
||||
|
||||
#[derive(Unwrap)]
|
||||
pub enum Env<'gc> {
|
||||
Strong(Rc<VmEnv<'gc>>),
|
||||
Weak(Weak<VmEnv<'gc>>),
|
||||
}
|
||||
|
||||
impl Env<'_> {
|
||||
fn upgrade(self) -> Self {
|
||||
if let Self::Weak(weak) = self {
|
||||
Env::Strong(weak.upgrade().unwrap())
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> Thunk<'gc> {
|
||||
pub fn new(opcodes: &'gc OpCodes) -> Self {
|
||||
Thunk {
|
||||
thunk: RefCell::new(_Thunk::Code(opcodes, None)).into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn capture_env(&self, env: Rc<VmEnv<'gc>>) {
|
||||
if let _Thunk::Code(_, envcell) = &mut *self.thunk.borrow_mut() {
|
||||
let _ = envcell.insert(Env::Strong(env));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn capture_env_weak(&self, env: Weak<VmEnv<'gc>>) {
|
||||
if let _Thunk::Code(_, envcell) = &mut *self.thunk.borrow_mut() {
|
||||
let _ = envcell.insert(Env::Weak(env));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn upgrade(&self) {
|
||||
replace_with_or_abort(&mut *self.thunk.borrow_mut(), |this| {
|
||||
if let _Thunk::Code(opcodes, envcell) = this {
|
||||
_Thunk::Code(opcodes, envcell.map(Env::upgrade))
|
||||
} else {
|
||||
this
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub fn suspend(&self) -> Result<(&'gc OpCodes, Rc<VmEnv<'gc>>)> {
|
||||
use _Thunk::*;
|
||||
match std::mem::replace(&mut *self.thunk.borrow_mut(), _Thunk::Suspended) {
|
||||
Code(opcodes, env) => Ok((opcodes, env.unwrap().upgrade().unwrap_strong())),
|
||||
_ => Err(Error::EvalError("infinite recursion encountered".into())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_value(&self, value: Value<'gc>) {
|
||||
*self.thunk.borrow_mut() = _Thunk::Value(value);
|
||||
}
|
||||
|
||||
pub fn get_value(&self) -> Option<&Value<'gc>> {
|
||||
if let _Thunk::Value(val) = unsafe { &*self.thunk.as_ptr() } {
|
||||
Some(val)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Thunk<'_> {
|
||||
fn eq(&self, _: &Self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ use super::Value;
|
||||
pub struct PrimOp {
|
||||
pub name: &'static str,
|
||||
arity: usize,
|
||||
func: for<'gc> fn(Vec<Value<'gc>>, &Engine) -> Result<Value<'gc>>,
|
||||
func: fn(Vec<Value>, &Engine) -> Result<Value>,
|
||||
}
|
||||
|
||||
impl PartialEq for PrimOp {
|
||||
@@ -21,7 +21,7 @@ impl PartialEq for PrimOp {
|
||||
}
|
||||
|
||||
impl PrimOp {
|
||||
pub fn call<'gc>(&self, arg: Value<'gc>, ctx: &Engine) -> Result<Value<'gc>> {
|
||||
pub fn call(&self, arg: Value, ctx: &Engine) -> Result<Value> {
|
||||
let mut args = Vec::with_capacity(self.arity);
|
||||
args.push(arg);
|
||||
if self.arity > 1 {
|
||||
@@ -39,21 +39,21 @@ impl PrimOp {
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct PartialPrimOp<'gc> {
|
||||
pub struct PartialPrimOp {
|
||||
pub name: &'static str,
|
||||
arity: usize,
|
||||
args: Vec<Value<'gc>>,
|
||||
func: fn(Vec<Value<'gc>>, &Engine) -> Result<Value<'gc>>,
|
||||
args: Vec<Value>,
|
||||
func: fn(Vec<Value>, &Engine) -> Result<Value>,
|
||||
}
|
||||
|
||||
impl PartialEq for PartialPrimOp<'_> {
|
||||
impl PartialEq for PartialPrimOp {
|
||||
fn eq(&self, _: &Self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gc> PartialPrimOp<'gc> {
|
||||
pub fn call(self: &mut Rc<Self>, arg: Value<'gc>, ctx: &Engine) -> Result<Value<'gc>> {
|
||||
impl PartialPrimOp {
|
||||
pub fn call(self: &mut Rc<Self>, arg: Value, ctx: &Engine) -> Result<Value> {
|
||||
let func = self.func;
|
||||
let Some(ret) = ({
|
||||
let self_mut = Rc::make_mut(self);
|
||||
|
||||
Reference in New Issue
Block a user