// --------------------------------------------------------------------------- // - Interp.hpp - // - afnix engine - interpreter class definition - // --------------------------------------------------------------------------- // - 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 - // --------------------------------------------------------------------------- #ifndef AFNIX_INTERP_HPP #define AFNIX_INTERP_HPP #ifndef AFNIX_STACK_HPP #include "Stack.hpp" #endif #ifndef AFNIX_LOADER_HPP #include "Loader.hpp" #endif #ifndef AFNIX_OPTIONS_HPP #include "Options.hpp" #endif #ifndef AFNIX_TERMINAL_HPP #include "Terminal.hpp" #endif #ifndef AFNIX_SUPERSET_HPP #include "Superset.hpp" #endif #ifndef AFNIX_RESOLVER_HPP #include "Resolver.hpp" #endif #ifndef AFNIX_RUNNABLE_HPP #include "Runnable.hpp" #endif namespace afnix { /// The Interp class is the main afnix interpreter engine. The interpreter /// operates on three streams, the standard input, the standard output and /// the standard error stream. By default, the interpreter install a /// terminal object, unless the three streams are specified at construction. /// The interpreter holds a series of registers. For each basic types, /// like integer, real, character and boolean, the interpreter has 256 /// local thread registers. The operations associated with the registers /// are type dependant. For integer and real, these are mostly arithmetic /// operations. For boolean, these are logical operations. The interpreter /// has a top level (or global) nameset. The global nameset is shared /// between all interpreters and is referenced as '...'. On top of this, /// the interpreter provides a 'compile' method which takes a form and /// generates a new one. The sole purpose of the compile method is to /// perform static checking and generate a new form ready for execution. /// @author amaury darsch class Interp : public Runnable { public: /// @return an interpreter option object static Options* getopts (void); private: /// the standard input stream mutable Input* p_is; /// the standard output stream mutable Output* p_os; /// the standard error stream mutable Output* p_es; /// the assert flag bool d_assert; /// the cloned interpreter flag bool d_cloned; /// the posted object Object* p_posted; /// the super global nameset Superset* p_gset; /// the execution stack Stack* p_stk; /// the vector arguments Vector* p_argv; /// the runnable form Object* p_rform; /// the library loader Loader* p_shld; protected: /// the default terminal Terminal* p_term; /// the path resolver Resolver* p_rslv; /// the encoding mode String d_emod; /// the next flag bool d_next; public: /// create a default interpreter Interp (void); /// create a new interpreter with or without a terminal /// @param tflg the terminal flag Interp (const bool tflg); /// create a new interpreter /// @param is the standard input stream /// @param os the standard output stream /// @param es the standard error stream Interp (Input* is, Output* os, Output* es); /// copy constructor for this interpreter /// @param that the interpreter to copy Interp (const Interp& that); /// destroy this interpreter ~Interp (void); /// @return the class name String repr (void) const; /// make this interpreter a shared object void mksho (void); /// post an object in this interpreter void post (Object* object); /// @return a clone of this interpreter Object* clone (void); /// clone this interpreter and set the runnable form /// @param form the runnable form to set Interp* dup (Object* form) const; /// duplicate this interpreter by seeting the terminal /// @param term the teminal stream to set Interp* dup (Terminal* term) const; /// duplicate this interpreter by updating the streams /// @param is the input stream to update /// @param os the output stream to update /// @param es the error stream to update Interp* dup (Input* is, Output* os, Output* es) const; /// evaluate the runnable form Object* run (void); /// evaluate a form in a thread by cloning this interpreter /// @param form the form to evaluate Object* launch (Object* form); /// evaluate a form in a daemon thread by cloning this interpreter /// @param form the form to evaluate Object* daemon (Object* form); /// @return the interpreter input stream Input* getis (void) const; /// @return the interpreter output stream Output* getos (void) const; /// @return the interpreter error stream Output* getes (void) const; /// set the primary prompt /// @param value the prompt to set void setpp (const String& value); /// set the secondary prompt /// @param value the prompt to set void setsp (const String& value); /// @return the primary prompt String getpp (void) const; /// @return the secondary prompt String getsp (void) const; /// set the interpreter encoding mode /// @param emod the encoding mode void setemod (const String& emod); /// @return the interpreter stack Stack* getstk (void) const; /// @return the interpreter global set Nameset* getgset (void) const; /// create a new reserved name in the global nameset /// @param name the reserved name /// @param object the object to bind void mkrsv (const String& name, Object* object); /// create a child nameset in the superset /// @param name the nameset name to create Nameset* mknset (const String& name); /// set the interpreter arguments /// @param args the arguments to set void setargs (const Strvec& args); /// @return the interpreter arguments Strvec getargs (void) const; /// add a path to the resolver /// @param path the path to add void addpath (const String& path); /// set the resolver with a list of path /// @param path the path to set void setpath (const Strvec& path); /// set the assert flag /// @param flag the flag to set void setasrt (const bool flag); /// @return the assert flag bool getasrt (void) const; /// @return the interpreter loader Loader* getld (void) const; /// register a library by name and handle /// @param name the library name to register /// @param hand the library handle void reglib (const String& name, void* hand); /// open a new dynamic library by name /// @param name the library name /// @param argv the vector arguments Object* library (const String& name, Vector* argv); /// set the next flag /// @param flag the flag to set void setnext (const bool flag); /// @return the next flag bool getnext (void) const; /// break the runnable in a nameset with an object /// @param nset the nameset to loop /// @param object the object to break on bool bpt (Nameset* nset, Object* object); /// run the read-eval loop on the standard streams /// @return false if something bad happen bool loop (void); /// loop in the context of a nameset and an input stream /// @param nset the nameset context /// @param is the input stream to use bool loop (Nameset* nset, Input* is); /// run the read-eval loop with a file /// @param fname the file name to read /// @return false if something bad happen bool loop (const String& fname); /// run the read-eval loop with a file /// @param fname the file name to read void load (const String& fname); /// compile from an input stream to an output stream /// @param the file to compile /// @param os the output stream to write void compile (const String& name, Output& os); private: // make the assignment operator private Interp& operator = (const Interp&); public: /// @return true if the given quark is defined bool isquark (const long quark, const bool hflg) const; /// evaluate an object in this object /// @param object the object to evaluate Object* eval (Object* object); /// evaluate an object method by quark /// @param robj the current runnable /// @param nset the current nameset /// @param quark the quark to evaluate Object* eval (Runnable* robj, Nameset* nset, const long quark); /// apply this object with a set of arguments and a quark /// @param robj the current runnable /// @param nset the current nameset /// @param quark the quark to apply these arguments /// @param argv the arguments to apply Object* apply (Runnable* robj, Nameset* nset, const long quark, Vector* argv); }; } #endif