#include "types.h"
#include "model.h"
#include "exc.h"
#include "consts.h"
#include "gc.h"
#include <cmath>
#include <cstdlib>
#include <sstream>
#include <iomanip>
const double EPS = 1e-16;
const int PREC = 16;
extern EmptyList *empty_list;
extern UnspecObj *unspec_obj;
Pair::Pair(EvalObj *_car, EvalObj *_cdr) : EvalObj(CLS_PAIR_OBJ),
car(_car), cdr(_cdr), next(NULL) {
gc.attach(car);
gc.attach(cdr);
}
Pair::~Pair() {
gc.expose(car);
gc.expose(cdr);
}
ReprCons *Pair::get_repr_cons() {
return new PairReprCons(this, this);
}
ParseBracket::ParseBracket(unsigned char _btype) :
FrameObj(CLS_SIM_OBJ | CLS_PAR_BRA), btype(_btype) {}
UnspecObj::UnspecObj() : EvalObj(CLS_SIM_OBJ) {}
ReprCons *UnspecObj::get_repr_cons() {
return new ReprStr("#<Unspecified>");
}
SymObj::SymObj(const string &str) :
EvalObj(CLS_SIM_OBJ | CLS_SYM_OBJ), val(str) {}
ReprCons *SymObj::get_repr_cons() {
return new ReprStr(val);
}
OptObj::OptObj() : EvalObj(CLS_SIM_OBJ | CLS_OPT_OBJ) {}
ProcObj::ProcObj(Pair *_body, Environment *_envt, EvalObj *_params) :
OptObj(), body(_body), params(_params), envt(_envt) {
gc.attach(body);
gc.attach(params);
gc.attach(envt);
}
ProcObj::~ProcObj() {
gc.expose(body);
gc.expose(params);
gc.expose(envt);
}
Pair *ProcObj::call(Pair *_args, Environment * &genvt,
Continuation * &cont, FrameObj ** &top_ptr) {
// Create a new continuation
// static_cast see `call` invocation in eval.cpp
Pair *ret_addr = static_cast<RetAddr*>(*top_ptr)->addr;
Continuation *_cont = new Continuation(genvt, ret_addr, cont, body);
// Create local env and recall the closure
Environment *_envt = new Environment(envt);
// static_cast<SymObj*> because the params is already checked
EvalObj *ppar, *nptr;
Pair *args = _args;
for (ppar = params;
ppar->is_pair_obj();
ppar = TO_PAIR(ppar)->cdr)
{
if ((nptr = args->cdr) != empty_list)
args = TO_PAIR(nptr);
else break;
_envt->add_binding(static_cast<SymObj*>(TO_PAIR(ppar)->car), args->car);
}
if (ppar->is_sym_obj())
_envt->add_binding(static_cast<SymObj*>(ppar), args->cdr); // (... . var_n)
else if (args->cdr != empty_list || ppar != empty_list)
throw TokenError("", RUN_ERR_WRONG_NUM_OF_ARGS);
gc.expose(genvt);
genvt = _envt;
gc.attach(genvt);
gc.expose(cont);
cont = _cont;
gc.attach(cont);
delete *top_ptr; // release ret addr
*top_ptr++ = new RetAddr(NULL); // Mark the entrance of a cont
gc.expose(_args);
return body; // Move pc to the proc entry point
}
ReprCons *ProcObj::get_repr_cons() {
return new ReprStr("#<Procedure>");
}
SpecialOptObj::SpecialOptObj(string _name) : OptObj(), name(_name) {}
ReprCons *SpecialOptObj::get_repr_cons() {
return new ReprStr("#<Built-in Opt: " + name + ">");
}
BoolObj::BoolObj(bool _val) : EvalObj(CLS_SIM_OBJ | CLS_BOOL_OBJ), val(_val) {}
bool BoolObj::is_true() { return val; }
ReprCons *BoolObj::get_repr_cons() {
return new ReprStr(val ? "#t" : "#f");
}
BoolObj *BoolObj::from_string(string repr) {
if (repr.length() != 2 || repr[0]