/** @file LocalEnv.cpp **/ #include "LocalEnv.hpp" #include "xo/reflect/Reflect.hpp" #include "xo/reflect/StructReflector.hpp" #include namespace xo { using xo::reflect::Reflect; using xo::reflect::StructReflector; using xo::reflect::TypeDescrW; using xo::reflect::TaggedPtr; using xo::reflect::TypeDescrExtra; using xo::reflect::EstablishTypeDescr; using xo::reflect::StlVectorTdx; using xo::print::quot; namespace scm { namespace { std::size_t slot_array_size(std::size_t n) { return n * sizeof(gp); } } gp LocalEnv::make(gc::IAlloc * mm, gp p, const rp & s, std::size_t n) { if (s) { assert(static_cast(n) == s->n_arg()); } return new (MMPtr(mm)) LocalEnv(mm, p, s, n); } LocalEnv::LocalEnv(gc::IAlloc * mm, gp p, const rp & s, std::size_t n) : parent_{p}, symtab_{s}, slot_v_{mm, n} {} bool LocalEnv::local_contains_var(const std::string & vname) const { assert(symtab_.get()); return symtab_->lookup_local(vname); } gp * LocalEnv::lookup_slot(const std::string & vname) { binding_path b = symtab_->lookup_local_binding(vname); if (b.i_link_ == 0) { assert((b.j_slot_ >= 0) && (static_cast(b.j_slot_) < slot_v_.size())); return &(slot_v_[b.j_slot_]); } if (parent_.get()) { return parent_->lookup_slot(vname); } return nullptr; } gp * LocalEnv::establish_var(bp v) { assert(v); throw std::runtime_error(tostr("LocalEnv::establish_var:" " inserting new variables not supported for LocalEnv", xtag("v.name", v->name()))); } TaggedPtr LocalEnv::self_tp() const { return Reflect::make_tp(const_cast(this)); } void LocalEnv::display(std::ostream & os) const { os << ""; } std::size_t LocalEnv::_shallow_size() const { std::size_t retval = sizeof(LocalEnv); retval += gc::IAlloc::with_padding(slot_array_size(slot_v_.size())); return retval; } Object * LocalEnv::_shallow_copy(gc::IAlloc * mm) const { Cpof cpof(mm, this); size_t z = this->size(); LocalEnv * copy = new (cpof) LocalEnv(cpof.mm_, parent_, symtab_, z); void * v_dest = copy->slot_v_.v_; if (slot_v_.v_) { ::memcpy(v_dest, slot_v_.v_, slot_array_size(z)); } #ifdef OBSOLETE for (size_t i = 0, n = n_slot_; i < n; ++i) { copy->v_[i] = v_[i]; } #endif return copy; } std::size_t LocalEnv::_forward_children(gc::IAlloc * gc) { static_assert(decltype(symtab_)::is_gc_ptr == false); Object::_forward_inplace(parent_, gc); // Object::_forward_inplace(symtab_); // not a gp yet for (std::size_t i = 0, n = slot_v_.size(); i < n; ++i) { Object::_forward_inplace((*this)[i], gc); } return _shallow_size(); } void LocalEnv::reflect_self() { StructReflector sr; if (sr.is_incomplete()) { /* reflect CVector> * * note: placement here works b/c CVector not used anywhere else */ using VectorType = obj::CVector>; /* custom reflection for array of Object pointers. * Can use StlVectorTdx here, treating CVector as a vector * via .size() and .operator[] members */ std::unique_ptr tdx1 = std::make_unique>(); TypeDescrW td1 = EstablishTypeDescr::establish(); td1->assign_tdextra(Reflect::get_final_invoker(), std::move(tdx1)); REFLECT_MEMBER(sr, parent); REFLECT_MEMBER(sr, slot_v); } } } /*namespace scm*/ } /*namespace xo*/ /* end LocalEnv.cpp */