aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTeddy <ted.sybil@gmail.com>2013-08-03 23:09:59 +0800
committerTeddy <ted.sybil@gmail.com>2013-08-03 23:09:59 +0800
commitc66dc142d240ec2e2ae78201d9614de76535be38 (patch)
treec9df286951328d7a477415946e8000beef6843ad
parente462669c3c3cc04ea29420e14dbb589899d201ec (diff)
C++ version now works!
-rw-r--r--Makefile7
-rw-r--r--TODO.rst3
-rw-r--r--builtin.cpp100
-rw-r--r--builtin.h30
-rw-r--r--eval.cpp91
-rw-r--r--eval.h14
-rw-r--r--main.cpp12
-rw-r--r--model.cpp63
-rw-r--r--model.h26
-rw-r--r--parser.cpp2
-rwxr-xr-xprototype/sketch.py2
11 files changed, 270 insertions, 80 deletions
diff --git a/Makefile b/Makefile
index 847cf3e..596f45f 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
-main: parser.o builtin.o model.o main.o
- g++ -o main $^
+main: main.o parser.o builtin.o model.o eval.o
+ g++ -o main $^ -g
.cpp.o:
g++ $< -c -g -DDEBUG
@@ -7,3 +7,6 @@ main: parser.o builtin.o model.o main.o
clean:
rm -f *.o
rm -f main
+
+db:
+ gdb main
diff --git a/TODO.rst b/TODO.rst
new file mode 100644
index 0000000..99dccee
--- /dev/null
+++ b/TODO.rst
@@ -0,0 +1,3 @@
+- Better judgement of continuation exit
+- Better inherit relationship between Cons and EvalObj
+- Replace many `dynamic_cast` with `static_cast`
diff --git a/builtin.cpp b/builtin.cpp
index 876c75d..13659f2 100644
--- a/builtin.cpp
+++ b/builtin.cpp
@@ -1,4 +1,5 @@
#include "builtin.h"
+#include <cstdio>
#include <sstream>
using std::stringstream;
@@ -42,12 +43,12 @@ void SpecialOptIf::prepare(Cons *pc) {
pc->cdr->cdr->skip = true;
}
-void SpecialOptIf::pre_call(ArgList *arg_list, Cons *pc,
+void SpecialOptIf::pre_call(ArgList *args, Cons *pc,
Environment *envt) {
pc = dynamic_cast<Cons*>(pc->car);
// Condition evaluated and the decision is made
state = 1;
- if (arg_list->cdr->car->is_true())
+ if (args->cdr->car->is_true())
{
pc = pc->cdr;
pc->skip = true;
@@ -65,23 +66,23 @@ void SpecialOptIf::pre_call(ArgList *arg_list, Cons *pc,
}
}
-EvalObj *SpecialOptIf::post_call(ArgList *arg_list, Cons *pc,
+EvalObj *SpecialOptIf::post_call(ArgList *args, Cons *pc,
Environment *envt) {
// Value already evaluated, so just return it
- return arg_list->cdr->car;
+ return args->cdr->car;
}
-Cons *SpecialOptIf::call(ArgList *arg_list, Environment * &envt,
+Cons *SpecialOptIf::call(ArgList *args, Environment * &envt,
Continuation * &cont, FrameObj ** &top_ptr) {
- Cons *ret_addr = dynamic_cast<Cons*>(*top_ptr);
+ Cons *ret_addr = dynamic_cast<RetAddr*>(*top_ptr)->addr;
if (state)
{
- *top_ptr = post_call(arg_list, ret_addr, envt);
+ *top_ptr++ = post_call(args, ret_addr, envt);
return ret_addr->next; // Move to the next instruction
}
else
{
- pre_call(arg_list, ret_addr, envt);
- top_ptr++;
+ pre_call(args, ret_addr, envt);
+ top_ptr += 2;
// Undo pop and invoke again
return dynamic_cast<Cons*>(ret_addr->car)->next;
}
@@ -94,8 +95,8 @@ string SpecialOptIf::_debug_repr() { return ext_repr(); }
SpecialOptLambda::SpecialOptLambda() : SpecialOptObj() {}
#define FILL_MARKS(pc, flag) \
- for (pc = pc->cdr; pc != empty_list; pc = pc->cdr) \
- pc->skip = flag
+ for (Cons *ptr = pc->cdr; ptr != empty_list; ptr = ptr->cdr) \
+ ptr->skip = flag
void SpecialOptLambda::prepare(Cons *pc) {
//TODO check number of arguments
@@ -103,9 +104,9 @@ void SpecialOptLambda::prepare(Cons *pc) {
FILL_MARKS(pc, true);
}
-Cons *SpecialOptLambda::call(ArgList *arg_list, Environment * &envt,
+Cons *SpecialOptLambda::call(ArgList *args, Environment * &envt,
Continuation * &cont, FrameObj ** &top_ptr) {
- Cons *ret_addr = dynamic_cast<Cons*>(*top_ptr);
+ Cons *ret_addr = dynamic_cast<RetAddr*>(*top_ptr)->addr;
Cons *pc = dynamic_cast<Cons*>(ret_addr->car);
SymbolList *para_list = dynamic_cast<SymbolList*>(pc->cdr->car); // parameter list
// Clear the flag to avoid side-effects (e.g. proc calling)
@@ -114,9 +115,9 @@ Cons *SpecialOptLambda::call(ArgList *arg_list, Environment * &envt,
// store a list of expressions inside <body>
ASTList *body = pc->cdr->cdr; // Truncate the expression list
for (Cons *ptr = body; ptr != empty_list; ptr = ptr->cdr)
- ptr->next = NULL; // Make each expression a orphan
+ ptr->next = NULL; // Make each expression an orphan
- *top_ptr = new ProcObj(body, envt, para_list);
+ *top_ptr++ = new ProcObj(body, envt, para_list);
return ret_addr->next; // Move to the next instruction
}
@@ -134,9 +135,9 @@ void SpecialOptDefine::prepare(Cons *pc) {
} // Procedure definition
else FILL_MARKS(pc, true); // Skip all parts
}
-Cons *SpecialOptDefine::call(ArgList *arg_list, Environment * &envt,
+Cons *SpecialOptDefine::call(ArgList *args, Environment * &envt,
Continuation * &cont, FrameObj ** &top_ptr) {
- Cons *ret_addr = dynamic_cast<Cons*>(*top_ptr);
+ Cons *ret_addr = dynamic_cast<RetAddr*>(*top_ptr)->addr;
Cons *pc = dynamic_cast<Cons*>(ret_addr->car);
EvalObj *obj;
SymObj *id;
@@ -144,7 +145,7 @@ Cons *SpecialOptDefine::call(ArgList *arg_list, Environment * &envt,
if (pc->cdr->car->is_simple_obj())
{
id = dynamic_cast<SymObj*>(pc->cdr->car);
- obj = arg_list->cdr->car;
+ obj = args->cdr->car;
}
else
{
@@ -160,7 +161,7 @@ Cons *SpecialOptDefine::call(ArgList *arg_list, Environment * &envt,
obj = new ProcObj(body, envt, para_list);
}
envt->add_binding(id, obj);
- *top_ptr = obj;
+ *top_ptr++ = new UnspecObj();
return ret_addr->next;
}
string SpecialOptDefine::ext_repr() { return string("#<Builtin Macro: define>"); }
@@ -174,18 +175,71 @@ void SpecialOptSet::prepare(Cons *pc) {
pc->cdr->cdr->skip = false;
}
-Cons *SpecialOptSet::call(ArgList *arg_list, Environment * &envt,
+Cons *SpecialOptSet::call(ArgList *args, Environment * &envt,
Continuation * &cont, FrameObj ** &top_ptr) {
- Cons *ret_addr = dynamic_cast<Cons*>(*top_ptr);
+ Cons *ret_addr = dynamic_cast<RetAddr*>(*top_ptr)->addr;
Cons *pc = dynamic_cast<Cons*>(ret_addr->car);
SymObj *id = dynamic_cast<SymObj*>(pc->cdr->car);
if (envt->has_obj(id))
- envt->add_binding(id, arg_list->cdr->car);
- *top_ptr = new UnspecObj();
+ envt->add_binding(id, args->cdr->car);
+ *top_ptr++ = new UnspecObj();
return ret_addr->next;
}
+SpecialOptSet::SpecialOptSet() {}
string SpecialOptSet::ext_repr() { return string("#<Builtin Macro: set!>"); }
#ifdef DEBUG
string SpecialOptSet::_debug_repr() { return ext_repr(); }
#endif
+
+EvalObj *builtin_plus(ArgList *args) {
+ // TODO: type conversion and proper arithmetic
+ int res = 0;
+ for (Cons *ptr = args; ptr != empty_list; ptr = ptr->cdr)
+ res += dynamic_cast<IntObj*>(ptr->car)->val;
+ return new IntObj(res);
+}
+
+EvalObj *builtin_minus(ArgList *args) {
+ // TODO: type conversion and proper arithmetic
+ int res = dynamic_cast<IntObj*>(args->car)->val;
+ for (Cons *ptr = args->cdr; ptr != empty_list; ptr = ptr->cdr)
+ res -= dynamic_cast<IntObj*>(ptr->car)->val;
+ return new IntObj(res);
+}
+
+EvalObj *builtin_times(ArgList *args) {
+ // TODO: type conversion and proper arithmetic
+ int res = 1;
+ for (Cons *ptr = args; ptr != empty_list; ptr = ptr->cdr)
+ res *= dynamic_cast<IntObj*>(ptr->car)->val;
+ return new IntObj(res);
+}
+
+EvalObj *builtin_div(ArgList *args) {
+ // TODO: type conversion and proper arithmetic
+ int res = dynamic_cast<IntObj*>(args->car)->val;
+ for (Cons *ptr = args->cdr; ptr != empty_list; ptr = ptr->cdr)
+ res /= dynamic_cast<IntObj*>(ptr->car)->val;
+ return new IntObj(res);
+}
+
+EvalObj *builtin_lt(ArgList *args) {
+ return new BoolObj(dynamic_cast<IntObj*>(args->car)->val <
+ dynamic_cast<IntObj*>(args->cdr->car)->val);
+}
+
+EvalObj *builtin_gt(ArgList *args) {
+ return new BoolObj(dynamic_cast<IntObj*>(args->car)->val >
+ dynamic_cast<IntObj*>(args->cdr->car)->val);
+}
+
+EvalObj *builtin_arithmetic_eq(ArgList *args) {
+ return new BoolObj(dynamic_cast<IntObj*>(args->car)->val ==
+ dynamic_cast<IntObj*>(args->cdr->car)->val);
+}
+
+EvalObj *builtin_display(ArgList *args) {
+ printf("%s\n", args->car->ext_repr().c_str());
+ return new UnspecObj();
+}
diff --git a/builtin.h b/builtin.h
index a4468ae..8b448cf 100644
--- a/builtin.h
+++ b/builtin.h
@@ -10,9 +10,8 @@ using std::string;
* Booleans
*/
class BoolObj: public EvalObj {
- private:
- bool val; /**< true for #t, false for #f */
public:
+ bool val; /**< true for #t, false for #f */
BoolObj(bool);
bool is_true(); /**< Override EvalObj `is_true()` */
#ifdef DEBUG
@@ -26,9 +25,8 @@ class BoolObj: public EvalObj {
* Will be removed in the future
*/
class IntObj: public NumberObj {
- private:
- int val;
public:
+ int val;
IntObj(int);
#ifdef DEBUG
string _debug_repr();
@@ -40,9 +38,8 @@ class IntObj: public NumberObj {
* Floating point numbers
*/
class FloatObj: public NumberObj {
- private:
- double val;
public:
+ double val;
FloatObj(double);
#ifdef DEBUG
string _debug_repr();
@@ -61,18 +58,18 @@ class SpecialOptIf: public SpecialOptObj {
* The evaluator will call this after the <condition> exp is evaluated.
* And this function tells the evaluator which of <consequence> and
* <alternative> should be evaluted. */
- void pre_call(ArgList *arg_list, Cons *pc,
+ void pre_call(ArgList *args, Cons *pc,
Environment *envt);
/** The system will call this again after the desired result is
* evaluated, so just return it to let the evaluator know the it's the
* answer.
*/
- EvalObj *post_call(ArgList *arg_list, Cons *pc,
+ EvalObj *post_call(ArgList *args, Cons *pc,
Environment *envt);
public:
SpecialOptIf();
void prepare(Cons *pc);
- Cons *call(ArgList *arg_list, Environment * &envt,
+ Cons *call(ArgList *args, Environment * &envt,
Continuation * &cont, FrameObj ** &top_ptr);
#ifdef DEBUG
string _debug_repr();
@@ -87,7 +84,7 @@ class SpecialOptLambda: public SpecialOptObj {
public:
SpecialOptLambda();
void prepare(Cons *pc);
- Cons *call(ArgList *arg_list, Environment * &envt,
+ Cons *call(ArgList *args, Environment * &envt,
Continuation * &cont, FrameObj ** &top_ptr);
#ifdef DEBUG
@@ -103,7 +100,7 @@ class SpecialOptDefine: public SpecialOptObj {
public:
SpecialOptDefine();
void prepare(Cons *pc);
- Cons *call(ArgList *arg_list, Environment * &envt,
+ Cons *call(ArgList *args, Environment * &envt,
Continuation * &cont, FrameObj ** &top_ptr);
#ifdef DEBUG
string _debug_repr();
@@ -118,7 +115,7 @@ class SpecialOptSet: public SpecialOptObj {
public:
SpecialOptSet();
void prepare(Cons *pc);
- Cons *call(ArgList *arg_list, Environment * &envt,
+ Cons *call(ArgList *args, Environment * &envt,
Continuation * &cont, FrameObj ** &top_ptr);
#ifdef DEBUG
string _debug_repr();
@@ -126,4 +123,13 @@ class SpecialOptSet: public SpecialOptObj {
string ext_repr();
};
+EvalObj *builtin_plus(ArgList *);
+EvalObj *builtin_minus(ArgList *);
+EvalObj *builtin_times(ArgList *);
+EvalObj *builtin_div(ArgList *);
+EvalObj *builtin_lt(ArgList *);
+EvalObj *builtin_gt(ArgList *);
+EvalObj *builtin_arithmetic_eq(ArgList *);
+EvalObj *builtin_display(ArgList *);
+
#endif
diff --git a/eval.cpp b/eval.cpp
new file mode 100644
index 0000000..279f8c4
--- /dev/null
+++ b/eval.cpp
@@ -0,0 +1,91 @@
+#include "eval.h"
+#include "builtin.h"
+#include <cstdio>
+
+extern Cons *empty_list;
+const int EVAL_STACK_SIZE = 65536;
+FrameObj *eval_stack[EVAL_STACK_SIZE];
+
+void Evaluator::add_builtin_routines() {
+
+#define ADD_ENTRY(name, rout) \
+ envt->add_binding(new SymObj(name), rout)
+
+ ADD_ENTRY("+", new BuiltinProcObj(builtin_plus, "+"));
+ ADD_ENTRY("-", new BuiltinProcObj(builtin_minus, "-"));
+ ADD_ENTRY("*", new BuiltinProcObj(builtin_times, "*"));
+ ADD_ENTRY("/", new BuiltinProcObj(builtin_div, "/"));
+ ADD_ENTRY(">", new BuiltinProcObj(builtin_gt, ">"));
+ ADD_ENTRY("<", new BuiltinProcObj(builtin_lt, "<"));
+ ADD_ENTRY("=", new BuiltinProcObj(builtin_arithmetic_eq, "="));
+ ADD_ENTRY("display", new BuiltinProcObj(builtin_display, "display"));
+ ADD_ENTRY("if", new SpecialOptIf());
+ ADD_ENTRY("lambda", new SpecialOptLambda());
+ ADD_ENTRY("define", new SpecialOptDefine());
+ ADD_ENTRY("set", new SpecialOptSet());
+}
+
+Evaluator::Evaluator() {
+ envt = new Environment(); // Top-level Environment
+ add_builtin_routines();
+}
+
+void push(Cons * &pc, FrameObj ** &top_ptr, Environment *envt) {
+ if (pc->car->is_simple_obj()) // Not an opt invocation
+ {
+ *top_ptr = envt->get_obj(pc->car); // Objectify the symbol
+ dynamic_cast<EvalObj*>(*top_ptr)->prepare(pc);
+ top_ptr++;
+ pc = pc->next; // Move to the next instruction
+ }
+ else // Operational Invocation
+ {
+ *top_ptr++ = new RetAddr(pc); // Push the return address
+ pc = dynamic_cast<Cons*>(pc->car); // Go deeper to enter the call
+ }
+}
+
+void stack_print(FrameObj **top_ptr) {
+ for (FrameObj **ptr = eval_stack; ptr != top_ptr; ptr++)
+ printf("%s\n", (*ptr)->_debug_repr().c_str());
+ puts("");
+}
+
+EvalObj *Evaluator::run_expr(Cons *prog) {
+ FrameObj **top_ptr = eval_stack;
+ Cons *pc = prog;
+ Continuation *cont = NULL;
+ // envt is this->envt
+ push(pc, top_ptr, envt);
+
+ while((*eval_stack)->is_ret_addr())
+ {
+ for (; pc && pc->skip; pc = pc->next);
+ if (pc)
+ push(pc, top_ptr, envt);
+ else
+ {
+ Cons *args = empty_list;
+ while (!(*(--top_ptr))->is_ret_addr())
+ args = new Cons(dynamic_cast<EvalObj*>(*top_ptr), args);
+ RetAddr *ret_addr = dynamic_cast<RetAddr*>(*top_ptr);
+ if (!ret_addr->addr)
+ {
+ Cons *nexp = cont->proc_body->cdr;
+ cont->proc_body = nexp;
+ if (nexp == empty_list)
+ {
+ *top_ptr = args->car;
+ envt = cont->envt;
+ pc = cont->pc->next;
+ cont = cont->prev_cont;
+ }
+ else pc = nexp;
+ top_ptr++;
+ }
+ else
+ pc = dynamic_cast<OptObj*>(args->car)->call(args, envt, cont, top_ptr);
+ }
+ }
+ return dynamic_cast<EvalObj*>(*(eval_stack));
+}
diff --git a/eval.h b/eval.h
new file mode 100644
index 0000000..0ec08f3
--- /dev/null
+++ b/eval.h
@@ -0,0 +1,14 @@
+#ifndef EVAL_H
+#define EVAL_H
+#include "model.h"
+
+class Evaluator {
+ private:
+ Environment *envt;
+ void add_builtin_routines();
+ public:
+ Evaluator();
+ EvalObj *run_expr(Cons *prog);
+};
+
+#endif
diff --git a/main.cpp b/main.cpp
index 6a86fe5..f32dac3 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,6 +1,7 @@
#include "model.h"
#include "builtin.h"
#include "parser.h"
+#include "eval.h"
#include <cstdio>
#ifdef DEBUG
@@ -16,6 +17,13 @@ void tree_print(Cons *ptr) {
int main() {
Tokenizor *tk = new Tokenizor();
ASTGenerator *ast = new ASTGenerator();
- Cons *tree = ast->absorb(tk);
- tree_print(tree);
+ Evaluator *eval = new Evaluator();
+
+ while (1)
+ {
+ Cons *tree = ast->absorb(tk);
+ if (!tree) break;
+ //tree_print(tree);
+ printf("%s\n", eval->run_expr(tree)->ext_repr().c_str());
+ }
}
diff --git a/model.cpp b/model.cpp
index 6f49871..951c9e0 100644
--- a/model.cpp
+++ b/model.cpp
@@ -1,6 +1,7 @@
#include <cstdio>
#include "model.h"
+FrameObj::FrameObj(ClassType _ftype) : ftype(_ftype) {}
EmptyList *empty_list = new EmptyList();
EmptyList::EmptyList() : Cons(NULL, NULL) {}
@@ -13,7 +14,7 @@ bool FrameObj::is_ret_addr() {
return ftype == CLS_RET_ADDR;
}
-EvalObj::EvalObj() : FrameObj() { ftype = CLS_EVAL_OBJ; }
+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;
@@ -28,24 +29,24 @@ bool EvalObj::is_true() {
}
Cons::Cons(EvalObj *_car, Cons *_cdr) :
- EvalObj(), car(_car), cdr(_cdr), skip(false), next(cdr) {}
+ EvalObj(CLS_CONS_OBJ), car(_car), cdr(_cdr), skip(false),
+ 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\n%s\n",
+ printf("mem: 0x%llX (0x%llX . 0x%llX) | 0x%llX\n%s\n",
(unsigned long long)this,
(unsigned long long)car,
(unsigned long long)cdr,
+ (unsigned long long)next,
("car: " + car -> ext_repr() + "\n" + \
"cdr: " + cdr -> ext_repr() + "\n").c_str());
}
#endif
-RetAddr::RetAddr(Cons *_addr) : FrameObj(), addr(_addr) {
- ftype = CLS_RET_ADDR;
-}
+RetAddr::RetAddr(Cons *_addr) : FrameObj(CLS_RET_ADDR), addr(_addr) {}
#ifdef DEBUG
string RetAddr::_debug_repr() { return string("#<Return Address>"); }
#endif
@@ -69,22 +70,22 @@ ProcObj::ProcObj(ASTList *_body,
SymbolList *_para_list) :
OptObj(), body(_body), envt(_envt), para_list(_para_list) {}
-Cons *ProcObj::call(ArgList *arg_list, Environment * &envt,
+Cons *ProcObj::call(ArgList *args, Environment * &_envt,
Continuation * &cont, FrameObj ** &top_ptr) {
// Create a new continuation
- Cons *ret_addr = dynamic_cast<Cons*>(*top_ptr);
- Continuation *ncont = new Continuation(envt, ret_addr, cont, body);
+ Cons *ret_addr = dynamic_cast<RetAddr*>(*top_ptr)->addr;
+ Continuation *ncont = new Continuation(_envt, ret_addr, cont, body);
cont = ncont; // Add to the cont chain
- envt = new Environment(envt); // Create local env and recall the closure
+ _envt = new Environment(envt); // Create local env and recall the closure
// TODO: Compare the arguments to the parameters
- for (Cons *ptr = arg_list->cdr, *ppar = para_list;
- ptr != empty_list; ptr = ptr->cdr)
- envt->add_binding(dynamic_cast<SymObj*>(ppar->car), ptr->car);
- *top_ptr = new RetAddr(NULL); // Mark the entrance of a cont
+ for (Cons *ptr = args->cdr, *ppar = para_list;
+ ptr != empty_list; ptr = ptr->cdr, ppar = ppar->cdr)
+ _envt->add_binding(dynamic_cast<SymObj*>(ppar->car), ptr->car);
+ *top_ptr++ = new RetAddr(NULL); // Mark the entrance of a cont
return body; // Move pc to the proc entry point
}
-string ProcObj::ext_repr() { return string("#<Procedure"); }
+string ProcObj::ext_repr() { return string("#<Procedure>"); }
#ifdef DEBUG
string ProcObj::_debug_repr() { return ext_repr(); }
#endif
@@ -93,41 +94,47 @@ SpecialOptObj::SpecialOptObj() : OptObj() {}
NumberObj::NumberObj() : EvalObj() {}
-BuiltinProcObj::BuiltinProcObj(BuiltinProc f, const string &_name) :
+BuiltinProcObj::BuiltinProcObj(BuiltinProc f, string _name) :
OptObj(), handler(f), name(_name) {}
-Cons *BuiltinProcObj::call(ArgList *arg_list, Environment * &envt,
+Cons *BuiltinProcObj::call(ArgList *args, Environment * &envt,
Continuation * &cont, FrameObj ** &top_ptr) {
- Cons *ret_addr = dynamic_cast<Cons*>(*top_ptr);
- *top_ptr = handler(arg_list->cdr);
+ Cons *ret_addr = dynamic_cast<RetAddr*>(*top_ptr)->addr;
+ *top_ptr++ = handler(args->cdr);
return ret_addr->next; // Move to the next instruction
}
+string BuiltinProcObj::ext_repr() {
+ return "#<Builtin Procedure: " + name + ">";
+}
+string BuiltinProcObj::_debug_repr() { return ext_repr(); }
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(SymObj *sym_obj) {
+EvalObj *Environment::get_obj(EvalObj *obj) {
+ SymObj *sym_obj = dynamic_cast<SymObj*>(obj);
+ if (!sym_obj) return obj; // Not a SymObj
+
string name(sym_obj->val);
- for (Environment *ptr = this; ptr; ptr = prev_envt)
+ for (Environment *ptr = this; ptr; ptr = ptr->prev_envt)
{
- bool has_key = binding.count(name);
- if (has_key) return binding[name];
+ bool has_key = ptr->binding.count(name);
+ if (has_key) return ptr->binding[name];
}
//TODO: exc key not found
}
bool Environment::has_obj(SymObj *sym_obj) {
string name(sym_obj->val);
- for (Environment *ptr = this; ptr; ptr = prev_envt)
- if (binding.count(name))
+ for (Environment *ptr = this; ptr; ptr = ptr->prev_envt)
+ if (ptr->binding.count(name))
return true;
return false;
}
Continuation::Continuation(Environment *_envt, Cons *_pc,
Continuation *_prev_cont,
- ASTList *_proc_body,
- unsigned int _body_cnt) :
+ ASTList *_proc_body) :
envt(_envt), pc(_pc), prev_cont(_prev_cont),
- proc_body(_proc_body), body_cnt(_body_cnt) {}
+ proc_body(_proc_body) {}
diff --git a/model.h b/model.h
index b8cd873..6105119 100644
--- a/model.h
+++ b/model.h
@@ -23,6 +23,7 @@ class FrameObj {
protected:
ClassType ftype; // avoid the use of dynamic_cast to improve efficiency
public:
+ FrameObj(ClassType);
virtual ~FrameObj() {}
bool is_ret_addr();
#ifdef DEBUG
@@ -36,10 +37,10 @@ class Cons;
* 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();
+ ClassType otype; // avoid the use of dynamic_cast to improve efficiency
+
+ EvalObj(ClassType _otype = CLS_SIM_OBJ);
bool is_simple_obj();
/** External representation of this object */
virtual void prepare(Cons *pc);
@@ -136,13 +137,13 @@ class OptObj: public EvalObj {
OptObj();
/**
* The function is called when an operation is needed.
- * @param arg_list The argument list (the first one is the opt itself)
+ * @param args 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,
+ virtual Cons *call(ArgList *args, Environment * &envt,
Continuation * &cont, FrameObj ** &top_ptr) = 0;
};
@@ -159,7 +160,7 @@ class ProcObj: public OptObj {
Environment *envt;
ProcObj(ASTList *, Environment *, SymbolList *);
- Cons *call(ArgList *arg_list, Environment * &envt,
+ Cons *call(ArgList *args, Environment * &envt,
Continuation * &cont, FrameObj ** &top_ptr);
#ifdef DEBUG
string _debug_repr();
@@ -185,9 +186,13 @@ class BuiltinProcObj: public OptObj {
BuiltinProc handler;
string name;
public:
- BuiltinProcObj(BuiltinProc, const string &);
- Cons *call(ArgList *arg_list, Environment * &envt,
+ BuiltinProcObj(BuiltinProc, string);
+ Cons *call(ArgList *args, Environment * &envt,
Continuation * &cont, FrameObj ** &top_ptr);
+#ifdef DEBUG
+ string _debug_repr();
+#endif
+ string ext_repr();
};
/** @class NumberObj
@@ -211,7 +216,7 @@ class Environment {
public:
Environment(Environment * = NULL);
void add_binding(SymObj *, EvalObj *);
- EvalObj *get_obj(SymObj *);
+ EvalObj *get_obj(EvalObj *);
bool has_obj(SymObj *);
};
@@ -221,10 +226,9 @@ class Continuation {
Environment *envt;
Cons *pc;
ASTList *proc_body;
- unsigned int body_cnt;
Continuation(Environment *, Cons *, Continuation *,
- ASTList *, unsigned int = 0);
+ ASTList *);
};
#endif
diff --git a/parser.cpp b/parser.cpp
index 0143700..e1724c3 100644
--- a/parser.cpp
+++ b/parser.cpp
@@ -79,7 +79,7 @@ Cons *ASTGenerator::absorb(Tokenizor *tk) {
if (top_ptr > parse_stack && *parse_stack)
return new Cons(*(top_ptr - 1), empty_list);
string token;
- tk->get_token(token);
+ if (!tk->get_token(token)) return NULL;
if (token == "(")
*top_ptr++ = NULL; // Make the beginning of a new level
else if (token == ")")
diff --git a/prototype/sketch.py b/prototype/sketch.py
index c51dad0..4fd5be1 100755
--- a/prototype/sketch.py
+++ b/prototype/sketch.py
@@ -535,6 +535,6 @@ while True:
cmd = sys.stdin.readline()
t.feed(cmd)
try:
- print e.run_expr(exp).ext_repr()
+ pdb.run("print e.run_expr(exp).ext_repr()")
except Exception as exc:
print exc