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
|
||||
CXX = g++
|
||||
|
||||
CPPFLAGS = -std=c++20 -g -Wall -Wextra -Wpedantic #-O3 -ffast-math
|
||||
CFLAGS = -g -Wall -Wextra -Wpedantic #-O3 -ffast-math
|
||||
LDFLAGS = -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
|
||||
LDFLAGS = -g -Wall -Wextra -Wpedantic -O3 -ffast-math
|
||||
LDLIBS =
|
||||
|
||||
|
||||
|
|
|
|||
211
src/main.cpp
211
src/main.cpp
|
|
@ -28,9 +28,16 @@ struct Cell {
|
|||
size_t cdr = 0;
|
||||
};
|
||||
|
||||
struct Env {
|
||||
std::unordered_set<std::string> builtin;
|
||||
std::unordered_map<std::string, size_t> userdef;
|
||||
// struct Env {
|
||||
// std::unordered_set<std::string> builtin;
|
||||
// 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 {
|
||||
|
|
@ -67,7 +74,8 @@ struct Fork : Data {
|
|||
};
|
||||
|
||||
struct Lambda : Data {
|
||||
Env env;
|
||||
//Env env;
|
||||
size_t env = 0;
|
||||
size_t args = 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 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 {
|
||||
|
|
@ -98,7 +106,8 @@ struct Registers {
|
|||
locs RP;
|
||||
|
||||
size_t R = 0;
|
||||
Env E;
|
||||
|
||||
size_t E = 0;
|
||||
|
||||
special_indef_eval screen = special_indef_eval::NONE;
|
||||
|
||||
|
|
@ -138,17 +147,52 @@ struct Machine {
|
|||
|
||||
Registers reg;
|
||||
|
||||
std::unordered_set<std::string> builtin;
|
||||
|
||||
size_t global_env = 0;
|
||||
|
||||
bool invalidgc = false;
|
||||
|
||||
Machine(size_t max) : mem(max), mem_empty(max) {
|
||||
maxCells = max;
|
||||
reg.E.builtin.insert("+");
|
||||
reg.E.builtin.insert("-");
|
||||
reg.E.builtin.insert("lambda");
|
||||
reg.E.builtin.insert("progn");
|
||||
reg.E.builtin.insert("print");
|
||||
|
||||
builtin.insert("+");
|
||||
builtin.insert("*");
|
||||
builtin.insert("-");
|
||||
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() {
|
||||
while (true) {
|
||||
switch (reg.RP) {
|
||||
|
|
@ -173,7 +217,7 @@ struct Machine {
|
|||
|
||||
// return h;
|
||||
} else if (Symbol *h = dynamic_cast<Symbol *>(d)) {
|
||||
if (reg.E.builtin.contains(h->data)) {
|
||||
if (builtin.contains(h->data)) {
|
||||
if(stack.empty()) {
|
||||
reg.R = reg.C; //return addressof
|
||||
return;
|
||||
|
|
@ -186,13 +230,15 @@ struct Machine {
|
|||
reg.R = loc; //return addressof
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
reg = stack.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)) {
|
||||
reg.Exp = reg.C; //set exp to addressof
|
||||
|
|
@ -225,6 +271,68 @@ struct Machine {
|
|||
} else if (c->data == "if") {
|
||||
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_current = 0;
|
||||
|
|
@ -290,7 +398,7 @@ struct Machine {
|
|||
reg.C = reg.op;
|
||||
Data *d = mem[reg.C].d;
|
||||
if (Symbol *fname = dynamic_cast<Symbol *>(d)) {
|
||||
if (reg.E.builtin.contains(fname->data)) {
|
||||
if (builtin.contains(fname->data)) {
|
||||
auto nloc = newCell();
|
||||
auto temp = ApplyBuiltin(fname->data, reg.args_front, nloc);
|
||||
if(stack.empty()) {
|
||||
|
|
@ -314,10 +422,22 @@ struct Machine {
|
|||
|
||||
reg.B = reg.args_front;
|
||||
// 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) {
|
||||
reg.E.userdef[((Symbol *)mem[reg.A].d)->data] =
|
||||
reg.B;
|
||||
//reg.E.userdef[((Symbol *)mem[reg.A].d)->data] = 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.B = mem[reg.B].cdr;
|
||||
}
|
||||
|
|
@ -445,7 +565,15 @@ struct Machine {
|
|||
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;
|
||||
}
|
||||
|
|
@ -495,7 +623,7 @@ struct Machine {
|
|||
// update orignal
|
||||
v = nloc;
|
||||
} else { // if already moved
|
||||
std::cout << "v: " << v << std::endl;
|
||||
//std::cout << "v: " << v << std::endl;
|
||||
v = mem[v].cdr - maxCells;
|
||||
}
|
||||
}
|
||||
|
|
@ -516,19 +644,23 @@ struct Machine {
|
|||
queue.push_back(std::ref(regs.op));
|
||||
|
||||
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) {
|
||||
for (auto& def : env.userdef) {
|
||||
queue.push_back(std::ref(def.second));
|
||||
}
|
||||
}
|
||||
// void addEnvToGCQueue(std::vector<std::reference_wrapper<size_t>>& queue, Env& env) {
|
||||
// for (auto& def : env.userdef) {
|
||||
// queue.push_back(std::ref(def.second));
|
||||
// }
|
||||
// }
|
||||
|
||||
void GC() {
|
||||
std::cout << "GCING" << std::endl;
|
||||
//std::cout << "GCING" << std::endl;
|
||||
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
|
||||
addRegsToGCQueue(queue, reg);
|
||||
|
||||
|
|
@ -536,6 +668,7 @@ struct Machine {
|
|||
addRegsToGCQueue(queue, e);
|
||||
}
|
||||
|
||||
|
||||
// cheney's alg
|
||||
|
||||
// copy all root nodes over to to-space
|
||||
|
|
@ -558,11 +691,14 @@ struct Machine {
|
|||
if (Fork * f = dynamic_cast<Fork*>(mem_empty[scan].d)) {
|
||||
GCMoveElem(std::ref(f->data));
|
||||
} else if (Lambda * l = dynamic_cast<Lambda*>(mem_empty[scan].d)) {
|
||||
for (auto& def : l->env.userdef) {
|
||||
GCMoveElem(std::ref(def.second));
|
||||
}
|
||||
GCMoveElem(std::ref(l->env));
|
||||
GCMoveElem(std::ref(l->args));
|
||||
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].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);
|
||||
freepos = mempty_pos;
|
||||
mempty_pos = 1;
|
||||
|
|
@ -711,7 +847,7 @@ struct Machine {
|
|||
};
|
||||
|
||||
int main() {
|
||||
auto m = Machine(27);
|
||||
auto m = Machine(270000);
|
||||
|
||||
|
||||
Cell c;
|
||||
|
|
@ -723,6 +859,7 @@ int main() {
|
|||
|
||||
m.stack = std::vector<Registers>();
|
||||
m.reg.ResetAllButEnv();
|
||||
m.reg.E = m.global_env;
|
||||
m.GC();
|
||||
m.invalidgc = true;
|
||||
auto exp = m.read_expr(std::cin);
|
||||
|
|
@ -732,14 +869,6 @@ int main() {
|
|||
//m.reg = r;
|
||||
m.reg.D = exp;
|
||||
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]);
|
||||
std::cout << std::endl;
|
||||
|
|
@ -748,7 +877,7 @@ int main() {
|
|||
} catch (const char * err) {
|
||||
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;
|
||||
|
||||
c.d = m.mem[m.reg.R].d;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue