diff --git a/src/vm/src/VM.cpp b/src/vm/src/VM.cpp index c7f6eed..664caeb 100644 --- a/src/vm/src/VM.cpp +++ b/src/vm/src/VM.cpp @@ -20,8 +20,7 @@ void VM::step() { break; } case CommandCell::CommandNum::LDC: { - IntCell *popped2 = dynamic_cast(pop(_c)); - push(_s, popped2); + push(_s, pop(_c)); break; } case CommandCell::CommandNum::LD: { @@ -29,7 +28,22 @@ void VM::step() { int64_t frame = dynamic_cast(popped2->_car)->_val; int64_t arg = dynamic_cast(popped2->_cdr)->_val; - // todo + + assert(frame > 0); + assert(arg > 0); + + ConsCell *curFrame = _e; + + for (int i = 1; i < frame; i++) { + curFrame = dynamic_cast(_e->_cdr); + } + + ConsCell *curArg = dynamic_cast(curFrame->_car); + for (int i = 1; i < arg; i++) { + curArg = dynamic_cast(curArg->_cdr); + } + + push(_s, curArg->_car); break; } @@ -53,12 +67,37 @@ void VM::step() { break; } case CommandCell::CommandNum::LDF: { + ConsCell *fn = dynamic_cast(pop(_c)); + push(_s, makeCell(fn, _e)); break; } case CommandCell::CommandNum::AP: { + ConsCell *closure = dynamic_cast(pop(_s)); + ConsCell *args = dynamic_cast(pop(_s)); + + push(_d, _s); + push(_d, _e); + push(_d, _c); + + _s = makeCell(); + _c = dynamic_cast(closure->_car); + _e = dynamic_cast(closure->_cdr); + push(_e, args); break; } case CommandCell::CommandNum::RET: { + ConsCell *c = dynamic_cast(pop(_d)); + ConsCell *e = dynamic_cast(pop(_d)); + ConsCell *s = dynamic_cast(pop(_d)); + + Cell *ret = pop(_s); + + _c = c; + _e = e; + _s = s; + + push(_s, ret); + break; } case CommandCell::CommandNum::DUM: { @@ -72,23 +111,31 @@ void VM::step() { break; } case CommandCell::CommandNum::ADD: { + IntCell *a1 = dynamic_cast(pop(_s)); + IntCell *a2 = dynamic_cast(pop(_s)); + push(_s, makeCell(a1->_val + a2->_val)); break; } case CommandCell::CommandNum::SUB: { break; } - case CommandCell::CommandNum::END: { - break; - } - case CommandCell::CommandNum::READCHAR: + case CommandCell::CommandNum::READCHAR: { char c; _instream >> c; push(_s, makeCell(c)); break; - case CommandCell::CommandNum::PUTCHAR: + } + case CommandCell::CommandNum::PUTCHAR: { IntCell *popped2 = dynamic_cast(pop(_s)); _outstream << (char) popped2->_val; break; + } + case CommandCell::CommandNum::END: { + assert(false); + break; + } + default: + assert(false); } } diff --git a/test/vm/VMTest.cpp b/test/vm/VMTest.cpp index c517376..442847f 100644 --- a/test/vm/VMTest.cpp +++ b/test/vm/VMTest.cpp @@ -63,4 +63,33 @@ TEST(VMTest, SelTest) { } ssout.flush(); EXPECT_EQ(ssout.str(), "14"); +} + +TEST(VMTest, SimpleFunction) { + std::stringstream ssin; + std::stringstream ssout; + { + VM vm(ssin, ssout); + vm.appendCommand(vm.makeCell(CommandCell::CommandNum::STOP)); + vm.appendCommand(vm.makeCell(CommandCell::CommandNum::PUTCHAR)); + + vm.appendCommand(vm.makeCell(CommandCell::CommandNum::AP)); + + // Add function + ConsCell *addfn = vm.makeCell(vm.makeCell(CommandCell::CommandNum::RET)); + vm.push(addfn, vm.makeCell(CommandCell::CommandNum::ADD)); + vm.push(addfn, vm.makeCell(vm.makeCell(1), vm.makeCell(2))); + vm.push(addfn, vm.makeCell(CommandCell::CommandNum::LD)); + vm.push(addfn, vm.makeCell(vm.makeCell(1), vm.makeCell(1))); + vm.push(addfn, vm.makeCell(CommandCell::CommandNum::LD)); + vm.appendCommand(addfn); + vm.appendCommand(vm.makeCell(CommandCell::CommandNum::LDF)); + vm.appendCommand( + vm.makeCell(vm.makeCell(1), vm.makeCell(vm.makeCell('2')))); + vm.appendCommand(vm.makeCell(CommandCell::CommandNum::LDC)); + vm.run(); + } + ssout.flush(); + EXPECT_EQ(ssout.str(), "3"); + } \ No newline at end of file