mirror of
https://github.com/usatiuk/psil.git
synced 2025-10-28 10:47:49 +01:00
switch for commands
This commit is contained in:
@@ -38,7 +38,7 @@ Handle Compiler::compile(const Handle &src, Handle fake_env, const Handle &suffi
|
||||
return out;
|
||||
};
|
||||
|
||||
std::function<Handle(Handle, Handle)> compileArgsList = [&](Handle args, Handle env) {
|
||||
std::function<Handle(Handle, Handle)> compileArgsList = [&](Handle args, const Handle &env) {
|
||||
Handle out;
|
||||
out.append(make_cmd(NIL));
|
||||
std::stack<Handle> rev;
|
||||
|
||||
@@ -23,10 +23,8 @@ void VM::run() {
|
||||
|
||||
void VM::step() {
|
||||
Handle poppedH = _c.pop();
|
||||
// as to not complicate parser for tests...
|
||||
CellValType poppedCmd = poppedH.type() == CellType::STRATOM ? str_to_cmd.at(poppedH.strval()) : poppedH.val();
|
||||
|
||||
|
||||
Logger::log(
|
||||
"VM",
|
||||
[&](std::ostream &out) {
|
||||
@@ -37,216 +35,276 @@ void VM::step() {
|
||||
if (!_d.null()) out << "d:" << _d << "\n";
|
||||
},
|
||||
Logger::TRACE);
|
||||
|
||||
if (poppedCmd == NIL) {
|
||||
_s.push(nullptr);
|
||||
} else if (poppedCmd == LDC) {
|
||||
_s.push(_c.pop());
|
||||
} else if (poppedCmd == ATOM) {
|
||||
_s.push(_s.pop().atom() ? 1 : 0);
|
||||
} else if (poppedCmd == NILC) {
|
||||
_s.push(_s.pop().null() ? 1 : 0);
|
||||
} else if (poppedCmd == LD) {
|
||||
Handle poppedH2 = _c.pop();
|
||||
|
||||
int64_t frame = poppedH2.car().val();
|
||||
int64_t arg = poppedH2.cdr().val();
|
||||
|
||||
assert(frame > 0);
|
||||
assert(arg > 0);
|
||||
|
||||
Handle curFrame = _e;
|
||||
|
||||
for (int i = 1; i < frame; i++) { curFrame = curFrame.cdr(); }
|
||||
|
||||
Handle curArg = curFrame.car();
|
||||
|
||||
for (int i = 1; i < arg; i++) { curArg = curArg.cdr(); }
|
||||
|
||||
_s.push(curArg.car());
|
||||
} else if (poppedCmd == SEL) {
|
||||
Handle popped2H = _s.pop();
|
||||
|
||||
Handle ct = _c.pop();
|
||||
Handle cf = _c.pop();
|
||||
|
||||
_d.push(_c);
|
||||
if (popped2H.val() > 0) {
|
||||
_c = ct;
|
||||
} else {
|
||||
_c = cf;
|
||||
|
||||
switch (poppedCmd) {
|
||||
case NIL: {
|
||||
_s.push(nullptr);
|
||||
break;
|
||||
}
|
||||
} else if (poppedCmd == JOIN) {
|
||||
_c = _d.pop();
|
||||
} else if (poppedCmd == LDF) {
|
||||
_s.push(Handle::cons(_c.pop(), _e));
|
||||
} else if (poppedCmd == AP) {
|
||||
Handle closureH = _s.pop();
|
||||
Handle argsH = _s.pop();
|
||||
|
||||
_d.push(_s);
|
||||
_d.push(_e);
|
||||
_d.push(_c);
|
||||
|
||||
std::optional<std::string> name;
|
||||
if (Logger::en_level("VM", Logger::DEBUG)) {
|
||||
name = "unknown";
|
||||
if (_globals_names_map.find(closureH) != _globals_names_map.end()) name = _globals_names_map.at(closureH);
|
||||
_d.push(Handle(*name));
|
||||
case LDC: {
|
||||
_s.push(_c.pop());
|
||||
break;
|
||||
}
|
||||
|
||||
_s = Handle::cons(nullptr, nullptr);
|
||||
_c = closureH.car();
|
||||
_e = closureH.cdr();
|
||||
|
||||
Logger::log(
|
||||
"VM",
|
||||
[&](std::ostream &out) {
|
||||
out << _cur_call_level;
|
||||
for (int i = 0; i < _cur_call_level; i++) out << " ";
|
||||
out << " Applying " << *name;
|
||||
out << " with args " << argsH;
|
||||
},
|
||||
Logger::DEBUG);
|
||||
|
||||
_cur_call_level++;
|
||||
_e.push(argsH);
|
||||
} else if (poppedCmd == RET) {
|
||||
_cur_call_level--;
|
||||
|
||||
Handle n;
|
||||
if (Logger::en_level("VM", Logger::DEBUG)) n = _d.pop();
|
||||
|
||||
Handle c = _d.pop();
|
||||
Handle e = _d.pop();
|
||||
Handle s = _d.pop();
|
||||
|
||||
Handle ret = _s.pop();
|
||||
|
||||
_c = c;
|
||||
_e = e;
|
||||
_s = s;
|
||||
|
||||
Logger::log(
|
||||
"VM",
|
||||
[&](std::ostream &out) {
|
||||
out << _cur_call_level;
|
||||
for (int i = 0; i < _cur_call_level; i++) out << " ";
|
||||
out << " Returning from " << n << " ";
|
||||
bool cons = !ret.atom();
|
||||
if (cons) out << "(";
|
||||
out << ret;
|
||||
if (cons) out << ")";
|
||||
},
|
||||
Logger::DEBUG);
|
||||
|
||||
_s.push(ret);
|
||||
} else if (poppedCmd == DUM) {
|
||||
_e.push(nullptr);
|
||||
} else if (poppedCmd == RAP) {
|
||||
Handle closureH = _s.pop();
|
||||
Handle argsH = _s.pop();
|
||||
|
||||
Handle origE = _e.cdr();
|
||||
|
||||
_d.push(_s);
|
||||
_d.push(origE);
|
||||
_d.push(_c);
|
||||
|
||||
if (Logger::en_level("VM", Logger::DEBUG)) _d.push(Handle("rap"));
|
||||
|
||||
_s = Handle::cons(nullptr, nullptr);
|
||||
_c = closureH.car();
|
||||
_e = closureH.cdr();
|
||||
|
||||
Handle fnEnv = closureH.cdr();
|
||||
assert(_e == fnEnv);
|
||||
|
||||
_cur_call_level++;
|
||||
|
||||
_e.push(argsH);
|
||||
fnEnv.setcar(argsH);
|
||||
} else if (poppedCmd == STOP) {
|
||||
_stop = true;
|
||||
} else if (poppedCmd == ADD) {
|
||||
_s.push(_s.pop().val() + _s.pop().val());
|
||||
} else if (poppedCmd == MULT) {
|
||||
_s.push(_s.pop().val() * _s.pop().val());
|
||||
} else if (poppedCmd == SUB) {
|
||||
CellValType a1 = _s.pop().val();
|
||||
CellValType a2 = _s.pop().val();
|
||||
_s.push(a1 - a2);
|
||||
} else if (poppedCmd == DIV) {
|
||||
CellValType a1 = _s.pop().val();
|
||||
CellValType a2 = _s.pop().val();
|
||||
_s.push(a1 / a2);
|
||||
} else if (poppedCmd == EQ) {
|
||||
_s.push(_s.pop() == _s.pop() ? 1 : 0);
|
||||
} else if (poppedCmd == LT) {
|
||||
CellValType a1 = _s.pop().val();
|
||||
CellValType a2 = _s.pop().val();
|
||||
_s.push(a1 < a2 ? 1 : 0);
|
||||
} else if (poppedCmd == GT) {
|
||||
CellValType a1 = _s.pop().val();
|
||||
CellValType a2 = _s.pop().val();
|
||||
_s.push(a1 > a2 ? 1 : 0);
|
||||
} else if (poppedCmd == CAR) {
|
||||
_s.push(_s.pop().car());
|
||||
} else if (poppedCmd == CDR) {
|
||||
_s.push(_s.pop().cdr());
|
||||
} else if (poppedCmd == CONS) {
|
||||
Handle h1 = _s.pop();
|
||||
Handle h2 = _s.pop();
|
||||
|
||||
_s.push(Handle::cons(h1, h2));
|
||||
} else if (poppedCmd == READCHAR) {
|
||||
char c;
|
||||
_instream >> c;
|
||||
_s.push(Handle::makeNumCell(c));
|
||||
} else if (poppedCmd == PUTCHAR) {
|
||||
_outstream << (char) _s.pop().val();
|
||||
} else if (poppedCmd == PUTNUM) {
|
||||
_outstream << _s.pop().val();
|
||||
} else if (poppedCmd == EVAL) {
|
||||
Handle code = _s.pop();
|
||||
Handle newc = Compiler::compile(code, _globals_names);
|
||||
Logger::log(
|
||||
"Compiler",
|
||||
[&](std::ostream &out) {
|
||||
out << "Compiled (" << code << ")";
|
||||
out << " to ";
|
||||
out << "(" << newc << ")";
|
||||
},
|
||||
Logger::DEBUG);
|
||||
newc.splice(_c);
|
||||
_c = newc;
|
||||
} else if (poppedCmd == LDG) {
|
||||
Handle newclosure = Handle::cons(_c.pop(), _e);
|
||||
|
||||
Handle curName = _globals_names.car();
|
||||
for (int i = 0; i < _cur_global; i++) { curName = curName.cdr(); }
|
||||
_globals_names_map.emplace(newclosure, curName.car().strval());
|
||||
_cur_global++;
|
||||
|
||||
_globals_vals.append(newclosure);
|
||||
} else if (poppedCmd == PRINT) {
|
||||
if (!_s.null()) {
|
||||
Handle val = _s.pop();
|
||||
bool cons = !val.atom();
|
||||
if (cons) _outstream << "(";
|
||||
_outstream << val;
|
||||
if (cons) _outstream << ")";
|
||||
_outstream << std::endl;
|
||||
case ATOM: {
|
||||
_s.push(_s.pop().atom() ? 1 : 0);
|
||||
break;
|
||||
}
|
||||
} else if (poppedCmd == READ) {
|
||||
std::string read;
|
||||
std::getline(_instream, read);
|
||||
_s.push(Parser::parse_str(read));
|
||||
} else {
|
||||
throw std::invalid_argument("Unexpected end of program");
|
||||
case NILC: {
|
||||
_s.push(_s.pop().null() ? 1 : 0);
|
||||
break;
|
||||
}
|
||||
case LD: {
|
||||
Handle poppedH2 = _c.pop();
|
||||
|
||||
int64_t frame = poppedH2.car().val();
|
||||
int64_t arg = poppedH2.cdr().val();
|
||||
|
||||
assert(frame > 0);
|
||||
assert(arg > 0);
|
||||
|
||||
Handle curFrame = _e;
|
||||
|
||||
for (int i = 1; i < frame; i++) { curFrame = curFrame.cdr(); }
|
||||
|
||||
Handle curArg = curFrame.car();
|
||||
|
||||
for (int i = 1; i < arg; i++) { curArg = curArg.cdr(); }
|
||||
|
||||
_s.push(curArg.car());
|
||||
break;
|
||||
}
|
||||
case SEL: {
|
||||
Handle popped2H = _s.pop();
|
||||
|
||||
Handle ct = _c.pop();
|
||||
Handle cf = _c.pop();
|
||||
|
||||
_d.push(_c);
|
||||
if (popped2H.val() > 0) {
|
||||
_c = ct;
|
||||
} else {
|
||||
_c = cf;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JOIN: {
|
||||
_c = _d.pop();
|
||||
break;
|
||||
}
|
||||
case LDF: {
|
||||
_s.push(Handle::cons(_c.pop(), _e));
|
||||
break;
|
||||
}
|
||||
case AP: {
|
||||
Handle closureH = _s.pop();
|
||||
Handle argsH = _s.pop();
|
||||
|
||||
_d.push(_s);
|
||||
_d.push(_e);
|
||||
_d.push(_c);
|
||||
|
||||
std::optional<std::string> name;
|
||||
if (Logger::en_level("VM", Logger::DEBUG)) {
|
||||
name = "unknown";
|
||||
if (_globals_names_map.find(closureH) != _globals_names_map.end())
|
||||
name = _globals_names_map.at(closureH);
|
||||
_d.push(Handle(*name));
|
||||
}
|
||||
|
||||
_s = Handle::cons(nullptr, nullptr);
|
||||
_c = closureH.car();
|
||||
_e = closureH.cdr();
|
||||
|
||||
Logger::log(
|
||||
"VM",
|
||||
[&](std::ostream &out) {
|
||||
out << _cur_call_level;
|
||||
for (int i = 0; i < _cur_call_level; i++) out << " ";
|
||||
out << " Applying " << *name;
|
||||
out << " with args " << argsH;
|
||||
},
|
||||
Logger::DEBUG);
|
||||
|
||||
_cur_call_level++;
|
||||
_e.push(argsH);
|
||||
break;
|
||||
}
|
||||
case RET: {
|
||||
_cur_call_level--;
|
||||
|
||||
Handle n;
|
||||
if (Logger::en_level("VM", Logger::DEBUG)) n = _d.pop();
|
||||
|
||||
Handle c = _d.pop();
|
||||
Handle e = _d.pop();
|
||||
Handle s = _d.pop();
|
||||
|
||||
Handle ret = _s.pop();
|
||||
|
||||
_c = c;
|
||||
_e = e;
|
||||
_s = s;
|
||||
|
||||
Logger::log(
|
||||
"VM",
|
||||
[&](std::ostream &out) {
|
||||
out << _cur_call_level;
|
||||
for (int i = 0; i < _cur_call_level; i++) out << " ";
|
||||
out << " Returning from " << n << " ";
|
||||
bool cons = !ret.atom();
|
||||
if (cons) out << "(";
|
||||
out << ret;
|
||||
if (cons) out << ")";
|
||||
},
|
||||
Logger::DEBUG);
|
||||
|
||||
_s.push(ret);
|
||||
break;
|
||||
}
|
||||
case DUM: {
|
||||
_e.push(nullptr);
|
||||
break;
|
||||
}
|
||||
case RAP: {
|
||||
Handle closureH = _s.pop();
|
||||
Handle argsH = _s.pop();
|
||||
|
||||
Handle origE = _e.cdr();
|
||||
|
||||
_d.push(_s);
|
||||
_d.push(origE);
|
||||
_d.push(_c);
|
||||
|
||||
if (Logger::en_level("VM", Logger::DEBUG)) _d.push(Handle("rap"));
|
||||
|
||||
_s = Handle::cons(nullptr, nullptr);
|
||||
_c = closureH.car();
|
||||
_e = closureH.cdr();
|
||||
|
||||
Handle fnEnv = closureH.cdr();
|
||||
assert(_e == fnEnv);
|
||||
|
||||
_cur_call_level++;
|
||||
|
||||
_e.push(argsH);
|
||||
fnEnv.setcar(argsH);
|
||||
break;
|
||||
}
|
||||
case STOP: {
|
||||
_stop = true;
|
||||
break;
|
||||
}
|
||||
case ADD: {
|
||||
_s.push(_s.pop().val() + _s.pop().val());
|
||||
break;
|
||||
}
|
||||
case MULT: {
|
||||
_s.push(_s.pop().val() * _s.pop().val());
|
||||
break;
|
||||
}
|
||||
case SUB: {
|
||||
CellValType a1 = _s.pop().val();
|
||||
CellValType a2 = _s.pop().val();
|
||||
_s.push(a1 - a2);
|
||||
break;
|
||||
}
|
||||
case DIV: {
|
||||
CellValType a1 = _s.pop().val();
|
||||
CellValType a2 = _s.pop().val();
|
||||
_s.push(a1 / a2);
|
||||
break;
|
||||
}
|
||||
case EQ: {
|
||||
_s.push(_s.pop() == _s.pop() ? 1 : 0);
|
||||
break;
|
||||
}
|
||||
case LT: {
|
||||
CellValType a1 = _s.pop().val();
|
||||
CellValType a2 = _s.pop().val();
|
||||
_s.push(a1 < a2 ? 1 : 0);
|
||||
break;
|
||||
}
|
||||
case GT: {
|
||||
CellValType a1 = _s.pop().val();
|
||||
CellValType a2 = _s.pop().val();
|
||||
_s.push(a1 > a2 ? 1 : 0);
|
||||
break;
|
||||
}
|
||||
case CAR: {
|
||||
_s.push(_s.pop().car());
|
||||
break;
|
||||
}
|
||||
case CDR: {
|
||||
_s.push(_s.pop().cdr());
|
||||
break;
|
||||
}
|
||||
case CONS: {
|
||||
Handle h1 = _s.pop();
|
||||
Handle h2 = _s.pop();
|
||||
|
||||
_s.push(Handle::cons(h1, h2));
|
||||
break;
|
||||
}
|
||||
case READCHAR: {
|
||||
char c;
|
||||
_instream >> c;
|
||||
_s.push(Handle::makeNumCell(c));
|
||||
break;
|
||||
}
|
||||
case PUTCHAR: {
|
||||
_outstream << (char) _s.pop().val();
|
||||
break;
|
||||
}
|
||||
case PUTNUM: {
|
||||
_outstream << _s.pop().val();
|
||||
break;
|
||||
}
|
||||
case EVAL: {
|
||||
Handle code = _s.pop();
|
||||
Handle newc = Compiler::compile(code, _globals_names);
|
||||
Logger::log(
|
||||
"Compiler",
|
||||
[&](std::ostream &out) {
|
||||
out << "Compiled (" << code << ")";
|
||||
out << " to ";
|
||||
out << "(" << newc << ")";
|
||||
},
|
||||
Logger::DEBUG);
|
||||
newc.splice(_c);
|
||||
_c = newc;
|
||||
break;
|
||||
}
|
||||
case LDG: {
|
||||
Handle newclosure = Handle::cons(_c.pop(), _e);
|
||||
|
||||
Handle curName = _globals_names.car();
|
||||
for (int i = 0; i < _cur_global; i++) { curName = curName.cdr(); }
|
||||
_globals_names_map.emplace(newclosure, curName.car().strval());
|
||||
_cur_global++;
|
||||
|
||||
_globals_vals.append(newclosure);
|
||||
break;
|
||||
}
|
||||
case PRINT: {
|
||||
if (!_s.null()) {
|
||||
Handle val = _s.pop();
|
||||
bool cons = !val.atom();
|
||||
if (cons) _outstream << "(";
|
||||
_outstream << val;
|
||||
if (cons) _outstream << ")";
|
||||
_outstream << std::endl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case READ: {
|
||||
std::string read;
|
||||
std::getline(_instream, read);
|
||||
_s.push(Parser::parse_str(read));
|
||||
}
|
||||
default:
|
||||
throw std::invalid_argument("Unknown command: " + std::to_string(poppedCmd));
|
||||
}
|
||||
|
||||
|
||||
Logger::log(
|
||||
"VM",
|
||||
[&](std::ostream &out) {
|
||||
|
||||
@@ -13,6 +13,7 @@ public:
|
||||
~Environment() override {}
|
||||
|
||||
void SetUp() override {
|
||||
Options::set<size_t>("cell_limit", 50000);
|
||||
Options::set<bool>("command_strs", true);
|
||||
Logger::set_level("VM", Logger::DEBUG);
|
||||
Logger::set_level("Compiler", Logger::DEBUG);
|
||||
|
||||
@@ -7,7 +7,7 @@ public:
|
||||
~Environment() override {}
|
||||
|
||||
void SetUp() override {
|
||||
Options::set<size_t>("cell_limit", 1000);
|
||||
Options::set<size_t>("cell_limit", 5000);
|
||||
Logger::set_level("Compiler", Logger::DEBUG);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ public:
|
||||
~Environment() override {}
|
||||
|
||||
void SetUp() override {
|
||||
Options::set<size_t>("cell_limit", 2000);
|
||||
Options::set<size_t>("cell_limit", 5000);
|
||||
Logger::set_level("Compiler", Logger::DEBUG);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user