// --------------------------------------------------------------------------- // - Localset.cpp - // - afnix engine - local set class implementation - // --------------------------------------------------------------------------- // - This program is free software; you can redistribute it and/or modify - // - it provided that this copyright notice is kept intact. - // - - // - This program is distributed in the hope that it will be useful, but - // - without any warranty; without even the implied warranty of - // - merchantability or fitness for a particular purpose. In no event shall - // - the copyright holder be liable for any direct, indirect, incidental or - // - special damages arising in any way out of the use of this software. - // --------------------------------------------------------------------------- // - copyright (c) 1999-2007 amaury darsch - // --------------------------------------------------------------------------- #include "Symbol.hpp" #include "Runnable.hpp" #include "Localset.hpp" #include "Exception.hpp" namespace afnix { // ------------------------------------------------------------------------- // - private section - // ------------------------------------------------------------------------- // this local set quark static const long QUARK_THIS = String::intern ("."); // ------------------------------------------------------------------------- // - class section - // ------------------------------------------------------------------------- // create a new local set Localset::Localset (void) { p_ptbl = new NameTable; p_stbl = nilp; Object::iref (p_ptbl); } // create a new local set but use only the primary table Localset::Localset (Localset* lset) { if (lset == nilp) { p_ptbl = new NameTable; p_stbl = nilp; } else { p_ptbl = lset->p_ptbl; p_stbl = new NameTable; symcst (QUARK_THIS, this); } Object::iref (p_ptbl); Object::iref (p_stbl); } // destroy this local set Localset::~Localset (void) { // protect us Object::iref (this); // destroy everything Object::dref (p_ptbl); Object::dref (p_stbl); } // return the class name String Localset::repr (void) const { return "Localset"; } void Localset::mksho (void) { if (p_shared != nilp) return; Object::mksho (); if (p_ptbl != nilp) p_ptbl->mksho (); } // reset the secondary name table / may be the first void Localset::reset (void) { wrlock (); try { // protect us before reset Object::iref (this); if (p_stbl != nilp) { p_stbl->reset (); Object::tref (this); unlock (); return; } if (p_ptbl != nilp) p_ptbl->reset (); Object::tref (this); unlock (); } catch (...) { unlock (); throw; } } // create a child local set Nameset* Localset::dup (void) { rdlock (); try { Nameset* result = new Localset; result->setparent (this); unlock (); return result; } catch (...) { unlock (); throw; } } // bind a new object by quark void Localset::bind (const long quark, Object* object) { wrlock (); try { if (p_stbl != nilp) p_stbl->add (quark, object); else p_ptbl->add (quark, object); unlock (); } catch (...) { unlock (); throw; } } // return true if the quark exists in the local set bool Localset::exists (const long quark) const { rdlock (); try { if (p_stbl != nilp) return p_stbl->exists (quark); bool result = p_ptbl->exists (quark); unlock (); return result; } catch (...) { unlock (); throw; } } // find an object in this local set by quark Object* Localset::find (const long quark) const { rdlock (); try { Object* obj = nilp; if (p_stbl != nilp) { obj = p_stbl->get (quark); if (obj == nilp) obj = p_ptbl->get (quark); } else { obj = p_ptbl->get (quark); } if (obj != nilp) { unlock (); return obj; } if (p_parent != nilp) { Object* result = p_parent->find (quark); unlock (); return result; } unlock (); return nilp; } catch (...) { unlock (); throw; } } // remove an object by quark in this localset void Localset::remove (const long quark) { wrlock (); try { Object::iref (this); if ((p_stbl != nilp) && (p_stbl->exists (quark) == true)) { p_stbl->remove (quark); Object::tref (this); unlock (); return; } p_ptbl->remove (quark); Object::tref (this); unlock (); } catch (...) { unlock (); throw; } } // set a constant object by quark Object* Localset::cdef (Runnable* robj, Nameset* nset, const long quark, Object* object) { wrlock (); try { Object* obj = nilp; if (p_stbl != nilp) { obj = p_stbl->get (quark); if (obj == nilp) obj = p_ptbl->get (quark); } else { obj = p_ptbl->get (quark); } if (obj != nilp) { obj->cdef (robj, nset, object); robj->post (object); unlock (); return object; } // the object is not found - create a symbol and bind it Symbol* sym = new Symbol (quark, object); sym->setconst (true); if (p_stbl != nilp) p_stbl->add (quark, sym); else p_ptbl->add (quark, sym); robj->post (object); unlock (); return object; } catch (...) { unlock (); throw; } } // set an object by quark Object* Localset::vdef (Runnable* robj, Nameset* nset, const long quark, Object* object) { wrlock (); try { // try first to find the object Object* obj = nilp; if (p_stbl != nilp) { obj = p_stbl->get (quark); if (obj == nilp) obj = p_ptbl->get (quark); } else { obj = p_ptbl->get (quark); } if (obj != nilp) { obj->vdef (robj, nset, object); robj->post (object); unlock (); return object; } // the object is not found - create a symbol and bind it Symbol* sym = new Symbol (quark, object); if (p_stbl != nilp) p_stbl->add (quark, sym); else p_ptbl->add (quark, sym); robj->post (object); unlock (); return object; } catch (...) { unlock (); throw; } } // evaluate an object in the current nameset by quark Object* Localset::eval (Runnable* robj, Nameset* nset, const long quark) { rdlock (); try { // try first to find the object Object* obj = nilp; if (p_stbl != nilp) { obj = p_stbl->get (quark); if (obj == nilp) obj = p_ptbl->get (quark); } else { obj = p_ptbl->get (quark); } if (obj != nilp) { Object* result = obj->eval (robj, nset); robj->post (result); unlock (); return result; } // try in the parent if (p_parent != nilp) { Object* result = p_parent->eval (robj, nset, quark); robj->post (result); unlock (); return result; } // not found throw Exception ("eval-error", "unbound symbol", String::qmap (quark)); } catch (...) { unlock (); throw; } } }