aboutsummaryrefslogblamecommitdiff
path: root/model.h
blob: 42765ba3f981cb9f48578910d8e923d11c5532ff (plain) (tree)

































































































































































































































                                                                                  
#ifndef MODEL_H
#define MODEL_H

#include <string>
#include <list>
#include <map>

using std::list;
using std::string;
using std::map;

typedef unsigned char ClassType;  // that range is enough

static const int CLS_RET_ADDR = 0;
static const int CLS_EVAL_OBJ = 1;
static const int CLS_SIM_OBJ = 0;
static const int CLS_CONS_OBJ = 1;

/** @class FrameObj
 * Objects that can be held in the evaluation stack
 */
class FrameObj {
    protected:
        ClassType ftype;   // avoid the use of dynamic_cast to improve efficiency
    public:
        virtual ~FrameObj() {}
        bool is_ret_addr();
#ifdef DEBUG
        virtual string _debug_repr() = 0;  
#endif
};


class Cons;
/** @class EvalObj
 * Objects that represents a value in evaluation
 */
class EvalObj : public FrameObj {
    private:
        ClassType otype;    // avoid the use of dynamic_cast to improve efficiency
    public:
        EvalObj();
        bool is_simple_obj();
        /** External representation of this object */
        virtual void prepare(Cons *pc);
        virtual string ext_repr() = 0;  
        /**< Always true for all EvalObjs except BoolObj */
        virtual bool is_true();         
};

/** @class Cons
 * Pair construct, which can be used to represent a list, or further
 * more, a syntax tree
 * (car . cdr) in Scheme
 */
class Cons : public EvalObj {
    public:
        EvalObj *car;                   /**< car (as in Scheme) */
        Cons *cdr;                      /**< cdr (as in Scheme) */
        bool skip;                      /**< Wether to skip the current branch */
        Cons* next;                      /**< The next branch in effect         */

        Cons(EvalObj *, Cons *);
#ifdef DEBUG
        void _debug_print();
        string _debug_repr();
#endif
        string ext_repr();
};

/** @class EmptyList
 * The empty list (special situation of a list)
 */
class EmptyList: public Cons {
    public:
        EmptyList();
#ifdef DEBUG
        string _debug_repr();
#endif
        string ext_repr();
};

/** @class RetAddr
 * Tracking the caller's Cons pointer
 */
class RetAddr : public FrameObj {
    public:
        Cons* addr;                      /**< The return address  */

        RetAddr(Cons *);
};


/** @class UnspecObj
 * The "unspecified" value returned by some builtin procedures
 */
class UnspecObj: public EvalObj {
    public:
        UnspecObj();
#ifdef DEBUG
        string _debug_repr();
#endif
        string ext_repr();
};

/** @class SymObj
 * Symbols
 */
class SymObj: public EvalObj {
    public:
        string val;

        SymObj(string);
#ifdef DEBUG
        string _debug_repr();
#endif
        string ext_repr();
};

// Everything is cons
typedef Cons ASTList;
typedef Cons SymbolList;
typedef Cons ArgList;
class Environment;
class Continuation;

/** @class OptObj
 * "Operators" in general sense
 */
class OptObj: public EvalObj {
    public:
        OptObj();
        /**
         * The function is called when an operation is needed.
         * @param arg_list The argument list (the first one is the opt itself)
         * @param envt The current environment (may be modified)
         * @param cont The current continuation (may be modified)
         * @param top_ptr Pointing to the top of the stack (may be modified)
         * @return New value for pc register 
         */
        virtual Cons *call(ArgList *arg_list, Environment * &envt, 
                            Continuation * &cont, FrameObj ** &top_ptr) = 0;
};

/** @class ProcObj
 * User-defined procedures
 */
class ProcObj: public OptObj {
    public:
        /** The procedure body, a list of expressions to be evaluated */
        ASTList *body;        
        /** The arguments, a list of Symbols */
        SymbolList *para_list;
        /** Pointer to the environment */
        Environment *envt;

        ProcObj(ASTList *, Environment *, SymbolList *);
        Cons *call(ArgList *arg_list, Environment * &envt,
                    Continuation * &cont, FrameObj ** &top_ptr);
#ifdef DEBUG
        string _debug_repr();
#endif
        string ext_repr();
};

/** @class SpecialOptObj
 * Special builtin syntax (`if`, `define`, `lambda`, etc.)
 */
class SpecialOptObj: public OptObj {
    public:
        SpecialOptObj();
};

typedef EvalObj* (*BuiltinProc)(ArgList *);
/** @class BuiltinProcObj
 * Wrapping class for builtin procedures (arithmetic operators, etc.)
 */
class BuiltinProcObj: public OptObj {
    private:
        /** The function that tackle the inputs in effect */
        BuiltinProc handler;        
        string name;
    public:
        BuiltinProcObj(BuiltinProc, string);
        Cons *call(ArgList *arg_list, Environment * &envt,
                    Continuation * &cont, FrameObj ** &top_ptr);
};

/** @class NumberObj
 * The top level abstract of numbers
 */

class NumberObj: public EvalObj {
    public:
        NumberObj();
};

typedef map<string, EvalObj*> Str2EvalObj;
/** @class Environment
 * The environment of current evaluation, i.e. the local variable binding 
 */
class Environment {
    private:
        Environment *prev_envt; /**< Pointer to the upper level environment */
        Str2EvalObj binding;    /**< Store all pairs of identifier and its
                                  corresponding obj */
    public:
        Environment(Environment * = NULL);
        void add_binding(SymObj *, EvalObj *);  
        EvalObj *get_obj(SymObj *);
        bool has_obj(SymObj *);
};

class Continuation {
    public:
        Continuation *prev_cont;
        Environment *envt;
        Cons *pc;
        ASTList *proc_body;
        unsigned int body_cnt;

        Continuation(Environment *, Cons *, Continuation *, 
                ASTList *, unsigned int = 0);
};

#endif