aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTeddy <ted.sybil@gmail.com>2013-08-04 09:40:43 +0800
committerTeddy <ted.sybil@gmail.com>2013-08-04 09:40:43 +0800
commit9e834528d38a89eb4075b09b35fb7b6e7636740d (patch)
tree5826c2142c69b7c96515262fb4d3e9e6b0ed819c
parentc66dc142d240ec2e2ae78201d9614de76535be38 (diff)
added more docs
-rw-r--r--Makefile4
-rw-r--r--builtin.cpp17
-rw-r--r--builtin.h10
-rw-r--r--eval.cpp2
-rw-r--r--eval.h9
-rw-r--r--model.cpp25
-rw-r--r--model.h100
-rw-r--r--parser.h18
8 files changed, 153 insertions, 32 deletions
diff --git a/Makefile b/Makefile
index 596f45f..0664a27 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
main: main.o parser.o builtin.o model.o eval.o
- g++ -o main $^ -g
+ g++ -o main $^ -pg
.cpp.o:
- g++ $< -c -g -DDEBUG
+ g++ $< -c -g -pg -DDEBUG
clean:
rm -f *.o
diff --git a/builtin.cpp b/builtin.cpp
index 13659f2..19516bd 100644
--- a/builtin.cpp
+++ b/builtin.cpp
@@ -7,33 +7,41 @@ using std::stringstream;
extern EmptyList *empty_list;
BoolObj::BoolObj(bool _val) : EvalObj(), val(_val) {}
+
bool BoolObj::is_true() { return val; }
+
string BoolObj::ext_repr() { return string(val ? "#t" : "#f"); }
+
#ifdef DEBUG
string BoolObj::_debug_repr() { return ext_repr(); }
#endif
IntObj::IntObj(int _val) : NumberObj(), val(_val) {}
+
string IntObj::ext_repr() {
stringstream ss;
ss << val;
return ss.str();
}
+
#ifdef DEBUG
string IntObj::_debug_repr() { return ext_repr(); }
#endif
FloatObj::FloatObj(double _val) : NumberObj(), val(_val) {}
+
string FloatObj::ext_repr() {
stringstream ss;
ss << val;
return ss.str();
}
+
#ifdef DEBUG
string FloatObj::_debug_repr() { return ext_repr(); }
#endif
SpecialOptIf::SpecialOptIf() : SpecialOptObj() {}
+
void SpecialOptIf::prepare(Cons *pc) {
state = 0; // Prepared
pc = pc->cdr;
@@ -71,6 +79,7 @@ EvalObj *SpecialOptIf::post_call(ArgList *args, Cons *pc,
// Value already evaluated, so just return it
return args->cdr->car;
}
+
Cons *SpecialOptIf::call(ArgList *args, Environment * &envt,
Continuation * &cont, FrameObj ** &top_ptr) {
Cons *ret_addr = dynamic_cast<RetAddr*>(*top_ptr)->addr;
@@ -89,6 +98,7 @@ Cons *SpecialOptIf::call(ArgList *args, Environment * &envt,
}
string SpecialOptIf::ext_repr() { return string("#<Builtin Macro: if>"); }
+
#ifdef DEBUG
string SpecialOptIf::_debug_repr() { return ext_repr(); }
#endif
@@ -122,11 +132,13 @@ Cons *SpecialOptLambda::call(ArgList *args, Environment * &envt,
}
string SpecialOptLambda::ext_repr() { return string("#<Builtin Macro: lambda>"); }
+
#ifdef DEBUG
string SpecialOptLambda::_debug_repr() { return ext_repr(); }
#endif
SpecialOptDefine::SpecialOptDefine() : SpecialOptObj() {}
+
void SpecialOptDefine::prepare(Cons *pc) {
if (pc->cdr->car->is_simple_obj()) // Simple value assignment
{
@@ -135,6 +147,7 @@ void SpecialOptDefine::prepare(Cons *pc) {
} // Procedure definition
else FILL_MARKS(pc, true); // Skip all parts
}
+
Cons *SpecialOptDefine::call(ArgList *args, Environment * &envt,
Continuation * &cont, FrameObj ** &top_ptr) {
Cons *ret_addr = dynamic_cast<RetAddr*>(*top_ptr)->addr;
@@ -164,7 +177,9 @@ Cons *SpecialOptDefine::call(ArgList *args, Environment * &envt,
*top_ptr++ = new UnspecObj();
return ret_addr->next;
}
+
string SpecialOptDefine::ext_repr() { return string("#<Builtin Macro: define>"); }
+
#ifdef DEBUG
string SpecialOptDefine::_debug_repr() { return ext_repr(); }
#endif
@@ -187,7 +202,9 @@ Cons *SpecialOptSet::call(ArgList *args, Environment * &envt,
}
SpecialOptSet::SpecialOptSet() {}
+
string SpecialOptSet::ext_repr() { return string("#<Builtin Macro: set!>"); }
+
#ifdef DEBUG
string SpecialOptSet::_debug_repr() { return ext_repr(); }
#endif
diff --git a/builtin.h b/builtin.h
index 8b448cf..92b2fe0 100644
--- a/builtin.h
+++ b/builtin.h
@@ -11,8 +11,8 @@ using std::string;
*/
class BoolObj: public EvalObj {
public:
- bool val; /**< true for #t, false for #f */
- BoolObj(bool);
+ bool val; /**< true for \#t, false for \#f */
+ BoolObj(bool); /**< Converts a C bool value to a BoolObj*/
bool is_true(); /**< Override EvalObj `is_true()` */
#ifdef DEBUG
string _debug_repr();
@@ -26,7 +26,8 @@ class BoolObj: public EvalObj {
*/
class IntObj: public NumberObj {
public:
- int val;
+ int val; /**< Numeric value */
+ /** Converts a C integer value to a FloatObj */
IntObj(int);
#ifdef DEBUG
string _debug_repr();
@@ -39,7 +40,8 @@ class IntObj: public NumberObj {
*/
class FloatObj: public NumberObj {
public:
- double val;
+ double val; /**< Numeric value */
+ /** Converts a C double value to a FloatObj */
FloatObj(double);
#ifdef DEBUG
string _debug_repr();
diff --git a/eval.cpp b/eval.cpp
index 279f8c4..07ea00e 100644
--- a/eval.cpp
+++ b/eval.cpp
@@ -26,7 +26,7 @@ void Evaluator::add_builtin_routines() {
}
Evaluator::Evaluator() {
- envt = new Environment(); // Top-level Environment
+ envt = new Environment(NULL); // Top-level Environment
add_builtin_routines();
}
diff --git a/eval.h b/eval.h
index 0ec08f3..78ede95 100644
--- a/eval.h
+++ b/eval.h
@@ -2,13 +2,16 @@
#define EVAL_H
#include "model.h"
+/** @class Evaluator
+ * A runtime platform of interpreting
+ */
class Evaluator {
private:
- Environment *envt;
- void add_builtin_routines();
+ Environment *envt; /**< Store the current environment */
+ void add_builtin_routines(); /**< Add builtin routines to the env */
public:
Evaluator();
- EvalObj *run_expr(Cons *prog);
+ EvalObj *run_expr(Cons *prog); /**< Interpret a program */
};
#endif
diff --git a/model.cpp b/model.cpp
index 951c9e0..ee578f2 100644
--- a/model.cpp
+++ b/model.cpp
@@ -2,10 +2,13 @@
#include "model.h"
FrameObj::FrameObj(ClassType _ftype) : ftype(_ftype) {}
+
EmptyList *empty_list = new EmptyList();
EmptyList::EmptyList() : Cons(NULL, NULL) {}
+
string EmptyList::ext_repr() { return string("()"); }
+
#ifdef DEBUG
string EmptyList::_debug_repr() { return ext_repr(); }
#endif
@@ -15,14 +18,19 @@ bool FrameObj::is_ret_addr() {
}
EvalObj::EvalObj(ClassType _otype) : FrameObj(CLS_EVAL_OBJ), otype(_otype) {}
+
void EvalObj::prepare(Cons *pc) {}
+
bool EvalObj::is_simple_obj() {
return otype == CLS_SIM_OBJ;
}
+
+#ifdef DEBUG
void EvalObj::_debug_print() {
printf("mem: 0x%llX\n%s\n\n", (unsigned long long)this,
_debug_repr().c_str());
}
+#endif
bool EvalObj::is_true() {
return true;
@@ -33,8 +41,10 @@ Cons::Cons(EvalObj *_car, Cons *_cdr) :
next(cdr == empty_list ? NULL : cdr) {}
string Cons::ext_repr() { return string("#<Cons>"); }
+
#ifdef DEBUG
string Cons::_debug_repr() { return ext_repr(); }
+
void Cons::_debug_print() {
printf("mem: 0x%llX (0x%llX . 0x%llX) | 0x%llX\n%s\n",
(unsigned long long)this,
@@ -47,18 +57,23 @@ void Cons::_debug_print() {
#endif
RetAddr::RetAddr(Cons *_addr) : FrameObj(CLS_RET_ADDR), addr(_addr) {}
+
#ifdef DEBUG
string RetAddr::_debug_repr() { return string("#<Return Address>"); }
#endif
UnspecObj::UnspecObj() : EvalObj() {}
+
string UnspecObj::ext_repr() { return string("#<Unspecified>"); }
+
#ifdef DEBUG
string UnspecObj::_debug_repr() { return ext_repr(); }
#endif
SymObj::SymObj(const string &str) : EvalObj(), val(str) {}
+
string SymObj::ext_repr() { return "#<Symbol: " + val + ">"; }
+
#ifdef DEBUG
string SymObj::_debug_repr() { return ext_repr(); }
#endif
@@ -86,6 +101,7 @@ Cons *ProcObj::call(ArgList *args, Environment * &_envt,
}
string ProcObj::ext_repr() { return string("#<Procedure>"); }
+
#ifdef DEBUG
string ProcObj::_debug_repr() { return ext_repr(); }
#endif
@@ -104,18 +120,24 @@ Cons *BuiltinProcObj::call(ArgList *args, Environment * &envt,
*top_ptr++ = handler(args->cdr);
return ret_addr->next; // Move to the next instruction
}
+
string BuiltinProcObj::ext_repr() {
return "#<Builtin Procedure: " + name + ">";
}
+
+#ifdef DEBUG
string BuiltinProcObj::_debug_repr() { return ext_repr(); }
+#endif
Environment::Environment(Environment *_prev_envt) : prev_envt(_prev_envt) {}
+
void Environment::add_binding(SymObj *sym_obj, EvalObj *eval_obj) {
binding[sym_obj->val] = eval_obj;
}
+
EvalObj *Environment::get_obj(EvalObj *obj) {
SymObj *sym_obj = dynamic_cast<SymObj*>(obj);
- if (!sym_obj) return obj; // Not a SymObj
+ if (!sym_obj) return obj; // Not a SymObj
string name(sym_obj->val);
for (Environment *ptr = this; ptr; ptr = ptr->prev_envt)
@@ -125,6 +147,7 @@ EvalObj *Environment::get_obj(EvalObj *obj) {
}
//TODO: exc key not found
}
+
bool Environment::has_obj(SymObj *sym_obj) {
string name(sym_obj->val);
for (Environment *ptr = this; ptr; ptr = ptr->prev_envt)
diff --git a/model.h b/model.h
index 6105119..13a5af2 100644
--- a/model.h
+++ b/model.h
@@ -21,10 +21,23 @@ static const int CLS_CONS_OBJ = 1;
*/
class FrameObj {
protected:
- ClassType ftype; // avoid the use of dynamic_cast to improve efficiency
+ /**
+ * Report the type of the FrameObj, which can avoid the use of
+ * dynamic_cast to improve efficiency. See the constructor for detail
+ */
+ ClassType ftype;
public:
- FrameObj(ClassType);
+ /**
+ * Construct an EvalObj
+ * @param ftype the type of the FrameObj (CLS_EVAL_OBJ for an EvalObj,
+ * CLS_RET_ADDR for a return address)
+ */
+ FrameObj(ClassType ftype);
virtual ~FrameObj() {}
+ /**
+ * Tell whether the object is a return address, according to ftype
+ * @return true for yes
+ */
bool is_ret_addr();
#ifdef DEBUG
virtual string _debug_repr() = 0;
@@ -37,15 +50,30 @@ class Cons;
* 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
+ */
+ ClassType otype;
public:
- ClassType otype; // avoid the use of dynamic_cast to improve efficiency
-
- EvalObj(ClassType _otype = CLS_SIM_OBJ);
+ /**
+ * Construct an EvalObj
+ * @param otype the type of the EvalObj (CLS_CONS_OBJ for a
+ * construction, CLS_SIM_OBJ for a simple object), which defaults to
+ * CLS_SIM_OBJ
+ */
+ EvalObj(ClassType otype = CLS_SIM_OBJ);
+ /** Check if the object is a simple object (instead of a call
+ * invocation)
+ * @return true if the object is not a construction (Cons)
+ * */
bool is_simple_obj();
/** External representation of this object */
virtual void prepare(Cons *pc);
+ /** Any EvalObj has its external representation */
virtual string ext_repr() = 0;
- /**< Always true for all EvalObjs except BoolObj */
+ /** Always true for all EvalObjs except BoolObj */
virtual bool is_true();
#ifdef DEBUG
virtual void _debug_print();
@@ -62,9 +90,9 @@ class Cons : public EvalObj {
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* next; /**< The next branch in effect */
- Cons(EvalObj *, Cons *);
+ Cons(EvalObj *car, Cons *cdr); /**< Create a Cons (car . cdr) */
#ifdef DEBUG
void _debug_print();
string _debug_repr();
@@ -90,9 +118,12 @@ class EmptyList: public Cons {
class RetAddr : public FrameObj {
public:
Cons* addr; /**< The return address */
-
- RetAddr(Cons *);
+ /** Constructs a return address object which refers to the node addr in
+ * the AST */
+ RetAddr(Cons *addr);
+#ifdef DEBUG
string _debug_repr();
+#endif
};
@@ -159,7 +190,8 @@ class ProcObj: public OptObj {
/** Pointer to the environment */
Environment *envt;
- ProcObj(ASTList *, Environment *, SymbolList *);
+ /** Conctructs a ProcObj */
+ ProcObj(ASTList *body, Environment *envt, SymbolList *para_list);
Cons *call(ArgList *args, Environment * &envt,
Continuation * &cont, FrameObj ** &top_ptr);
#ifdef DEBUG
@@ -186,7 +218,12 @@ class BuiltinProcObj: public OptObj {
BuiltinProc handler;
string name;
public:
- BuiltinProcObj(BuiltinProc, string);
+ /**
+ * Make a BuiltinProcObj which invokes proc when called
+ * @param proc the actual handler
+ * @param name the name of this built-in procedure
+ */
+ BuiltinProcObj(BuiltinProc proc, string name);
Cons *call(ArgList *args, Environment * &envt,
Continuation * &cont, FrameObj ** &top_ptr);
#ifdef DEBUG
@@ -210,25 +247,46 @@ typedef map<string, EvalObj*> Str2EvalObj;
*/
class Environment {
private:
- Environment *prev_envt; /**< Pointer to the upper level environment */
+ 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(EvalObj *);
+ /** Create an runtime environment
+ * @param prev_envt the outer environment
+ * */
+ Environment(Environment *prev_envt);
+ /** Add a binding entry which binds sym_obj to eval_obj */
+ void add_binding(SymObj *sym_obj, EvalObj *eval_obj);
+ /** Extract the corresponding EvalObj if obj is a SymObj, or just
+ * simply return obj as it is
+ * @param obj the object as request
+ * */
+ EvalObj *get_obj(EvalObj *obj);
+ /** Check if the desired obj exists
+ * @return true for yes
+ */
bool has_obj(SymObj *);
};
+/** @class Continuation
+ * Save the registers and necessary information when a user-defined call is
+ * being made (Behave like a stack frame in C). When the call has accomplished,
+ * the system will restore all the registers according to the continuation.
+ */
class Continuation {
public:
- Continuation *prev_cont;
- Environment *envt;
- Cons *pc;
+ /** Linking the previous continuation on the chain */
+ Continuation *prev_cont;
+ Environment *envt; /**< The saved envt */
+ Cons *pc; /**< The saved pc */
+ /** Pointing to the current expression that is being evaluated.
+ * When its value goes to empty_list, the call is accomplished.
+ */
ASTList *proc_body;
- Continuation(Environment *, Cons *, Continuation *,
- ASTList *);
+ /** Create a continuation */
+ Continuation(Environment *envt, Cons *pc, Continuation *prev_cont,
+ ASTList *proc_body);
};
#endif
diff --git a/parser.h b/parser.h
index 065ed2a..5c427ee 100644
--- a/parser.h
+++ b/parser.h
@@ -9,23 +9,41 @@ using std::string;
const int TOKEN_BUFF_SIZE = 65536;
const int PARSE_STACK_SIZE = 65536;
+/** @class Tokenizor
+ * Break down the input string stream into tokens
+ */
class Tokenizor {
private:
FILE *stream;
char *buff_ptr;
public:
Tokenizor();
+ /** Set the stream to be read from (without setting this, the default
+ * would be stdin) */
void set_stream(FILE *stream);
+ /** Extract the next token
+ * @param ret the extracted token
+ * @return false if nothing can be read further
+ * */
bool get_token(string &ret);
};
+/** @class ASTGenerator
+ * Read the tokens and build up an Abstract Syntax Tree (which is in effect a
+ * Cons)
+ */
class ASTGenerator {
private:
static EvalObj* to_float(const string &);
static EvalObj* to_int(const string &);
+ /** Convert the string to an internal object */
static EvalObj* to_obj(const string &);
public:
ASTGenerator();
+ /** Read tokens from Tokenizor tk, then return a AST
+ * @param tk pointer to a Tokenizor
+ * @return Abstract Syntax Tree
+ */
Cons *absorb(Tokenizor *tk);
};