hopefully correct rap

This commit is contained in:
2023-12-23 14:22:47 +01:00
parent 6d324954af
commit 3bace25d46
3 changed files with 201 additions and 6 deletions

View File

@@ -48,6 +48,9 @@ struct CommandCell : public IntCell {
READCHAR = 201, READCHAR = 201,
PUTCHAR = 202, PUTCHAR = 202,
PUTNUM = 203,
CONS = 301,
END = 1000 END = 1000
}; };

View File

@@ -13,6 +13,7 @@ void VM::run() {
void VM::step() { void VM::step() {
CommandCell *popped = dynamic_cast<CommandCell *>(pop(_c)); CommandCell *popped = dynamic_cast<CommandCell *>(pop(_c));
assert(popped);
switch (popped->intToCmd()) { switch (popped->intToCmd()) {
case CommandCell::CommandNum::NIL: { case CommandCell::CommandNum::NIL: {
@@ -25,8 +26,11 @@ void VM::step() {
} }
case CommandCell::CommandNum::LD: { case CommandCell::CommandNum::LD: {
ConsCell *popped2 = dynamic_cast<ConsCell *>(pop(_c)); ConsCell *popped2 = dynamic_cast<ConsCell *>(pop(_c));
assert(popped2);
assert(dynamic_cast<IntCell *>(popped2->_car));
int64_t frame = dynamic_cast<IntCell *>(popped2->_car)->_val; int64_t frame = dynamic_cast<IntCell *>(popped2->_car)->_val;
assert(dynamic_cast<IntCell *>(popped2->_cdr));
int64_t arg = dynamic_cast<IntCell *>(popped2->_cdr)->_val; int64_t arg = dynamic_cast<IntCell *>(popped2->_cdr)->_val;
assert(frame > 0); assert(frame > 0);
@@ -36,11 +40,13 @@ void VM::step() {
for (int i = 1; i < frame; i++) { for (int i = 1; i < frame; i++) {
curFrame = dynamic_cast<ConsCell *>(_e->_cdr); curFrame = dynamic_cast<ConsCell *>(_e->_cdr);
assert(curFrame);
} }
ConsCell *curArg = dynamic_cast<ConsCell *>(curFrame->_car); ConsCell *curArg = dynamic_cast<ConsCell *>(curFrame->_car);
for (int i = 1; i < arg; i++) { for (int i = 1; i < arg; i++) {
curArg = dynamic_cast<ConsCell *>(curArg->_cdr); curArg = dynamic_cast<ConsCell *>(curArg->_cdr);
assert(curArg);
} }
push(_s, curArg->_car); push(_s, curArg->_car);
@@ -49,8 +55,11 @@ void VM::step() {
} }
case CommandCell::CommandNum::SEL: { case CommandCell::CommandNum::SEL: {
IntCell *popped2 = dynamic_cast<IntCell *>(pop(_s)); IntCell *popped2 = dynamic_cast<IntCell *>(pop(_s));
assert(popped2);
ConsCell *ct = dynamic_cast<ConsCell *>(pop(_c)); ConsCell *ct = dynamic_cast<ConsCell *>(pop(_c));
assert(ct);
ConsCell *cf = dynamic_cast<ConsCell *>(pop(_c)); ConsCell *cf = dynamic_cast<ConsCell *>(pop(_c));
assert(cf);
ConsCell *ret = _c; ConsCell *ret = _c;
push(_d, ret); push(_d, ret);
if (popped2->_val > 0) { if (popped2->_val > 0) {
@@ -63,30 +72,37 @@ void VM::step() {
} }
case CommandCell::CommandNum::JOIN: { case CommandCell::CommandNum::JOIN: {
ConsCell *ret = dynamic_cast<ConsCell *>(pop(_d)); ConsCell *ret = dynamic_cast<ConsCell *>(pop(_d));
assert(ret);
_c = ret; _c = ret;
break; break;
} }
case CommandCell::CommandNum::LDF: { case CommandCell::CommandNum::LDF: {
ConsCell *fn = dynamic_cast<ConsCell *>(pop(_c)); ConsCell *fn = dynamic_cast<ConsCell *>(pop(_c));
assert(fn);
push(_s, makeCell<ConsCell>(fn, _e)); push(_s, makeCell<ConsCell>(fn, _e));
break; break;
} }
case CommandCell::CommandNum::AP: { case CommandCell::CommandNum::AP: {
ConsCell *closure = dynamic_cast<ConsCell *>(pop(_s)); ConsCell *closure = dynamic_cast<ConsCell *>(pop(_s));
assert(closure);
ConsCell *args = dynamic_cast<ConsCell *>(pop(_s)); ConsCell *args = dynamic_cast<ConsCell *>(pop(_s));
assert(args);
push(_d, _s); push(_d, _s);
push(_d, _e); push(_d, _e);
assert(_c);
push(_d, _c); push(_d, _c);
_s = makeCell<ConsCell>(); _s = makeCell<ConsCell>();
_c = dynamic_cast<ConsCell *>(closure->_car); _c = dynamic_cast<ConsCell *>(closure->_car);
assert(_c);
_e = dynamic_cast<ConsCell *>(closure->_cdr); _e = dynamic_cast<ConsCell *>(closure->_cdr);
push(_e, args); push(_e, args);
break; break;
} }
case CommandCell::CommandNum::RET: { case CommandCell::CommandNum::RET: {
ConsCell *c = dynamic_cast<ConsCell *>(pop(_d)); ConsCell *c = dynamic_cast<ConsCell *>(pop(_d));
assert(c);
ConsCell *e = dynamic_cast<ConsCell *>(pop(_d)); ConsCell *e = dynamic_cast<ConsCell *>(pop(_d));
ConsCell *s = dynamic_cast<ConsCell *>(pop(_d)); ConsCell *s = dynamic_cast<ConsCell *>(pop(_d));
@@ -101,9 +117,28 @@ void VM::step() {
break; break;
} }
case CommandCell::CommandNum::DUM: { case CommandCell::CommandNum::DUM: {
push(_e, nullptr);
break; break;
} }
case CommandCell::CommandNum::RAP: { case CommandCell::CommandNum::RAP: {
ConsCell *closure = dynamic_cast<ConsCell *>(pop(_s));
assert(closure);
ConsCell *args = dynamic_cast<ConsCell *>(pop(_s));
assert(args);
push(_d, _s);
ConsCell *e = dynamic_cast<ConsCell *>(_e->_cdr);
push(_d, e);
assert(_c);
push(_d, _c);
_s = makeCell<ConsCell>();
_c = dynamic_cast<ConsCell *>(closure->_car);
assert(_c);
ConsCell *fnenv = dynamic_cast<ConsCell *>(closure->_cdr);
assert(fnenv);
assert(_e == fnenv);
fnenv->_car = args;
break; break;
} }
case CommandCell::CommandNum::STOP: { case CommandCell::CommandNum::STOP: {
@@ -112,13 +147,22 @@ void VM::step() {
} }
case CommandCell::CommandNum::ADD: { case CommandCell::CommandNum::ADD: {
IntCell *a1 = dynamic_cast<IntCell *>(pop(_s)); IntCell *a1 = dynamic_cast<IntCell *>(pop(_s));
assert(a1);
IntCell *a2 = dynamic_cast<IntCell *>(pop(_s)); IntCell *a2 = dynamic_cast<IntCell *>(pop(_s));
assert(a2);
push(_s, makeCell<IntCell>(a1->_val + a2->_val)); push(_s, makeCell<IntCell>(a1->_val + a2->_val));
break; break;
} }
case CommandCell::CommandNum::SUB: { case CommandCell::CommandNum::SUB: {
break; break;
} }
case CommandCell::CommandNum::CONS: {
Cell *a1 = pop(_s);
Cell *a2 = pop(_s);
push(_s, cons(a1, a2));
break;
}
case CommandCell::CommandNum::READCHAR: { case CommandCell::CommandNum::READCHAR: {
char c; char c;
_instream >> c; _instream >> c;
@@ -127,9 +171,16 @@ void VM::step() {
} }
case CommandCell::CommandNum::PUTCHAR: { case CommandCell::CommandNum::PUTCHAR: {
IntCell *popped2 = dynamic_cast<IntCell *>(pop(_s)); IntCell *popped2 = dynamic_cast<IntCell *>(pop(_s));
assert(popped2);
_outstream << (char) popped2->_val; _outstream << (char) popped2->_val;
break; break;
} }
case CommandCell::CommandNum::PUTNUM: {
IntCell *popped2 = dynamic_cast<IntCell *>(pop(_s));
assert(popped2);
_outstream << popped2->_val;
break;
}
case CommandCell::CommandNum::END: { case CommandCell::CommandNum::END: {
assert(false); assert(false);
break; break;
@@ -140,9 +191,4 @@ void VM::step() {
} }
VM::VM(std::istream &instream, std::ostream &outstream) : _instream(instream), _outstream(outstream) { VM::VM(std::istream &instream, std::ostream &outstream) : _instream(instream), _outstream(outstream) {}
_s = dynamic_cast<ConsCell *>(makeCell<ConsCell>(nullptr));
_e = dynamic_cast<ConsCell *>(makeCell<ConsCell>(nullptr));
_c = dynamic_cast<ConsCell *>(makeCell<ConsCell>(nullptr));
_d = dynamic_cast<ConsCell *>(makeCell<ConsCell>(nullptr));
}

View File

@@ -92,4 +92,150 @@ TEST(VMTest, SimpleFunction) {
ssout.flush(); ssout.flush();
EXPECT_EQ(ssout.str(), "3"); EXPECT_EQ(ssout.str(), "3");
}
TEST(VMTest, RecursiveFunction) {
std::stringstream ssin;
std::stringstream ssout;
{
VM vm(ssin, ssout);
vm.appendCommand(vm.makeCell<CommandCell>(CommandCell::CommandNum::STOP));
vm.appendCommand(vm.makeCell<CommandCell>(CommandCell::CommandNum::RAP));
// Fib function
ConsCell *fibfn = vm.makeCell<ConsCell>(vm.makeCell<CommandCell>(CommandCell::CommandNum::RET));
// 0 case
ConsCell *zcase = vm.makeCell<ConsCell>(vm.makeCell<CommandCell>(CommandCell::CommandNum::JOIN));
vm.push(zcase, vm.makeCell<IntCell>(0));
vm.push(zcase, vm.makeCell<CommandCell>(CommandCell::CommandNum::LDC));
// 1 case
ConsCell *ocase = vm.makeCell<ConsCell>(vm.makeCell<CommandCell>(CommandCell::CommandNum::JOIN));
vm.push(ocase, vm.makeCell<IntCell>(1));
vm.push(ocase, vm.makeCell<CommandCell>(CommandCell::CommandNum::LDC));
// >1 case
ConsCell *gocase = vm.makeCell<ConsCell>(vm.makeCell<CommandCell>(CommandCell::CommandNum::JOIN));
vm.push(gocase, vm.makeCell<CommandCell>(CommandCell::CommandNum::ADD));
vm.push(gocase, vm.makeCell<CommandCell>(CommandCell::CommandNum::AP));
vm.push(gocase, vm.makeCell<ConsCell>(vm.makeCell<IntCell>(2), vm.makeCell<IntCell>(1)));
vm.push(gocase, vm.makeCell<CommandCell>(CommandCell::CommandNum::LD));
vm.push(gocase, vm.makeCell<CommandCell>(CommandCell::CommandNum::CONS));
vm.push(gocase, vm.makeCell<CommandCell>(CommandCell::CommandNum::ADD));
vm.push(gocase, vm.makeCell<IntCell>(-2));
vm.push(gocase, vm.makeCell<CommandCell>(CommandCell::CommandNum::LDC));
vm.push(gocase, vm.makeCell<ConsCell>(vm.makeCell<IntCell>(1), vm.makeCell<IntCell>(1)));
vm.push(gocase, vm.makeCell<CommandCell>(CommandCell::CommandNum::LD));
vm.push(gocase, vm.makeCell<CommandCell>(CommandCell::CommandNum::NIL));
vm.push(gocase, vm.makeCell<CommandCell>(CommandCell::CommandNum::AP));
vm.push(gocase, vm.makeCell<ConsCell>(vm.makeCell<IntCell>(2), vm.makeCell<IntCell>(1)));
vm.push(gocase, vm.makeCell<CommandCell>(CommandCell::CommandNum::LD));
vm.push(gocase, vm.makeCell<CommandCell>(CommandCell::CommandNum::CONS));
vm.push(gocase, vm.makeCell<CommandCell>(CommandCell::CommandNum::ADD));
vm.push(gocase, vm.makeCell<IntCell>(-1));
vm.push(gocase, vm.makeCell<CommandCell>(CommandCell::CommandNum::LDC));
vm.push(gocase, vm.makeCell<ConsCell>(vm.makeCell<IntCell>(1), vm.makeCell<IntCell>(1)));
vm.push(gocase, vm.makeCell<CommandCell>(CommandCell::CommandNum::LD));
vm.push(gocase, vm.makeCell<CommandCell>(CommandCell::CommandNum::NIL));
// >=1 case
ConsCell *geocase = vm.makeCell<ConsCell>(vm.makeCell<CommandCell>(CommandCell::CommandNum::JOIN));
vm.push(geocase, ocase);
vm.push(geocase, gocase);
vm.push(geocase, vm.makeCell<CommandCell>(CommandCell::CommandNum::SEL));
vm.push(geocase, vm.makeCell<CommandCell>(CommandCell::CommandNum::ADD));
vm.push(geocase, vm.makeCell<IntCell>(-1));
vm.push(geocase, vm.makeCell<CommandCell>(CommandCell::CommandNum::LDC));
vm.push(geocase, vm.makeCell<ConsCell>(vm.makeCell<IntCell>(1), vm.makeCell<IntCell>(1)));
vm.push(geocase, vm.makeCell<CommandCell>(CommandCell::CommandNum::LD));
vm.push(fibfn, zcase);
vm.push(fibfn, geocase);
vm.push(fibfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::SEL));
vm.push(fibfn, vm.makeCell<ConsCell>(vm.makeCell<IntCell>(1), vm.makeCell<IntCell>(1)));
vm.push(fibfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::LD));
// Fib caller function
ConsCell *fibcallfn = vm.makeCell<ConsCell>(vm.makeCell<CommandCell>(CommandCell::CommandNum::RET));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::PUTNUM));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::PUTCHAR));
vm.push(fibcallfn, vm.makeCell<IntCell>(' '));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::LDC));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::AP));
vm.push(fibcallfn, vm.makeCell<ConsCell>(vm.makeCell<IntCell>(1), vm.makeCell<IntCell>(1)));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::LD));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::CONS));
vm.push(fibcallfn, vm.makeCell<IntCell>(20));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::LDC));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::NIL));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::PUTCHAR));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::ADD));
vm.push(fibcallfn, vm.makeCell<IntCell>('0'));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::LDC));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::AP));
vm.push(fibcallfn, vm.makeCell<ConsCell>(vm.makeCell<IntCell>(1), vm.makeCell<IntCell>(1)));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::LD));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::CONS));
vm.push(fibcallfn, vm.makeCell<IntCell>(6));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::LDC));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::NIL));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::PUTCHAR));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::ADD));
vm.push(fibcallfn, vm.makeCell<IntCell>('0'));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::LDC));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::AP));
vm.push(fibcallfn, vm.makeCell<ConsCell>(vm.makeCell<IntCell>(1), vm.makeCell<IntCell>(1)));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::LD));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::CONS));
vm.push(fibcallfn, vm.makeCell<IntCell>(5));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::LDC));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::NIL));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::PUTCHAR));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::ADD));
vm.push(fibcallfn, vm.makeCell<IntCell>('0'));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::LDC));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::AP));
vm.push(fibcallfn, vm.makeCell<ConsCell>(vm.makeCell<IntCell>(1), vm.makeCell<IntCell>(1)));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::LD));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::CONS));
vm.push(fibcallfn, vm.makeCell<IntCell>(4));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::LDC));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::NIL));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::PUTCHAR));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::ADD));
vm.push(fibcallfn, vm.makeCell<IntCell>('0'));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::LDC));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::AP));
vm.push(fibcallfn, vm.makeCell<ConsCell>(vm.makeCell<IntCell>(1), vm.makeCell<IntCell>(1)));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::LD));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::CONS));
vm.push(fibcallfn, vm.makeCell<IntCell>(3));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::LDC));
vm.push(fibcallfn, vm.makeCell<CommandCell>(CommandCell::CommandNum::NIL));
vm.appendCommand(fibcallfn);
vm.appendCommand(vm.makeCell<CommandCell>(CommandCell::CommandNum::LDF));
vm.appendCommand(vm.makeCell<CommandCell>(CommandCell::CommandNum::CONS));
vm.appendCommand(fibfn);
vm.appendCommand(vm.makeCell<CommandCell>(CommandCell::CommandNum::LDF));
vm.appendCommand(vm.makeCell<CommandCell>(CommandCell::CommandNum::NIL));
vm.appendCommand(vm.makeCell<CommandCell>(CommandCell::CommandNum::DUM));
vm.run();
}
ssout.flush();
EXPECT_EQ(ssout.str(), "2358 6765");
} }