#include "types.h"
#include "model.h"
#include "exc.h"
#include "consts.h"
#include <cmath>
#include <cstdlib>
#include <sstream>
#include <iomanip>
const double EPS = 1e-16;
const int PREC = 16;
EmptyList *empty_list = new EmptyList();
Pair::Pair(EvalObj *_car, EvalObj *_cdr) :
EvalObj(CLS_PAIR_OBJ), car(_car), cdr(_cdr),
next(NULL) {}
ReprCons *Pair::get_repr_cons() {
return new PairReprCons(this, this);
}
RetAddr::RetAddr(Pair *_addr) : FrameObj(CLS_RET_ADDR), addr(_addr) {}
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) {}
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;
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);
genvt = _envt;
cont = _cont;
*top_ptr++ = new RetAddr(NULL); // Mark the entrance of a cont
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] != '#')
return NULL;
if (repr[1] == 't')
return new BoolObj(true);
else if (repr[1] == 'f')
return new BoolObj(false);
return NULL;
}
NumObj::NumObj(NumLvl _level, bool _exactness) :
EvalObj(CLS_SIM_OBJ | CLS_NUM_OBJ), exactness(_exactness), level(_level) {}
bool NumObj::is_exact() { return exactness; }
StrObj::StrObj(string _str) : EvalObj(CLS_SIM_OBJ | CLS_STR_OBJ), str(_str) {}
ReprCons *StrObj::get_repr_cons() {
return new ReprStr(str);
}
CharObj::CharObj(char _ch) : EvalObj(CLS_SIM_OBJ | CLS_CHAR_OBJ), ch(_ch)