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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
#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_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))
/** @class FrameObj
* Objects that can be held in the parsing 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 a FrameObj
* @param ftype describes the type of the FrameObj (CLS_EVAL_OBJ for an EvalObj,
* CLS_PAR_BRA for a bracket)
*/
FrameObj(FrameType ftype);
/**
* The destructor
*/
virtual ~FrameObj() {}
/**
* Tell whether the object is a bracket, according to ftype
* @return true for yes
*/
bool is_parse_bracket();
};/*}}}*/
class GCRecord;
class Pair;
class ReprCons;
/** @class EvalObj
* Objects that represents a value in evaluation
*/
class EvalObj : public FrameObj {/*{{{*/
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:
/**
* The pointer to the corresponding record in GC
*/
GCRecord *gc_rec;
/**
* Construct an EvalObj
* @param otype the type of the EvalObj (CLS_PAIR_OBJ for a pair,
* CLS_SIM_OBJ for a simple object), which defaults to CLS_SIM_OBJ, etc.
*/
EvalObj(int otype = CLS_SIM_OBJ);
/**
* The destructor
*/
~EvalObj();
/** Check if the object is a simple object (instead of a call
* invocation)
* @return true if the object is not a pair or an empty list
* */
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 (notice that an empty list does
* not counts as a pair here) */
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();
/** Check if the object is a container */
bool is_container();
/** Get `otype`, used by some routines for efficiency issues */
int get_otype();
/** Dummy function, actually used by OptObj, called before the actual
* invocation */
virtual void prepare(Pair *pc);
/** Any EvalObj has its external representation */
string ext_repr();
/** Always true for all other EvalObjs except BoolObj */
virtual bool is_true();
/** External representation construction, used by `ext_repr()` */
virtual ReprCons *get_repr_cons() = 0;
};/*}}}*/
/** @class ParseBracket
* To indiate a left bracket when parsing, used in the parse_stack
*/
class ParseBracket : public FrameObj {/*{{{*/
public:
/** The type of the bracket (to distingiush '(' and '#(' ) */
unsigned char btype;
/** Construct a ParseBracket object */
ParseBracket(unsigned char btype);
};/*}}}*/
/** @class Container
* Describes the kind of EvalObjs which may cause circular reference issue,
* different from some "direct" objects, such as BoolObj, NumberObj...
*/
class Container: public EvalObj {/*{{{*/
public:
/** true if the object is still in use, its value is set and read temporarily,
* check `gc.cpp` */
bool keep;
/** the counter used when resolving circular references, see `gc.cpp` */
size_t gc_refs;
/** Constructor, does an "or" bit operation on the otype provided by
* its subclasses, i.e. to mark CLS_CONTAINER.
* The mark will not be not enforced if the `override` is
* true. */
Container(int otype = 0, bool override = false);
/**
* Decrease the gc_refs of the objects referenced by this container.
* Used by circular ref resolver to detect the cycle.
*/
virtual void gc_decrement() = 0;
/** Push the objects referenced by this container to the queue via the pointer `tail`. Used in the phase of
* marking `keep`.
*/
virtual void gc_trigger(EvalObj ** &tail) = 0;
};/*}}}*/
#endif
|