it lives !!
This commit is contained in:
parent
058405e5eb
commit
f4fccc86d2
2 changed files with 174 additions and 45 deletions
6
Makefile
6
Makefile
|
|
@ -1,9 +1,9 @@
|
||||||
CC = gcc
|
CC = gcc
|
||||||
CXX = g++
|
CXX = g++
|
||||||
|
|
||||||
CPPFLAGS = -std=c++20 -g -Wall -Wextra -Wpedantic #-O3 -ffast-math
|
CPPFLAGS = -std=c++20 -g -Wall -Wextra -Wpedantic -O3 -ffast-math
|
||||||
CFLAGS = -g -Wall -Wextra -Wpedantic #-O3 -ffast-math
|
CFLAGS = -g -Wall -Wextra -Wpedantic -O3 -ffast-math
|
||||||
LDFLAGS = -g -Wall -Wextra -Wpedantic #-O3 -ffast-math
|
LDFLAGS = -g -Wall -Wextra -Wpedantic -O3 -ffast-math
|
||||||
LDLIBS =
|
LDLIBS =
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
211
src/main.cpp
211
src/main.cpp
|
|
@ -28,9 +28,16 @@ struct Cell {
|
||||||
size_t cdr = 0;
|
size_t cdr = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Env {
|
// struct Env {
|
||||||
std::unordered_set<std::string> builtin;
|
// std::unordered_set<std::string> builtin;
|
||||||
std::unordered_map<std::string, size_t> userdef;
|
// std::unordered_map<std::string, size_t> userdef;
|
||||||
|
// };
|
||||||
|
|
||||||
|
|
||||||
|
struct EnvFrame : Data {
|
||||||
|
size_t parent = 0;
|
||||||
|
std::unordered_map<std::string, size_t> bindings;
|
||||||
|
EnvFrame(size_t par) : parent(par) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Symbol : Data {
|
struct Symbol : Data {
|
||||||
|
|
@ -67,7 +74,8 @@ struct Fork : Data {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Lambda : Data {
|
struct Lambda : Data {
|
||||||
Env env;
|
//Env env;
|
||||||
|
size_t env = 0;
|
||||||
size_t args = 0;
|
size_t args = 0;
|
||||||
size_t f = 0;
|
size_t f = 0;
|
||||||
};
|
};
|
||||||
|
|
@ -76,7 +84,7 @@ struct Lambda : Data {
|
||||||
|
|
||||||
enum class locs { EVAL_START, EVAL_OP_FIN, EVAL_TOP_ARG, APPLY };
|
enum class locs { EVAL_START, EVAL_OP_FIN, EVAL_TOP_ARG, APPLY };
|
||||||
|
|
||||||
enum class special_indef_eval {NONE, PROGN, IF_BEGIN, FORCE_RETURN_NEXT_ARG};
|
enum class special_indef_eval {NONE, PROGN, IF_BEGIN, FORCE_RETURN_NEXT_ARG, DEFINE};
|
||||||
|
|
||||||
|
|
||||||
struct Registers {
|
struct Registers {
|
||||||
|
|
@ -98,7 +106,8 @@ struct Registers {
|
||||||
locs RP;
|
locs RP;
|
||||||
|
|
||||||
size_t R = 0;
|
size_t R = 0;
|
||||||
Env E;
|
|
||||||
|
size_t E = 0;
|
||||||
|
|
||||||
special_indef_eval screen = special_indef_eval::NONE;
|
special_indef_eval screen = special_indef_eval::NONE;
|
||||||
|
|
||||||
|
|
@ -138,15 +147,50 @@ struct Machine {
|
||||||
|
|
||||||
Registers reg;
|
Registers reg;
|
||||||
|
|
||||||
|
std::unordered_set<std::string> builtin;
|
||||||
|
|
||||||
|
size_t global_env = 0;
|
||||||
|
|
||||||
bool invalidgc = false;
|
bool invalidgc = false;
|
||||||
|
|
||||||
Machine(size_t max) : mem(max), mem_empty(max) {
|
Machine(size_t max) : mem(max), mem_empty(max) {
|
||||||
maxCells = max;
|
maxCells = max;
|
||||||
reg.E.builtin.insert("+");
|
|
||||||
reg.E.builtin.insert("-");
|
builtin.insert("+");
|
||||||
reg.E.builtin.insert("lambda");
|
builtin.insert("*");
|
||||||
reg.E.builtin.insert("progn");
|
builtin.insert("-");
|
||||||
reg.E.builtin.insert("print");
|
builtin.insert("lambda");
|
||||||
|
builtin.insert("progn");
|
||||||
|
builtin.insert("print");
|
||||||
|
builtin.insert("<");
|
||||||
|
builtin.insert("if");
|
||||||
|
builtin.insert("quote");
|
||||||
|
builtin.insert("define");
|
||||||
|
builtin.insert("defun-unq");
|
||||||
|
builtin.insert("defun");
|
||||||
|
|
||||||
|
//alloc global environment node
|
||||||
|
global_env = newCell(new EnvFrame(0));
|
||||||
|
|
||||||
|
// reg.E.builtin.insert("+");
|
||||||
|
// reg.E.builtin.insert("-");
|
||||||
|
// reg.E.builtin.insert("lambda");
|
||||||
|
// reg.E.builtin.insert("progn");
|
||||||
|
// reg.E.builtin.insert("print");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t EnvLookup(size_t startAddr, std::string name) {
|
||||||
|
|
||||||
|
EnvFrame * env = static_cast<EnvFrame*>(mem[startAddr].d);
|
||||||
|
while(true) {
|
||||||
|
if (env == 0) return 0;
|
||||||
|
if (env->bindings.contains(name)) {
|
||||||
|
return env->bindings[name];
|
||||||
|
}
|
||||||
|
env = static_cast<EnvFrame*>(mem[env->parent].d);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EvalLoop() {
|
void EvalLoop() {
|
||||||
|
|
@ -173,7 +217,7 @@ struct Machine {
|
||||||
|
|
||||||
// return h;
|
// return h;
|
||||||
} else if (Symbol *h = dynamic_cast<Symbol *>(d)) {
|
} else if (Symbol *h = dynamic_cast<Symbol *>(d)) {
|
||||||
if (reg.E.builtin.contains(h->data)) {
|
if (builtin.contains(h->data)) {
|
||||||
if(stack.empty()) {
|
if(stack.empty()) {
|
||||||
reg.R = reg.C; //return addressof
|
reg.R = reg.C; //return addressof
|
||||||
return;
|
return;
|
||||||
|
|
@ -186,13 +230,15 @@ struct Machine {
|
||||||
reg.R = loc; //return addressof
|
reg.R = loc; //return addressof
|
||||||
} else {
|
} else {
|
||||||
if(stack.empty()) {
|
if(stack.empty()) {
|
||||||
reg.R = reg.E.userdef[h->data];
|
//reg.R = reg.E.userdef[h->data];
|
||||||
|
reg.R = EnvLookup(reg.E, h->data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
reg = stack.back();
|
reg = stack.back();
|
||||||
stack.pop_back();
|
stack.pop_back();
|
||||||
reg.R = reg.E.userdef[h->data];
|
//reg.R = reg.E.userdef[h->data];
|
||||||
|
reg.R = EnvLookup(reg.E, h->data);
|
||||||
}
|
}
|
||||||
} else if (Fork *h = dynamic_cast<Fork *>(d)) {
|
} else if (Fork *h = dynamic_cast<Fork *>(d)) {
|
||||||
reg.Exp = reg.C; //set exp to addressof
|
reg.Exp = reg.C; //set exp to addressof
|
||||||
|
|
@ -225,6 +271,68 @@ struct Machine {
|
||||||
} else if (c->data == "if") {
|
} else if (c->data == "if") {
|
||||||
reg.screen = special_indef_eval::IF_BEGIN;
|
reg.screen = special_indef_eval::IF_BEGIN;
|
||||||
}
|
}
|
||||||
|
// if(c->data == "define") {
|
||||||
|
// reg.screen = special_indef_eval::DEFINE;
|
||||||
|
|
||||||
|
// }
|
||||||
|
if(c->data == "quote") {
|
||||||
|
reg.args_left = 0;
|
||||||
|
reg.args_current = 0;
|
||||||
|
reg.args_front = mem[((Fork *) mem[reg.Exp].d)->data].cdr;
|
||||||
|
reg.RP = locs::EVAL_TOP_ARG;
|
||||||
|
reg.argflag = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->data == "defun") {
|
||||||
|
reg.args_front = mem[((Fork *) mem[reg.Exp].d)->data].cdr;
|
||||||
|
reg.A = newCell(); // quote fork
|
||||||
|
reg.B = newCell(); // quote
|
||||||
|
reg.C = newCell(); // to store symbol name
|
||||||
|
reg.D = newCell(); // almsot root
|
||||||
|
|
||||||
|
mem[reg.D].d = new Symbol;
|
||||||
|
static_cast<Symbol*>(mem[reg.D].d)->data = "defun-unq";
|
||||||
|
|
||||||
|
// reg.C = newCell(); // lambda
|
||||||
|
mem[reg.B].d = new Symbol;
|
||||||
|
static_cast<Symbol*>(mem[reg.B].d)->data = "quote";
|
||||||
|
|
||||||
|
mem[reg.C].d = new Symbol;
|
||||||
|
static_cast<Symbol*>(mem[reg.C].d)->data = static_cast<Symbol*>(mem[reg.args_front].d)->data;
|
||||||
|
|
||||||
|
|
||||||
|
mem[reg.B].cdr = reg.C;
|
||||||
|
mem[reg.A].d = new Fork;
|
||||||
|
static_cast<Fork*>(mem[reg.A].d)->data = reg.B;
|
||||||
|
|
||||||
|
mem[reg.D].cdr = reg.A;
|
||||||
|
|
||||||
|
|
||||||
|
reg.A = newCell(); // lambda fork
|
||||||
|
reg.B = newCell(); // lambda symbol
|
||||||
|
|
||||||
|
mem[mem[reg.D].cdr].cdr = reg.A;
|
||||||
|
|
||||||
|
|
||||||
|
mem[reg.A].d = new Fork;
|
||||||
|
static_cast<Fork*>(mem[reg.A].d)->data = reg.B;
|
||||||
|
|
||||||
|
mem[reg.B].d = new Symbol;
|
||||||
|
static_cast<Symbol*>(mem[reg.B].d)->data = "lambda";
|
||||||
|
mem[reg.B].cdr = mem[reg.args_front].cdr;
|
||||||
|
|
||||||
|
reg.A = newCell(); //wrapper
|
||||||
|
mem[reg.A].d = new Fork;
|
||||||
|
static_cast<Fork*>(mem[reg.A].d)->data = reg.D;
|
||||||
|
|
||||||
|
reg.D = reg.A;
|
||||||
|
|
||||||
|
reg.RP = locs::EVAL_START;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
reg.args_left = mem[((Fork *) mem[reg.Exp].d)->data].cdr;
|
reg.args_left = mem[((Fork *) mem[reg.Exp].d)->data].cdr;
|
||||||
reg.args_current = 0;
|
reg.args_current = 0;
|
||||||
|
|
@ -290,7 +398,7 @@ struct Machine {
|
||||||
reg.C = reg.op;
|
reg.C = reg.op;
|
||||||
Data *d = mem[reg.C].d;
|
Data *d = mem[reg.C].d;
|
||||||
if (Symbol *fname = dynamic_cast<Symbol *>(d)) {
|
if (Symbol *fname = dynamic_cast<Symbol *>(d)) {
|
||||||
if (reg.E.builtin.contains(fname->data)) {
|
if (builtin.contains(fname->data)) {
|
||||||
auto nloc = newCell();
|
auto nloc = newCell();
|
||||||
auto temp = ApplyBuiltin(fname->data, reg.args_front, nloc);
|
auto temp = ApplyBuiltin(fname->data, reg.args_front, nloc);
|
||||||
if(stack.empty()) {
|
if(stack.empty()) {
|
||||||
|
|
@ -314,10 +422,22 @@ struct Machine {
|
||||||
|
|
||||||
reg.B = reg.args_front;
|
reg.B = reg.args_front;
|
||||||
// reg.E = f->env;
|
// reg.E = f->env;
|
||||||
reg.E.userdef = f->env.userdef;
|
//reg.E.userdef = f->env.userdef;
|
||||||
|
|
||||||
|
|
||||||
|
//make new env with parrent set as the lambda's env
|
||||||
|
reg.C = newCell();
|
||||||
|
mem[reg.C].d = new EnvFrame(f->env);
|
||||||
|
|
||||||
|
|
||||||
|
//(static_cast<EnvFrame*>( mem[reg.E].d))->parent
|
||||||
|
|
||||||
|
reg.E = reg.C;
|
||||||
while (reg.A != 0) {
|
while (reg.A != 0) {
|
||||||
reg.E.userdef[((Symbol *)mem[reg.A].d)->data] =
|
//reg.E.userdef[((Symbol *)mem[reg.A].d)->data] = reg.B;
|
||||||
reg.B;
|
//EnvLookup(0, ((Symbol *) mem[reg.A].d)->data);
|
||||||
|
|
||||||
|
static_cast<EnvFrame*> (mem[reg.E].d)->bindings[static_cast<Symbol*>(mem[reg.A].d)->data] = reg.B;
|
||||||
reg.A = mem[reg.A].cdr;
|
reg.A = mem[reg.A].cdr;
|
||||||
reg.B = mem[reg.B].cdr;
|
reg.B = mem[reg.B].cdr;
|
||||||
}
|
}
|
||||||
|
|
@ -445,7 +565,15 @@ struct Machine {
|
||||||
return newlocation;
|
return newlocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (fname == "quote") {
|
||||||
|
return cdr;
|
||||||
|
} else if (fname == "define") {
|
||||||
|
static_cast<EnvFrame*>(mem[reg.E].d)->bindings[static_cast<Symbol*>(mem[cdr].d)->data] = mem[cdr].cdr;
|
||||||
|
return cdr;
|
||||||
|
} else if (fname == "defun-unq") {
|
||||||
|
static_cast<EnvFrame*>(mem[reg.E].d)->bindings[static_cast<Symbol*>(mem[cdr].d)->data] = mem[cdr].cdr;
|
||||||
|
static_cast<EnvFrame*>(mem[static_cast<Lambda*>(mem[mem[cdr].cdr].d)->env].d)->bindings[static_cast<Symbol*>(mem[cdr].d)->data] = mem[cdr].cdr;
|
||||||
|
return cdr;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -495,7 +623,7 @@ struct Machine {
|
||||||
// update orignal
|
// update orignal
|
||||||
v = nloc;
|
v = nloc;
|
||||||
} else { // if already moved
|
} else { // if already moved
|
||||||
std::cout << "v: " << v << std::endl;
|
//std::cout << "v: " << v << std::endl;
|
||||||
v = mem[v].cdr - maxCells;
|
v = mem[v].cdr - maxCells;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -516,19 +644,23 @@ struct Machine {
|
||||||
queue.push_back(std::ref(regs.op));
|
queue.push_back(std::ref(regs.op));
|
||||||
|
|
||||||
queue.push_back(std::ref(regs.R));
|
queue.push_back(std::ref(regs.R));
|
||||||
addEnvToGCQueue(queue, regs.E);
|
queue.push_back(std::ref(regs.E));
|
||||||
|
//addEnvToGCQueue(queue, regs.E);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addEnvToGCQueue(std::vector<std::reference_wrapper<size_t>>& queue, Env& env) {
|
// void addEnvToGCQueue(std::vector<std::reference_wrapper<size_t>>& queue, Env& env) {
|
||||||
for (auto& def : env.userdef) {
|
// for (auto& def : env.userdef) {
|
||||||
queue.push_back(std::ref(def.second));
|
// queue.push_back(std::ref(def.second));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
void GC() {
|
void GC() {
|
||||||
std::cout << "GCING" << std::endl;
|
//std::cout << "GCING" << std::endl;
|
||||||
std::vector<std::reference_wrapper<size_t>> queue;
|
std::vector<std::reference_wrapper<size_t>> queue;
|
||||||
|
|
||||||
|
|
||||||
|
// add global environment to queue (probably pos 1)
|
||||||
|
queue.push_back(std::ref(global_env));
|
||||||
// add all known to queue
|
// add all known to queue
|
||||||
addRegsToGCQueue(queue, reg);
|
addRegsToGCQueue(queue, reg);
|
||||||
|
|
||||||
|
|
@ -536,6 +668,7 @@ struct Machine {
|
||||||
addRegsToGCQueue(queue, e);
|
addRegsToGCQueue(queue, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// cheney's alg
|
// cheney's alg
|
||||||
|
|
||||||
// copy all root nodes over to to-space
|
// copy all root nodes over to to-space
|
||||||
|
|
@ -558,11 +691,14 @@ struct Machine {
|
||||||
if (Fork * f = dynamic_cast<Fork*>(mem_empty[scan].d)) {
|
if (Fork * f = dynamic_cast<Fork*>(mem_empty[scan].d)) {
|
||||||
GCMoveElem(std::ref(f->data));
|
GCMoveElem(std::ref(f->data));
|
||||||
} else if (Lambda * l = dynamic_cast<Lambda*>(mem_empty[scan].d)) {
|
} else if (Lambda * l = dynamic_cast<Lambda*>(mem_empty[scan].d)) {
|
||||||
for (auto& def : l->env.userdef) {
|
GCMoveElem(std::ref(l->env));
|
||||||
GCMoveElem(std::ref(def.second));
|
|
||||||
}
|
|
||||||
GCMoveElem(std::ref(l->args));
|
GCMoveElem(std::ref(l->args));
|
||||||
GCMoveElem(std::ref(l->f));
|
GCMoveElem(std::ref(l->f));
|
||||||
|
} else if (EnvFrame * e = dynamic_cast<EnvFrame*>(mem_empty[scan].d)) {
|
||||||
|
GCMoveElem(std::ref(e->parent));
|
||||||
|
for (auto& pair : e->bindings) {
|
||||||
|
GCMoveElem(std::ref(pair.second));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -585,7 +721,7 @@ struct Machine {
|
||||||
mem[i].d = nullptr;
|
mem[i].d = nullptr;
|
||||||
mem[i].cdr = 0;
|
mem[i].cdr = 0;
|
||||||
}
|
}
|
||||||
std::cout << "GC DONE, OLDSIZE: " << freepos << " newsize: " << mempty_pos << std::endl;
|
//std::cout << "GC DONE, OLDSIZE: " << freepos << " newsize: " << mempty_pos << std::endl;
|
||||||
mem.swap(mem_empty);
|
mem.swap(mem_empty);
|
||||||
freepos = mempty_pos;
|
freepos = mempty_pos;
|
||||||
mempty_pos = 1;
|
mempty_pos = 1;
|
||||||
|
|
@ -711,7 +847,7 @@ struct Machine {
|
||||||
};
|
};
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
auto m = Machine(27);
|
auto m = Machine(270000);
|
||||||
|
|
||||||
|
|
||||||
Cell c;
|
Cell c;
|
||||||
|
|
@ -723,6 +859,7 @@ int main() {
|
||||||
|
|
||||||
m.stack = std::vector<Registers>();
|
m.stack = std::vector<Registers>();
|
||||||
m.reg.ResetAllButEnv();
|
m.reg.ResetAllButEnv();
|
||||||
|
m.reg.E = m.global_env;
|
||||||
m.GC();
|
m.GC();
|
||||||
m.invalidgc = true;
|
m.invalidgc = true;
|
||||||
auto exp = m.read_expr(std::cin);
|
auto exp = m.read_expr(std::cin);
|
||||||
|
|
@ -732,14 +869,6 @@ int main() {
|
||||||
//m.reg = r;
|
//m.reg = r;
|
||||||
m.reg.D = exp;
|
m.reg.D = exp;
|
||||||
m.reg.RP = locs::EVAL_START;
|
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("progn");
|
|
||||||
m.reg.E.builtin.insert("print");
|
|
||||||
m.reg.E.builtin.insert("<");
|
|
||||||
m.reg.E.builtin.insert("if");
|
|
||||||
|
|
||||||
//m.ListPrint(m.mem[exp]);
|
//m.ListPrint(m.mem[exp]);
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
|
|
@ -748,7 +877,7 @@ int main() {
|
||||||
} catch (const char * err) {
|
} catch (const char * err) {
|
||||||
std::cout << err << std::endl;
|
std::cout << err << std::endl;
|
||||||
}
|
}
|
||||||
std::cout << "out of loop" << std::endl;
|
//std::cout << "out of loop" << std::endl;
|
||||||
std::cout << "freepos: " << m.freepos << " out of: " << m.maxCells << std::endl;
|
std::cout << "freepos: " << m.freepos << " out of: " << m.maxCells << std::endl;
|
||||||
|
|
||||||
c.d = m.mem[m.reg.R].d;
|
c.d = m.mem[m.reg.R].d;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue