mirror of
https://github.com/usatiuk/psil.git
synced 2025-10-28 18:57:48 +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;
|
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;
|
Handle out;
|
||||||
out.append(make_cmd(NIL));
|
out.append(make_cmd(NIL));
|
||||||
std::stack<Handle> rev;
|
std::stack<Handle> rev;
|
||||||
|
|||||||
@@ -23,10 +23,8 @@ void VM::run() {
|
|||||||
|
|
||||||
void VM::step() {
|
void VM::step() {
|
||||||
Handle poppedH = _c.pop();
|
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();
|
CellValType poppedCmd = poppedH.type() == CellType::STRATOM ? str_to_cmd.at(poppedH.strval()) : poppedH.val();
|
||||||
|
|
||||||
|
|
||||||
Logger::log(
|
Logger::log(
|
||||||
"VM",
|
"VM",
|
||||||
[&](std::ostream &out) {
|
[&](std::ostream &out) {
|
||||||
@@ -37,216 +35,276 @@ void VM::step() {
|
|||||||
if (!_d.null()) out << "d:" << _d << "\n";
|
if (!_d.null()) out << "d:" << _d << "\n";
|
||||||
},
|
},
|
||||||
Logger::TRACE);
|
Logger::TRACE);
|
||||||
|
|
||||||
if (poppedCmd == NIL) {
|
switch (poppedCmd) {
|
||||||
_s.push(nullptr);
|
case NIL: {
|
||||||
} else if (poppedCmd == LDC) {
|
_s.push(nullptr);
|
||||||
_s.push(_c.pop());
|
break;
|
||||||
} 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;
|
|
||||||
}
|
}
|
||||||
} else if (poppedCmd == JOIN) {
|
case LDC: {
|
||||||
_c = _d.pop();
|
_s.push(_c.pop());
|
||||||
} else if (poppedCmd == LDF) {
|
break;
|
||||||
_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 ATOM: {
|
||||||
_s = Handle::cons(nullptr, nullptr);
|
_s.push(_s.pop().atom() ? 1 : 0);
|
||||||
_c = closureH.car();
|
break;
|
||||||
_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;
|
|
||||||
}
|
}
|
||||||
} else if (poppedCmd == READ) {
|
case NILC: {
|
||||||
std::string read;
|
_s.push(_s.pop().null() ? 1 : 0);
|
||||||
std::getline(_instream, read);
|
break;
|
||||||
_s.push(Parser::parse_str(read));
|
}
|
||||||
} else {
|
case LD: {
|
||||||
throw std::invalid_argument("Unexpected end of program");
|
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(
|
Logger::log(
|
||||||
"VM",
|
"VM",
|
||||||
[&](std::ostream &out) {
|
[&](std::ostream &out) {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ public:
|
|||||||
~Environment() override {}
|
~Environment() override {}
|
||||||
|
|
||||||
void SetUp() override {
|
void SetUp() override {
|
||||||
|
Options::set<size_t>("cell_limit", 50000);
|
||||||
Options::set<bool>("command_strs", true);
|
Options::set<bool>("command_strs", true);
|
||||||
Logger::set_level("VM", Logger::DEBUG);
|
Logger::set_level("VM", Logger::DEBUG);
|
||||||
Logger::set_level("Compiler", Logger::DEBUG);
|
Logger::set_level("Compiler", Logger::DEBUG);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ public:
|
|||||||
~Environment() override {}
|
~Environment() override {}
|
||||||
|
|
||||||
void SetUp() override {
|
void SetUp() override {
|
||||||
Options::set<size_t>("cell_limit", 1000);
|
Options::set<size_t>("cell_limit", 5000);
|
||||||
Logger::set_level("Compiler", Logger::DEBUG);
|
Logger::set_level("Compiler", Logger::DEBUG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ public:
|
|||||||
~Environment() override {}
|
~Environment() override {}
|
||||||
|
|
||||||
void SetUp() override {
|
void SetUp() override {
|
||||||
Options::set<size_t>("cell_limit", 2000);
|
Options::set<size_t>("cell_limit", 5000);
|
||||||
Logger::set_level("Compiler", Logger::DEBUG);
|
Logger::set_level("Compiler", Logger::DEBUG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user