// --------------------------------------------------------------------------- // - Lexical.cpp - // - afnix engine - lexical name 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 "Engsid.hxx" #include "Vector.hpp" #include "Lexical.hpp" #include "Nameset.hpp" #include "Integer.hpp" #include "Runnable.hpp" #include "QuarkZone.hpp" #include "Exception.hpp" namespace afnix { // ------------------------------------------------------------------------- // - private section - // ------------------------------------------------------------------------- // the nil quark static const long QUARK_NIL = String::intern ("nil"); // this procedure returns a new lexical object for deserialization static Serial* mksob (void) { return new Lexical; } // register this lexical serial id static const t_byte SERIAL_ID = Serial::setsid (SERIAL_LEXL_ID, mksob); // ------------------------------------------------------------------------- // - public section - // ------------------------------------------------------------------------- // return true if the character is a valid lexical one bool Lexical::valid (const t_quad c) { if ((c >= 'a') && (c <= 'z')) return true; if ((c >= 'A') && (c <= 'Z')) return true; if ((c >= '0') && (c <= '9')) return true; if (c == '.') return true; if (c == '+') return true; if (c == '-') return true; if (c == '*') return true; if (c == '/') return true; if (c == '!') return true; if (c == '=') return true; if (c == '.') return true; if (c == '>') return true; if (c == '<') return true; if (c == '?') return true; return false; } // return true if the name is valid lexical one bool Lexical::valid (const String& name) { long len = name.length (); if (len == 0) return false; for (long i = 0; i < len; i++) if (Lexical::valid (name[i]) == false) return false; return true; } // ------------------------------------------------------------------------- // - class section - // ------------------------------------------------------------------------- // create a default lexical Lexical::Lexical (void) { d_lnum = 0; d_quark = 0; } // create a lexical with a name Lexical::Lexical (const String& name) { if (Lexical::valid (name) == false) throw Exception ("syntax-error","invalid lexical name", name); d_name = name; d_quark = name.toquark (); d_lnum = 0; } // create a lexical with a name and a line number Lexical::Lexical (const String& name, const long lnum) { if (Lexical::valid (name) == false) throw Exception ("syntax-error","invalid lexical name", name); d_name = name; d_quark = name.toquark (); d_lnum = lnum; } // copy constructor for this lexical Lexical::Lexical (const Lexical& that) { that.rdlock (); d_name = that.d_name; d_quark = that.d_quark; d_lnum = that.d_lnum; that.unlock (); } // return the class name String Lexical::repr (void) const { return "Lexical"; } // return a clone of this lexical Object* Lexical::clone (void) const { return new Lexical (*this); } // return a literal representation of this lexical String Lexical::toliteral (void) const { rdlock (); String result = d_name; unlock (); return result; } // return a string representation of this lexical String Lexical::tostring (void) const { rdlock (); String result = d_name; unlock (); return result; } // return the lexical serial code t_byte Lexical::serialid (void) const { return SERIAL_LEXL_ID; } // serialize this lexical void Lexical::wrstream (Output& os) const { rdlock (); Integer lnum (d_lnum); d_name.wrstream (os); lnum.wrstream (os); unlock (); } // deserialize this lexical void Lexical::rdstream (Input& is) { wrlock (); String sval; Integer ival; sval.rdstream (is); ival.rdstream (is); d_name = sval; d_lnum = ival.tointeger (); d_quark = sval.toquark (); unlock (); } // return the lexical line number long Lexical::getlnum (void) const { rdlock (); long result = d_lnum; unlock (); return result; } // return the lexical quark long Lexical::toquark (void) const { rdlock (); long result = d_quark; unlock (); return result; } // return true if the lexical is the nil quark bool Lexical::isnil (void) const { rdlock (); bool result = (d_quark == QUARK_NIL); unlock (); return result; } // ------------------------------------------------------------------------- // - object section - // ------------------------------------------------------------------------- // the quark zone static const long QUARK_ZONE_LENGTH = 1; static QuarkZone zone (QUARK_ZONE_LENGTH); // the lexical quarks static const long QUARK_MAP = zone.intern ("map"); // create a new object in a generic way Object* Lexical::mknew (Vector* argv) { // get the number of arguments long argc = (argv == nilp) ? 0 : argv->length (); // check for 0 argument if (argc == 0) return new Lexical; // check for 1 argument if (argc == 1) { String name = argv->getstring (0); return new Lexical (name); } // illegal arguments throw Exception ("argument-error", "too many arguments with lexical"); } // return true if the given quark is defined bool Lexical::isquark (const long quark, const bool hflg) const { rdlock (); if (zone.exists (quark) == true) { unlock (); return true; } bool result = hflg ? Literal::isquark (quark, hflg) : false; unlock (); return result; } // set this lexical name as a const symbol Object* Lexical::cdef (Runnable* robj, Nameset* nset, Object* object) { wrlock (); try { Object* result = nset->cdef (robj, nset, d_quark, object); robj->post (result); unlock (); return result; } catch (...) { unlock (); throw; } } // set this lexical name with an object Object* Lexical::vdef (Runnable* robj, Nameset* nset, Object* object) { wrlock (); try { Object* result = nset->vdef (robj, nset, d_quark, object); robj->post (result); unlock (); return result; } catch (...) { unlock (); throw; } } // evaluate this lexical in the current environment Object* Lexical::eval (Runnable* robj, Nameset* nset) { rdlock (); try { Object* result = nset->eval (robj,nset,d_quark); robj->post (result); unlock (); return result; } catch (...) { unlock (); throw; } } // apply this lexical with a set of arguments and a quark Object* Lexical::apply (Runnable* robj, Nameset* nset, const long quark, Vector* argv) { // get the number of arguments long argc = (argv == nilp) ? 0 : argv->length (); // dispatch 0 argument if (argc == 0) { if (quark == QUARK_MAP) { Object* result = (nset == nilp) ? nilp : nset->find (d_quark); robj->post (result); return result; } } // call the literal method return Literal::apply (robj, nset, quark, argv); } }