diff options
author | Teddy <[email protected]> | 2013-08-04 09:40:43 +0800 |
---|---|---|
committer | Teddy <[email protected]> | 2013-08-04 09:40:43 +0800 |
commit | 9e834528d38a89eb4075b09b35fb7b6e7636740d (patch) | |
tree | 5826c2142c69b7c96515262fb4d3e9e6b0ed819c | |
parent | c66dc142d240ec2e2ae78201d9614de76535be38 (diff) |
added more docs
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | builtin.cpp | 17 | ||||
-rw-r--r-- | builtin.h | 10 | ||||
-rw-r--r-- | eval.cpp | 2 | ||||
-rw-r--r-- | eval.h | 9 | ||||
-rw-r--r-- | model.cpp | 25 | ||||
-rw-r--r-- | model.h | 100 | ||||
-rw-r--r-- | parser.h | 18 |
8 files changed, 153 insertions, 32 deletions
@@ -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 @@ -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(); @@ -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(); } @@ -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 @@ -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) @@ -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 @@ -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); }; |