1use crate::{future_wrapper, rc_fn_helper, Binding, ObjValue};2use std::{cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc};34rc_fn_helper!(5 ContextCreator,6 context_creator,7 dyn Fn(Option<ObjValue>, Option<ObjValue>) -> Context8);910future_wrapper!(Context, FutureContext);1112#[derive(Debug)]13struct ContextInternals {14 dollar: Option<ObjValue>,15 this: Option<ObjValue>,16 super_obj: Option<ObjValue>,17 bindings: Rc<RefCell<HashMap<String, Binding>>>,18}19pub struct Context(Rc<ContextInternals>);20impl Debug for Context {21 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {22 f.debug_struct("Context")23 .field("this", &self.0.this.clone().map(|e| Rc::as_ptr(&e.0)))24 .finish()25 }26}27impl Context {28 pub fn new_future() -> FutureContext {29 FutureContext(Rc::new(RefCell::new(None)))30 }3132 pub fn dollar(&self) -> &Option<ObjValue> {33 &self.0.dollar34 }3536 pub fn this(&self) -> &Option<ObjValue> {37 &self.0.this38 }3940 pub fn super_obj(&self) -> &Option<ObjValue> {41 &self.0.super_obj42 }4344 pub fn new() -> Context {45 Context(Rc::new(ContextInternals {46 dollar: None,47 this: None,48 super_obj: None,49 bindings: Rc::new(RefCell::new(HashMap::new())),50 }))51 }5253 pub fn binding(&self, name: &str) -> Binding {54 self.055 .bindings56 .borrow()57 .get(name)58 .cloned()59 .unwrap_or_else(|| {60 panic!("can't find {} in {:?}", name, self);61 })62 }63 pub fn into_future(self, ctx: FutureContext) -> Context {64 {65 ctx.0.borrow_mut().replace(self);66 }67 ctx.unwrap()68 }6970 pub fn extend(71 &self,72 new_bindings: HashMap<String, Binding>,73 new_dollar: Option<ObjValue>,74 new_this: Option<ObjValue>,75 new_super_obj: Option<ObjValue>,76 ) -> Context {77 let dollar = new_dollar.or_else(|| self.0.dollar.clone());78 let this = new_this.or_else(|| self.0.this.clone());79 let super_obj = new_super_obj.or_else(|| self.0.super_obj.clone());80 let bindings = if new_bindings.is_empty() {81 self.0.bindings.clone()82 } else {83 let new = self.0.bindings.clone();84 for (k, v) in new_bindings.into_iter() {85 new.borrow_mut().insert(k, v);86 }87 new88 };89 Context(Rc::new(ContextInternals {90 dollar,91 this,92 super_obj,93 bindings,94 }))95 }96}9798impl Default for Context {99 fn default() -> Self {100 Self::new()101 }102}103104impl PartialEq for Context {105 fn eq(&self, other: &Self) -> bool {106 Rc::ptr_eq(&self.0, &other.0)107 }108}109110impl Clone for Context {111 fn clone(&self) -> Self {112 Context(self.0.clone())113 }114}