if
This commit is contained in:
parent
9b19a1f63d
commit
2c64b5b231
1 changed files with 53 additions and 3 deletions
56
src/main.cpp
56
src/main.cpp
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue