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 <iostream>
#include <istream>
#include <memory>
#include <string>
#include <unordered_map>
#include <unordered_set>
@ -50,6 +51,11 @@ struct Number : SelfEval {
}
};
struct Nil : SelfEval {
void Get() {}
};
struct Fork : Data {
size_t data;
size_t Get() {
@ -65,7 +71,7 @@ struct Lambda : Data {
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 {
@ -171,6 +177,8 @@ struct Machine {
}
if(c->data == "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;
@ -191,6 +199,23 @@ struct Machine {
reg.args_current = temp;
}
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
auto onlyoneleft = mem[reg.args_left].cdr == 0;
@ -198,7 +223,8 @@ struct Machine {
bool newframe = false;
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);
newframe = true;
@ -253,6 +279,8 @@ struct Machine {
throw "err";
}
}
}
}
}
@ -328,10 +356,30 @@ struct Machine {
std::cout << n->data << std::endl;
} else if (String * s = dynamic_cast<String*>(mem[cdr].d)) {
std::cout << s->data << std::endl;
} else if(Nil * n = dynamic_cast<Nil*>(mem[cdr].d)) {
std::cout << "!nil!" << std::endl;
} else {
throw "invalid print";
}
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;
}
@ -466,7 +514,7 @@ struct Machine {
};
int main() {
auto m = Machine(10000);
auto m = Machine(1000);
Cell c;
@ -487,6 +535,8 @@ int main() {
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;