#include #include "VM.h" TEST(VMTest, BasicHello) { 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('h')); vm.appendCommand(vm.makeCell(CommandCell::CommandNum::LDC)); vm.appendCommand(vm.makeCell(CommandCell::CommandNum::NIL)); vm.run(); } ssout.flush(); EXPECT_EQ(ssout.str(), "h"); } TEST(VMTest, SelTest) { std::stringstream ssin; std::stringstream ssout; { VM vm(ssin, ssout); vm.appendCommand(vm.makeCell(CommandCell::CommandNum::STOP)); // True branch true test ConsCell *tbtt = vm.makeCell(vm.makeCell(CommandCell::CommandNum::JOIN)); vm.push(tbtt, vm.makeCell(CommandCell::CommandNum::PUTCHAR)); vm.push(tbtt, vm.makeCell('1')); vm.push(tbtt, vm.makeCell(CommandCell::CommandNum::LDC)); // False branch true test ConsCell *fbtt = vm.makeCell(vm.makeCell(CommandCell::CommandNum::JOIN)); vm.push(fbtt, vm.makeCell(CommandCell::CommandNum::PUTCHAR)); vm.push(fbtt, vm.makeCell('2')); vm.push(fbtt, vm.makeCell(CommandCell::CommandNum::LDC)); // True branch false test ConsCell *tbft = vm.makeCell(vm.makeCell(CommandCell::CommandNum::JOIN)); vm.push(tbft, vm.makeCell(CommandCell::CommandNum::PUTCHAR)); vm.push(tbft, vm.makeCell('3')); vm.push(tbft, vm.makeCell(CommandCell::CommandNum::LDC)); // False branch false test ConsCell *fbft = vm.makeCell(vm.makeCell(CommandCell::CommandNum::JOIN)); vm.push(fbft, vm.makeCell(CommandCell::CommandNum::PUTCHAR)); vm.push(fbft, vm.makeCell('4')); vm.push(fbft, vm.makeCell(CommandCell::CommandNum::LDC)); vm.appendCommand(fbft); vm.appendCommand(tbft); vm.appendCommand(vm.makeCell(CommandCell::CommandNum::SEL)); vm.appendCommand(vm.makeCell(0)); vm.appendCommand(vm.makeCell(CommandCell::CommandNum::LDC)); vm.appendCommand(fbtt); vm.appendCommand(tbtt); vm.appendCommand(vm.makeCell(CommandCell::CommandNum::SEL)); vm.appendCommand(vm.makeCell(1)); vm.appendCommand(vm.makeCell(CommandCell::CommandNum::LDC)); vm.run(); } 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"); } TEST(VMTest, RecursiveFunction) { std::stringstream ssin; std::stringstream ssout; { VM vm(ssin, ssout); vm.appendCommand(vm.makeCell(CommandCell::CommandNum::STOP)); vm.appendCommand(vm.makeCell(CommandCell::CommandNum::RAP)); // Fib function ConsCell *fibfn = vm.makeCell(vm.makeCell(CommandCell::CommandNum::RET)); // 0 case ConsCell *zcase = vm.makeCell(vm.makeCell(CommandCell::CommandNum::JOIN)); vm.push(zcase, vm.makeCell(0)); vm.push(zcase, vm.makeCell(CommandCell::CommandNum::LDC)); // 1 case ConsCell *ocase = vm.makeCell(vm.makeCell(CommandCell::CommandNum::JOIN)); vm.push(ocase, vm.makeCell(1)); vm.push(ocase, vm.makeCell(CommandCell::CommandNum::LDC)); // >1 case ConsCell *gocase = vm.makeCell(vm.makeCell(CommandCell::CommandNum::JOIN)); vm.push(gocase, vm.makeCell(CommandCell::CommandNum::ADD)); vm.push(gocase, vm.makeCell(CommandCell::CommandNum::AP)); vm.push(gocase, vm.makeCell(vm.makeCell(2), vm.makeCell(1))); vm.push(gocase, vm.makeCell(CommandCell::CommandNum::LD)); vm.push(gocase, vm.makeCell(CommandCell::CommandNum::CONS)); vm.push(gocase, vm.makeCell(CommandCell::CommandNum::ADD)); vm.push(gocase, vm.makeCell(-2)); vm.push(gocase, vm.makeCell(CommandCell::CommandNum::LDC)); vm.push(gocase, vm.makeCell(vm.makeCell(1), vm.makeCell(1))); vm.push(gocase, vm.makeCell(CommandCell::CommandNum::LD)); vm.push(gocase, vm.makeCell(CommandCell::CommandNum::NIL)); vm.push(gocase, vm.makeCell(CommandCell::CommandNum::AP)); vm.push(gocase, vm.makeCell(vm.makeCell(2), vm.makeCell(1))); vm.push(gocase, vm.makeCell(CommandCell::CommandNum::LD)); vm.push(gocase, vm.makeCell(CommandCell::CommandNum::CONS)); vm.push(gocase, vm.makeCell(CommandCell::CommandNum::ADD)); vm.push(gocase, vm.makeCell(-1)); vm.push(gocase, vm.makeCell(CommandCell::CommandNum::LDC)); vm.push(gocase, vm.makeCell(vm.makeCell(1), vm.makeCell(1))); vm.push(gocase, vm.makeCell(CommandCell::CommandNum::LD)); vm.push(gocase, vm.makeCell(CommandCell::CommandNum::NIL)); // >=1 case ConsCell *geocase = vm.makeCell(vm.makeCell(CommandCell::CommandNum::JOIN)); vm.push(geocase, ocase); vm.push(geocase, gocase); vm.push(geocase, vm.makeCell(CommandCell::CommandNum::SEL)); vm.push(geocase, vm.makeCell(CommandCell::CommandNum::ADD)); vm.push(geocase, vm.makeCell(-1)); vm.push(geocase, vm.makeCell(CommandCell::CommandNum::LDC)); vm.push(geocase, vm.makeCell(vm.makeCell(1), vm.makeCell(1))); vm.push(geocase, vm.makeCell(CommandCell::CommandNum::LD)); vm.push(fibfn, zcase); vm.push(fibfn, geocase); vm.push(fibfn, vm.makeCell(CommandCell::CommandNum::SEL)); vm.push(fibfn, vm.makeCell(vm.makeCell(1), vm.makeCell(1))); vm.push(fibfn, vm.makeCell(CommandCell::CommandNum::LD)); // Fib caller function ConsCell *fibcallfn = vm.makeCell(vm.makeCell(CommandCell::CommandNum::RET)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::PUTNUM)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::PUTCHAR)); vm.push(fibcallfn, vm.makeCell(' ')); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::LDC)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::AP)); vm.push(fibcallfn, vm.makeCell(vm.makeCell(1), vm.makeCell(1))); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::LD)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::CONS)); vm.push(fibcallfn, vm.makeCell(10)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::LDC)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::NIL)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::PUTCHAR)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::ADD)); vm.push(fibcallfn, vm.makeCell('0')); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::LDC)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::AP)); vm.push(fibcallfn, vm.makeCell(vm.makeCell(1), vm.makeCell(1))); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::LD)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::CONS)); vm.push(fibcallfn, vm.makeCell(6)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::LDC)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::NIL)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::PUTCHAR)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::ADD)); vm.push(fibcallfn, vm.makeCell('0')); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::LDC)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::AP)); vm.push(fibcallfn, vm.makeCell(vm.makeCell(1), vm.makeCell(1))); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::LD)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::CONS)); vm.push(fibcallfn, vm.makeCell(5)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::LDC)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::NIL)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::PUTCHAR)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::ADD)); vm.push(fibcallfn, vm.makeCell('0')); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::LDC)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::AP)); vm.push(fibcallfn, vm.makeCell(vm.makeCell(1), vm.makeCell(1))); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::LD)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::CONS)); vm.push(fibcallfn, vm.makeCell(4)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::LDC)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::NIL)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::PUTCHAR)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::ADD)); vm.push(fibcallfn, vm.makeCell('0')); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::LDC)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::AP)); vm.push(fibcallfn, vm.makeCell(vm.makeCell(1), vm.makeCell(1))); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::LD)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::CONS)); vm.push(fibcallfn, vm.makeCell(3)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::LDC)); vm.push(fibcallfn, vm.makeCell(CommandCell::CommandNum::NIL)); vm.appendCommand(fibcallfn); vm.appendCommand(vm.makeCell(CommandCell::CommandNum::LDF)); vm.appendCommand(vm.makeCell(CommandCell::CommandNum::CONS)); vm.appendCommand(fibfn); vm.appendCommand(vm.makeCell(CommandCell::CommandNum::LDF)); vm.appendCommand(vm.makeCell(CommandCell::CommandNum::NIL)); vm.appendCommand(vm.makeCell(CommandCell::CommandNum::DUM)); vm.run(); } ssout.flush(); EXPECT_EQ(ssout.str(), "2358 55"); }