end of work from old arch
This commit is contained in:
parent
9db341eac5
commit
31b14705ba
1 changed files with 220 additions and 101 deletions
313
src/main.cpp
313
src/main.cpp
|
|
@ -29,7 +29,7 @@ struct Env {
|
|||
std::unordered_map<std::string, size_t> userdef;
|
||||
};
|
||||
|
||||
struct Symbol : Data{
|
||||
struct Symbol : Data {
|
||||
std::string data;
|
||||
std::string Get() {
|
||||
return data;
|
||||
|
|
@ -63,10 +63,27 @@ struct Lambda : Data {
|
|||
Cell f;
|
||||
};
|
||||
|
||||
enum class locs { EVAL_START, EVAL_OP_FIN, EVAL_TOP_ARG, APPLY };
|
||||
|
||||
struct Registers {
|
||||
std::variant<size_t, Data *, Cell> Exp;
|
||||
size_t args_front;
|
||||
size_t args_current;
|
||||
size_t args_left;
|
||||
|
||||
// general registers
|
||||
std::variant<size_t, Data *, Cell> A;
|
||||
std::variant<size_t, Data *, Cell> B;
|
||||
std::variant<size_t, Data *, Cell> C;
|
||||
std::variant<size_t, Data *, Cell> D;
|
||||
|
||||
bool argflag = false;
|
||||
|
||||
std::variant<size_t, Data *, Cell> op;
|
||||
|
||||
locs RP;
|
||||
|
||||
std::variant<size_t, Data *, Cell> R;
|
||||
Env E;
|
||||
};
|
||||
|
||||
|
|
@ -84,46 +101,149 @@ struct Machine {
|
|||
reg.E.builtin.insert("+");
|
||||
reg.E.builtin.insert("-");
|
||||
reg.E.builtin.insert("lambda");
|
||||
reg.E.builtin.insert("set");
|
||||
reg.E.builtin.insert("block");
|
||||
reg.E.builtin.insert("print");
|
||||
}
|
||||
|
||||
size_t Apply(Data * d, size_t cdr) {
|
||||
if (Symbol * fname = dynamic_cast<Symbol*>(d)) {
|
||||
if (reg.E.builtin.contains(fname->data)) {
|
||||
return ApplyBuiltin(fname->data, cdr);
|
||||
} else { //defined symbol.
|
||||
return 0; //TODO
|
||||
}
|
||||
void EvalLoop() {
|
||||
while (true) {
|
||||
switch (reg.RP) {
|
||||
case locs::EVAL_START: { // Expects data* in D;
|
||||
Data *d = std::get<Data *>(reg.D);
|
||||
if (SelfEval *h = dynamic_cast<SelfEval *>(d)) {
|
||||
if(stack.empty()) {
|
||||
reg.R = h;
|
||||
return;
|
||||
}
|
||||
reg = stack.back();
|
||||
stack.pop_back();
|
||||
reg.R = h;
|
||||
|
||||
} else if (Lambda * f = dynamic_cast<Lambda*>(d)) {
|
||||
reg.A = f->args;
|
||||
reg.A = ((Fork *) (std::get<Cell>(reg.A)).d)->data;
|
||||
// return h;
|
||||
} else if (Symbol *h = dynamic_cast<Symbol *>(d)) {
|
||||
if (reg.E.builtin.contains(h->data)) {
|
||||
if(stack.empty()) {
|
||||
reg.R = h;
|
||||
return;
|
||||
}
|
||||
reg = stack.back();
|
||||
stack.pop_back();
|
||||
reg.R = h;
|
||||
} else {
|
||||
if(stack.empty()) {
|
||||
reg.R = mem[reg.E.userdef[h->data]].d;
|
||||
return;
|
||||
}
|
||||
reg = stack.back();
|
||||
stack.pop_back();
|
||||
reg.R = mem[reg.E.userdef[h->data]].d;
|
||||
}
|
||||
} else if (Fork *h = dynamic_cast<Fork *>(d)) {
|
||||
reg.Exp = h;
|
||||
reg.D = mem[h->data].d; // pass car into eval
|
||||
reg.RP = locs::EVAL_OP_FIN;
|
||||
reg.argflag = false;
|
||||
stack.push_back(reg);
|
||||
reg.RP = locs::EVAL_START; // start eval of car;
|
||||
} else {
|
||||
throw("err no eval type");
|
||||
}
|
||||
|
||||
reg.B = cdr;
|
||||
auto tmp = reg.E;
|
||||
//reg.E = f->env;
|
||||
reg.E.userdef.merge(f->env.userdef);
|
||||
while (std::get<size_t>(reg.A) != 0) {
|
||||
reg.E.userdef[ ((Symbol *) mem[std::get<size_t>(reg.A)].d )->data] = std::get<size_t>(reg.B);
|
||||
reg.A = mem[std::get<size_t>(reg.A)].cdr;
|
||||
reg.B = mem[std::get<size_t>(reg.B)].cdr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case locs::EVAL_OP_FIN: {
|
||||
reg.op = reg.R; // save op
|
||||
if (Symbol * c = dynamic_cast<Symbol*>(std::get<Data*>(reg.op))) {
|
||||
if(c->data == "lambda") {
|
||||
reg.args_left = 0;
|
||||
reg.args_current = 0;
|
||||
reg.args_front = mem[((Fork *)std::get<Data *>(reg.Exp))->data].cdr;
|
||||
reg.RP = locs::EVAL_TOP_ARG;
|
||||
reg.argflag=false;
|
||||
break;
|
||||
|
||||
auto ret = Eval(f->f.d);
|
||||
reg.E = tmp;
|
||||
return newCell(ret);
|
||||
}
|
||||
}
|
||||
reg.args_left = mem[((Fork *)std::get<Data *>(reg.Exp))->data].cdr;
|
||||
reg.args_current = 0;
|
||||
reg.args_front = 0;
|
||||
reg.RP = locs::EVAL_TOP_ARG;
|
||||
reg.argflag = false;
|
||||
break;
|
||||
}
|
||||
case locs::EVAL_TOP_ARG: {
|
||||
if (reg.argflag) {
|
||||
if (reg.args_front == 0) {
|
||||
reg.args_front = newCell();
|
||||
reg.args_current = reg.args_front;
|
||||
} else {
|
||||
auto temp = newCell();
|
||||
mem[reg.args_current].cdr = temp;
|
||||
reg.args_current = temp;
|
||||
}
|
||||
mem[reg.args_current].d = std::get<Data*>(reg.R);
|
||||
}
|
||||
if (reg.args_left != 0) {
|
||||
reg.argflag = true;
|
||||
stack.push_back(reg);
|
||||
reg.D = mem[reg.args_left].d;
|
||||
reg.args_left = mem[reg.args_left].cdr;
|
||||
stack.back().args_left = reg.args_left;
|
||||
reg.RP = locs::EVAL_START;
|
||||
} else {
|
||||
reg.RP = locs::APPLY; // all args ready
|
||||
}
|
||||
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case locs::APPLY: {
|
||||
Data *d = std::get<Data *>(reg.op);
|
||||
if (Symbol *fname = dynamic_cast<Symbol *>(d)) {
|
||||
if (reg.E.builtin.contains(fname->data)) {
|
||||
auto temp = ApplyBuiltin(fname->data, reg.args_front);
|
||||
if(stack.empty()) {
|
||||
reg.R = mem[temp].d; //special case for term;
|
||||
return;
|
||||
}
|
||||
reg = stack.back();
|
||||
stack.pop_back();
|
||||
reg.R = mem[temp].d;
|
||||
break;
|
||||
} else {
|
||||
throw "err2";
|
||||
}
|
||||
} else if (Lambda *f = dynamic_cast<Lambda *>(d)) {
|
||||
reg.A = f->args;
|
||||
reg.A = ((Fork *)(std::get<Cell>(reg.A)).d)->data;
|
||||
|
||||
reg.B = reg.args_front;
|
||||
// reg.E = f->env;
|
||||
reg.E.userdef = f->env.userdef;
|
||||
while (std::get<size_t>(reg.A) != 0) {
|
||||
reg.E.userdef[((Symbol *)mem[std::get<size_t>(reg.A)].d)->data] =
|
||||
std::get<size_t>(reg.B);
|
||||
reg.A = mem[std::get<size_t>(reg.A)].cdr;
|
||||
reg.B = mem[std::get<size_t>(reg.B)].cdr;
|
||||
}
|
||||
|
||||
reg.D = f->f.d;
|
||||
//reg.E.userdef.merge(f->env.userdef);
|
||||
reg.RP = locs::EVAL_START;
|
||||
break;
|
||||
} else {
|
||||
throw "err";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t ApplyBuiltin(std::string fname, size_t cdr) {
|
||||
if (fname == "+") {
|
||||
int base = 0;
|
||||
while (cdr != 0) {
|
||||
Number *a = dynamic_cast<Number *>(mem[cdr].d);
|
||||
if (!a) throw "Non Number applied to +";
|
||||
base += a->data;
|
||||
cdr = mem[cdr].cdr;
|
||||
}
|
||||
|
|
@ -131,8 +251,20 @@ struct Machine {
|
|||
n->data = base;
|
||||
return newCell(n);
|
||||
|
||||
} else if (fname == "*") {
|
||||
int base = 1;
|
||||
while (cdr != 0) {
|
||||
Number *a = dynamic_cast<Number *>(mem[cdr].d);
|
||||
if (!a) throw "Non Number applied to +";
|
||||
base *= a->data;
|
||||
cdr = mem[cdr].cdr;
|
||||
}
|
||||
Number *n = new Number;
|
||||
n->data = base;
|
||||
return newCell(n);
|
||||
} else if (fname == "-") {
|
||||
Number *s = dynamic_cast<Number *>(mem[cdr].d);
|
||||
if (!s) throw "Non Number applied to -";
|
||||
int base = s->data;
|
||||
|
||||
cdr = mem[cdr].cdr;
|
||||
|
|
@ -143,6 +275,7 @@ struct Machine {
|
|||
} else {
|
||||
while (cdr != 0) {
|
||||
Number *a = dynamic_cast<Number *>(mem[cdr].d);
|
||||
if (!a) throw "Non Number applied to -";
|
||||
base -= a->data;
|
||||
cdr = mem[cdr].cdr;
|
||||
}
|
||||
|
|
@ -151,23 +284,39 @@ struct Machine {
|
|||
return newCell(n);
|
||||
}
|
||||
} else if (fname == "lambda") {
|
||||
Fork * args = dynamic_cast<Fork*>(mem[cdr].d);
|
||||
Fork * f = dynamic_cast<Fork*>(mem[mem[cdr].cdr].d);
|
||||
Fork *args = dynamic_cast<Fork *>(mem[cdr].d);
|
||||
Fork *f = dynamic_cast<Fork *>(mem[mem[cdr].cdr].d);
|
||||
|
||||
Lambda * l = new Lambda;
|
||||
l->env = reg.E;
|
||||
l->args = mem[cdr]; //mem[args->data];
|
||||
l->f = mem[mem[cdr].cdr]; //mem[f->data];
|
||||
//std::cout <<"got lambd" << std::endl;
|
||||
return newCell(l);
|
||||
Lambda *l = new Lambda;
|
||||
l->env = reg.E;
|
||||
l->args = mem[cdr]; // mem[args->data];
|
||||
l->f = mem[mem[cdr].cdr]; // mem[f->data];
|
||||
// std::cout <<"got lambd" << std::endl;
|
||||
return newCell(l);
|
||||
} else if (fname == "block") {
|
||||
Data * out = NULL;
|
||||
while (cdr != 0) {
|
||||
out = (mem[cdr].d);
|
||||
cdr = mem[cdr].cdr;
|
||||
}
|
||||
return newCell(out);
|
||||
|
||||
} else if (fname == "print") {
|
||||
if (Number * n = dynamic_cast<Number*>(mem[cdr].d)) {
|
||||
std::cout << n->data << std::endl;
|
||||
} else if (String * s = dynamic_cast<String*>(mem[cdr].d)) {
|
||||
std::cout << s->data << std::endl;
|
||||
} else {
|
||||
throw "invalid print";
|
||||
}
|
||||
return cdr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t newCell() {
|
||||
if (freepos >= maxCells) {
|
||||
exit(1);
|
||||
throw "OOM";
|
||||
}
|
||||
auto nc = freepos;
|
||||
freepos += 1;
|
||||
|
|
@ -180,58 +329,6 @@ struct Machine {
|
|||
return t;
|
||||
}
|
||||
|
||||
Data *Eval(Data *d) {
|
||||
// std::cout << "Eval top" << std::endl;
|
||||
if (SelfEval *h = dynamic_cast<SelfEval *>(d)) {
|
||||
return h;
|
||||
} else if (Symbol *h = dynamic_cast<Symbol*>(d)) {
|
||||
if (reg.E.builtin.contains(h->data)) return h;
|
||||
return mem[reg.E.userdef[h->data]].d;
|
||||
} else if (Fork *h = dynamic_cast<Fork *>(d)) {
|
||||
// std::cout << "Eval callllled" << std::endl;
|
||||
// Symbol *car = dynamic_cast<Symbol *>(mem[h->data].d);
|
||||
//new car:
|
||||
auto car = mem[h->data].d;
|
||||
|
||||
// if (!car) {
|
||||
// throw(100);
|
||||
// }
|
||||
size_t front = 0;
|
||||
size_t current = 0;
|
||||
size_t firstargleft = mem[h->data].cdr;
|
||||
|
||||
// std::cout << "Farg " << firstargleft << std::endl;
|
||||
|
||||
while (firstargleft != 0) {
|
||||
if (auto c = dynamic_cast<Symbol*>(car)) {
|
||||
if(c->data == "lambda") {
|
||||
front = mem[h->data].cdr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (front == 0) {
|
||||
front = newCell();
|
||||
current = front;
|
||||
} else {
|
||||
auto temp = newCell();
|
||||
mem[current].cdr = temp;
|
||||
current = temp;
|
||||
}
|
||||
|
||||
// std::cout << "here" << std::endl;
|
||||
mem[current].d = Eval(mem[firstargleft].d);
|
||||
|
||||
// std::cout << "there" << std::endl;
|
||||
firstargleft = mem[firstargleft].cdr;
|
||||
}
|
||||
|
||||
return mem[Apply(Eval(car), front)].d;
|
||||
} else {
|
||||
throw("err");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ListPrint(Cell c) {
|
||||
while (true) {
|
||||
|
|
@ -312,7 +409,7 @@ struct Machine {
|
|||
size_t current = 0;
|
||||
|
||||
char ch;
|
||||
while (in.get(ch)) {
|
||||
while (in.get(ch) && ch != '\n') {
|
||||
if (!std::isspace(ch)) {
|
||||
if (ch == '(') {
|
||||
auto temp = newCell();
|
||||
|
|
@ -347,19 +444,41 @@ struct Machine {
|
|||
};
|
||||
|
||||
int main() {
|
||||
auto m = Machine(1000);
|
||||
auto m = Machine(10000);
|
||||
|
||||
auto exp = m.read_expr(std::cin);
|
||||
|
||||
m.ListPrint(m.mem[exp]);
|
||||
std::cout << std::endl;
|
||||
|
||||
Cell c;
|
||||
c.d = m.Eval(m.mem[exp].d);
|
||||
// c.d = m.Eval(m.mem[exp].d);
|
||||
Registers r;
|
||||
|
||||
|
||||
while (true) {
|
||||
|
||||
m.stack = std::vector<Registers>();
|
||||
auto exp = m.read_expr(std::cin);
|
||||
r.D = m.mem[exp].d;
|
||||
m.reg = r;
|
||||
m.reg.RP = locs::EVAL_START;
|
||||
m.reg.E.builtin.insert("+");
|
||||
m.reg.E.builtin.insert("*");
|
||||
m.reg.E.builtin.insert("-");
|
||||
m.reg.E.builtin.insert("lambda");
|
||||
m.reg.E.builtin.insert("block");
|
||||
m.reg.E.builtin.insert("print");
|
||||
|
||||
//m.ListPrint(m.mem[exp]);
|
||||
std::cout << std::endl;
|
||||
try {
|
||||
m.EvalLoop();
|
||||
} catch (const char * err) {
|
||||
std::cout << err << std::endl;
|
||||
}
|
||||
std::cout << "out of loop" << std::endl;
|
||||
|
||||
c.d = std::get<Data *>(m.reg.R);
|
||||
m.ListPrint(c);
|
||||
std::cout << std::endl;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue