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 <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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue