This commit is contained in:
IXtreme 2026-07-08 23:54:55 -04:00
parent 9b19a1f63d
commit 2c64b5b231

View file

@ -1,6 +1,7 @@
#include <cassert> #include <cassert>
#include <iostream> #include <iostream>
#include <istream> #include <istream>
#include <memory>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
@ -50,6 +51,11 @@ struct Number : SelfEval {
} }
}; };
struct Nil : SelfEval {
void Get() {}
};
struct Fork : Data { struct Fork : Data {
size_t data; size_t data;
size_t Get() { size_t Get() {
@ -65,7 +71,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}; enum class special_indef_eval {NONE, PROGN, IF_BEGIN, FORCE_RETURN_NEXT_ARG};
struct Registers { struct Registers {
@ -171,6 +177,8 @@ struct Machine {
} }
if(c->data == "progn") { if(c->data == "progn") {
reg.screen = special_indef_eval::PROGN; reg.screen = special_indef_eval::PROGN;
} else if (c->data == "if") {
reg.screen = special_indef_eval::IF_BEGIN;
} }
} }
reg.args_left = mem[((Fork *)std::get<Data *>(reg.Exp))->data].cdr; reg.args_left = mem[((Fork *)std::get<Data *>(reg.Exp))->data].cdr;
@ -191,6 +199,23 @@ struct Machine {
reg.args_current = temp; reg.args_current = temp;
} }
mem[reg.args_current].d = std::get<Data*>(reg.R); mem[reg.args_current].d = std::get<Data*>(reg.R);
// is in an 'if' statement but got first arg back
if (reg.screen == special_indef_eval::IF_BEGIN) {
Nil * v = dynamic_cast<Nil*>(mem[reg.args_current].d);
if(v != nullptr) {
// if conditional returned false
// skip first argument
reg.args_left = mem[reg.args_left].cdr;
reg.screen = special_indef_eval::FORCE_RETURN_NEXT_ARG;
} else {
// if conditional returned true
reg.screen = special_indef_eval::FORCE_RETURN_NEXT_ARG;
}
}
} }
if (reg.args_left != 0) { //args left if (reg.args_left != 0) { //args left
auto onlyoneleft = mem[reg.args_left].cdr == 0; auto onlyoneleft = mem[reg.args_left].cdr == 0;
@ -198,7 +223,8 @@ struct Machine {
bool newframe = false; bool newframe = false;
if (reg.screen == special_indef_eval::NONE if (reg.screen == special_indef_eval::NONE
|| (reg.screen == special_indef_eval::PROGN && !onlyoneleft)) { || (reg.screen == special_indef_eval::PROGN && !onlyoneleft)
|| (reg.screen == special_indef_eval::IF_BEGIN)) {
stack.push_back(reg); stack.push_back(reg);
newframe = true; newframe = true;
@ -253,6 +279,8 @@ struct Machine {
throw "err"; throw "err";
} }
} }
} }
} }
} }
@ -328,10 +356,30 @@ struct Machine {
std::cout << n->data << std::endl; std::cout << n->data << std::endl;
} else if (String * s = dynamic_cast<String*>(mem[cdr].d)) { } else if (String * s = dynamic_cast<String*>(mem[cdr].d)) {
std::cout << s->data << std::endl; std::cout << s->data << std::endl;
} else if(Nil * n = dynamic_cast<Nil*>(mem[cdr].d)) {
std::cout << "!nil!" << std::endl;
} else { } else {
throw "invalid print"; throw "invalid print";
} }
return cdr; return cdr;
} else if (fname == "<") {
Number * f = dynamic_cast<Number*>(mem[cdr].d);
if (!f) throw "Non Number applied to <";
cdr = mem[cdr].cdr;
Number * l = dynamic_cast<Number*>(mem[cdr].d);
if (!l) throw "Non Number applied to <";
if (f->Get() < l->Get()) {
Number *n = new Number;
n->data = 1;
return newCell(n);
} else {
Nil * n = new Nil;
return newCell(n);
}
} }
return 0; return 0;
} }
@ -466,7 +514,7 @@ struct Machine {
}; };
int main() { int main() {
auto m = Machine(10000); auto m = Machine(1000);
Cell c; Cell c;
@ -487,6 +535,8 @@ int main() {
m.reg.E.builtin.insert("lambda"); m.reg.E.builtin.insert("lambda");
m.reg.E.builtin.insert("progn"); m.reg.E.builtin.insert("progn");
m.reg.E.builtin.insert("print"); 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;