aboutsummaryrefslogtreecommitdiff
path: root/model.h
blob: 964d68be4ae80e3475d91cd8ce4c245ca81fa155 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#ifndef MODEL_H
#define MODEL_H

#include <string>
#include <set>

using std::string;

// the range of unsigned char is enough for these types
typedef unsigned char FrameType;
typedef unsigned char NumLvl;

const int CLS_RET_ADDR = 1 << 0;
const int CLS_EVAL_OBJ = 1 << 1;
const int CLS_PAR_BRA = 1 << 2;

const int CLS_SIM_OBJ = 1 << 0;
const int CLS_PAIR_OBJ = 1 << 1;
const int CLS_CONTAINER = 1 << 20;

#define TO_PAIR(ptr) \
    (static_cast<Pair*>(ptr))

#define EXIT_CURRENT_ENVT(lenvt) \
    do { \
        gc.expose(lenvt); \
        lenvt = cont->envt; \
        gc.attach(lenvt); \
    } while (0)
#define EXIT_CURRENT_CONT(cont) \
    do { \
        gc.expose(cont); \
        cont = cont->prev_cont; \
        gc.attach(cont); \
    } while (0)

#define EXIT_CURRENT_EXEC(lenvt, cont) \
    do { \
        EXIT_CURRENT_ENVT(lenvt); \
        EXIT_CURRENT_CONT(cont); \
    } while (0)

/** @class FrameObj
 * Objects that can be held in the evaluation stack
 */
class FrameObj {
    protected:
        /**
         * Report the type of the FrameObj, which can avoid the use of
         * dynamic_cast to improve efficiency. See the constructor for detail
         */
        FrameType ftype;
    public:
        /**
         * Construct an EvalObj
         * @param ftype the type of the FrameObj (CLS_EVAL_OBJ for an EvalObj,
         * CLS_RET_ADDR for a return address)
         */
        FrameObj(FrameType ftype);
        virtual ~FrameObj() {}
        /**
         * Tell whether the object is a bracket, according to ftype
         * @return true for yes
         */
        bool is_parse_bracket();
};


class Pair;
class ReprCons;
/** @class EvalObj
 * Objects that represents a value in evaluation
 */
class EvalObj : public FrameObj {
    private:
        size_t gc_cnt;
    protected:
        /**
         * Report the type of the EvalObj, which can avoid the use of
         * dynamic_cast to improve efficiency. See the constructor for detail
         */
        int otype;
    public:
        /**
         * Construct an EvalObj
         * @param otype the type of the EvalObj (CLS_PAIR_OBJ for a
         * construction, CLS_SIM_OBJ for a simple object), which defaults to
         * CLS_SIM_OBJ
         */
        EvalObj(int otype = CLS_SIM_OBJ);
        ~EvalObj();
        /** Check if the object is a simple object (instead of a call
         * invocation)
         * @return true if the object is not a construction (Pair)
         * */
        bool is_simple_obj();
        /** Check if the object is a symobl */
        bool is_sym_obj();
        /** Check if the object is an operator */
        bool is_opt_obj();
        /** Check if the object is a Pair */
        bool is_pair_obj();
        /** Check if the object is a number */
        bool is_num_obj();
        /** Check if the object is a boolean */
        bool is_bool_obj();
        /** Check if the object is a string */
        bool is_str_obj();
        /** Check if the object is a promise */
        bool is_prom_obj();
        /** Check if the object is a vector */
        bool is_vect_obj();
        bool is_container();
        int get_otype();
        virtual void prepare(Pair *pc);
        /** Any EvalObj has its external representation */
        string ext_repr();
        /** Always true for all EvalObjs except BoolObj */
        virtual bool is_true();
        /** External representation construction */
        virtual ReprCons *get_repr_cons() = 0;
        bool gc_dec();
        void gc_inc();
        size_t gc_get_cnt();
};

typedef std::set<EvalObj*> EvalObjSet;
class Container: public EvalObj {
    public:
    bool keep;
    size_t gc_refs;
    Container(int otype = 0, bool override = false);
    virtual void gc_decrement() = 0;
    virtual void gc_trigger(EvalObj ** &tail, EvalObjSet &visited) = 0;
};

#endif