// ---------------------------------------------------------------------------
// - 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;
}
}
}
syntax highlighted by Code2HTML, v. 0.9.1