better commands

This commit is contained in:
2024-01-03 15:47:37 +01:00
parent 33a9939b37
commit d7805aa7e7
6 changed files with 130 additions and 87 deletions

View File

@@ -4,21 +4,28 @@
#include "Parser.h"
#include "VM.h"
int main() {
Handle repl;
{
Parser parser;
parser.loadStr("(READ EVAL PRINT STOP)");
repl = parser.parseExpr();
}
while (true) {
int main(int argc, char *argv[]) {
try {
Handle repl;
{
Parser parser;
parser.loadStr("(READ EVAL PRINT STOP)");
repl = parser.parseExpr();
}
VM vm;
std::cout << std::endl;
vm.loadControl(repl);
vm.run();
std::cout << std::endl;
}
while (true) {
std::cout << std::endl;
vm.loadControl(repl);
vm.run();
std::cout << std::endl;
}
} catch (const std::exception &e) {
std::cerr << "\nUncaught exception: " << e.what() << std::endl;
return -1;
} catch (...) {
std::cerr << "Crash!" << std::endl;
return -1;
}
return 0;
}

49
src/vm/include/Command.h Normal file
View File

@@ -0,0 +1,49 @@
//
// Created by stepus53 on 3.1.24.
//
#ifndef PSIL_COMMAND_H
#define PSIL_COMMAND_H
#include <unordered_map>
#include "Cell.h"
namespace Command {
enum Command : CellValType {
NIL = 1,
LDC = 2,
LD = 3,
SEL = 4,
JOIN = 5,
LDF = 6,
AP = 7,
RET = 8,
DUM = 9,
RAP = 10,
STOP = 11,
ATOM = 12,
ADD = 13,
SUB = 14,
READCHAR = 15,
PUTCHAR = 16,
PUTNUM = 17,
EVAL = 18,
PRINT = 19,
READ = 20,
CONS = 21,
};
static inline std::unordered_map<std::string_view, CellValType> str_to_cmd{
{"NIL", 1}, {"LDC", 2}, {"LD", 3}, {"SEL", 4}, {"JOIN", 5}, {"LDF", 6}, {"AP", 7},
{"RET", 8}, {"DUM", 9}, {"RAP", 10}, {"STOP", 11}, {"ATOM", 12}, {"ADD", 13}, {"SUB", 14},
{"READCHAR", 15}, {"PUTCHAR", 16}, {"PUTNUM", 17}, {"EVAL", 18}, {"PRINT", 19}, {"READ", 20}, {"CONS", 21},
};
};// namespace Command
#endif//PSIL_COMMAND_H

View File

@@ -19,7 +19,10 @@ public:
void run();
void loadControl(const Handle &h) { _c = h; }
void loadControl(const Handle &h) {
_c = h;
_stop = false;
}
void step();
@@ -32,32 +35,6 @@ private:
std::istream &_instream;
std::ostream &_outstream;
Handle NIL = Handle::makeStrCell("NIL");
Handle LDC = Handle::makeStrCell("LDC");
Handle LD = Handle::makeStrCell("LD");
Handle SEL = Handle::makeStrCell("SEL");
Handle JOIN = Handle::makeStrCell("JOIN");
Handle LDF = Handle::makeStrCell("LDF");
Handle AP = Handle::makeStrCell("AP");
Handle RET = Handle::makeStrCell("RET");
Handle DUM = Handle::makeStrCell("DUM");
Handle RAP = Handle::makeStrCell("RAP");
Handle STOP = Handle::makeStrCell("STOP");
Handle ATOM = Handle::makeStrCell("ATOM");
Handle ADD = Handle::makeStrCell("ADD");
Handle SUB = Handle::makeStrCell("SUB");
Handle READCHAR = Handle::makeStrCell("READCHAR");
Handle PUTCHAR = Handle::makeStrCell("PUTCHAR");
Handle PUTNUM = Handle::makeStrCell("PUTNUM");
Handle EVAL = Handle::makeStrCell("EVAL");
Handle PRINT = Handle::makeStrCell("PRINT");
Handle READ = Handle::makeStrCell("READ");
Handle CONS = Handle::makeStrCell("CONS");
};
#endif//PSIL_VM_H

View File

@@ -4,9 +4,13 @@
#include "Compiler.h"
#include "Command.h"
#include <functional>
#include <string>
using namespace Command;
Handle Compiler::compile(Handle src, Handle fake_env, Handle suffix) {
Handle out;
@@ -21,10 +25,10 @@ Handle Compiler::compile(Handle src, Handle fake_env, Handle suffix) {
std::function<Handle(Handle, Handle)> compileArgsList = [&](Handle args, Handle env) {
Handle out;
out.append(Handle("NIL"));
out.append(Handle(NIL));
while (!args.null()) {
out.splice(compile(args.car(), env));
out.append(Handle("CONS"));
out.append(Handle(CONS));
args = args.cdr();
}
return out;
@@ -33,18 +37,18 @@ Handle Compiler::compile(Handle src, Handle fake_env, Handle suffix) {
Handle expr = src;
if (expr.null()) {
out.append(Handle("NIL"));
out.append(Handle(NIL));
} else if (expr.atom()) {
if (expr.type() == CellType::NUMATOM) {
out.append(Handle("LDC"));
out.append(Handle(LDC));
out.append(expr);
} else if (expr.type() == CellType::STRATOM) {
Handle idx = findIndex(expr, fake_env);
if (idx == nullptr) {
out.append(Handle("LDC"));
out.append(Handle(LDC));
out.append(expr);
} else {
out.append(Handle("LD"));
out.append(Handle(LD));
out.append(idx);
}
}
@@ -54,17 +58,17 @@ Handle Compiler::compile(Handle src, Handle fake_env, Handle suffix) {
if (car.atom()) {
if (car.strval() == "+") {
out.splice(compileArgsRaw(cdr));
out.append(Handle("ADD"));
out.append(Handle(ADD));
} else if (car.strval() == "read") {
out.append(Handle("READ"));
out.append(Handle(READ));
} else if (car.strval() == "lambda") {
out.append(Handle("LDF"));
out.append(compile(cdr.cdr().car(), Handle::cons(cdr.car(), fake_env), Handle("RET")));
out.append(Handle(LDF));
out.append(compile(cdr.cdr().car(), Handle::cons(cdr.car(), fake_env), Handle(RET)));
} else if (car.strval() == "if") {
out.splice(compile(cdr.car(), fake_env));
out.append(Handle("SEL"));
out.append(compile(cdr.cdr().car(), fake_env, Handle("JOIN")));
out.append(compile(cdr.cdr().cdr().car(), fake_env, Handle("JOIN")));
out.append(Handle(SEL));
out.append(compile(cdr.cdr().car(), fake_env, Handle(JOIN)));
out.append(compile(cdr.cdr().cdr().car(), fake_env, Handle(JOIN)));
} else if (car.strval() == "let" || car.strval() == "letrec") {
std::vector<std::pair<Handle, Handle>> argBody;
@@ -85,26 +89,26 @@ Handle Compiler::compile(Handle src, Handle fake_env, Handle suffix) {
Handle newenv = Handle::cons(argNames, fake_env);
if (car.strval() == "let") out.splice(compileArgsList(argBodies, fake_env));
else if (car.strval() == "letrec") {
out.append(Handle("DUM"));
out.append(Handle(DUM));
out.splice(compileArgsList(argBodies, newenv));
}
out.append(Handle("LDF"));
out.append(compile(body, newenv, Handle("RET")));
if (car.strval() == "let") out.append(Handle("AP"));
out.append(Handle(LDF));
out.append(compile(body, newenv, Handle(RET)));
if (car.strval() == "let") out.append(Handle(AP));
else
out.append(Handle("RAP"));
out.append(Handle(RAP));
} else {
out.splice(compileArgsList(cdr, fake_env));
out.append(Handle("LD"));
out.append(Handle(LD));
Handle idx = findIndex(car, fake_env);
out.append(idx);
out.append(Handle("AP"));
out.append(Handle(AP));
}
} else {
out.splice(compileArgsList(cdr, fake_env));
out.splice(compile(car, fake_env, Handle("AP")));
out.splice(compile(car, fake_env, Handle(AP)));
}
}
out.splice(suffix);

View File

@@ -6,10 +6,12 @@
#include <set>
#include <utility>
#include "Command.h"
#include "Compiler.h"
#include "Parser.h"
#include "VM.h"
using namespace Command;
VM::VM(std::istream &instream, std::ostream &outstream) : _instream(instream), _outstream(outstream) {}
@@ -19,13 +21,15 @@ void VM::run() {
void VM::step() {
Handle poppedH = _c.pop();
if (poppedH == NIL) {
// as to not complicate parser for tests...
CellValType poppedCmd = poppedH.type() == CellType::STRATOM ? str_to_cmd.at(poppedH.strval()) : poppedH.val();
if (poppedCmd == NIL) {
_s.push(nullptr);
} else if (poppedH == LDC) {
} else if (poppedCmd == LDC) {
_s.push(_c.pop());
} else if (poppedH == ATOM) {
} else if (poppedCmd == ATOM) {
_s.push(_c.pop().atom() ? 1 : 0);
} else if (poppedH == LD) {
} else if (poppedCmd == LD) {
Handle poppedH2 = _c.pop();
int64_t frame = poppedH2.car().val();
@@ -43,7 +47,7 @@ void VM::step() {
for (int i = 1; i < arg; i++) { curArg = curArg.cdr(); }
_s.push(curArg.car());
} else if (poppedH == SEL) {
} else if (poppedCmd == SEL) {
Handle popped2H = _s.pop();
Handle ct = _c.pop();
@@ -55,11 +59,11 @@ void VM::step() {
} else {
_c = cf;
}
} else if (poppedH == JOIN) {
} else if (poppedCmd == JOIN) {
_c = _d.pop();
} else if (poppedH == LDF) {
} else if (poppedCmd == LDF) {
_s.push(Handle::cons(_c.pop(), _e));
} else if (poppedH == AP) {
} else if (poppedCmd == AP) {
Handle closureH = _s.pop();
Handle argsH = _s.pop();
@@ -71,7 +75,7 @@ void VM::step() {
_c = closureH.car();
_e = closureH.cdr();
_e.push(argsH);
} else if (poppedH == RET) {
} else if (poppedCmd == RET) {
Handle c = _d.pop();
Handle e = _d.pop();
Handle s = _d.pop();
@@ -83,9 +87,9 @@ void VM::step() {
_s = s;
_s.push(ret);
} else if (poppedH == DUM) {
} else if (poppedCmd == DUM) {
_e.push(nullptr);
} else if (poppedH == RAP) {
} else if (poppedCmd == RAP) {
Handle closureH = _s.pop();
Handle argsH = _s.pop();
@@ -104,26 +108,26 @@ void VM::step() {
_e.push(argsH);
fnEnv.setcar(argsH);
} else if (poppedH == STOP) {
} else if (poppedCmd == STOP) {
_stop = true;
} else if (poppedH == ADD) {
} else if (poppedCmd == ADD) {
_s.push(_s.pop().val() + _s.pop().val());
} else if (poppedH == SUB) {
} else if (poppedCmd == SUB) {
assert(false);
} else if (poppedH == CONS) {
} else if (poppedCmd == CONS) {
Handle h1 = _s.pop();
Handle h2 = _s.pop();
_s.push(Handle::cons(h1, h2));
} else if (poppedH == READCHAR) {
} else if (poppedCmd == READCHAR) {
char c;
_instream >> c;
_s.push(Handle::makeNumCell(c));
} else if (poppedH == PUTCHAR) {
} else if (poppedCmd == PUTCHAR) {
_outstream << (char) _s.pop().val();
} else if (poppedH == PUTNUM) {
} else if (poppedCmd == PUTNUM) {
_outstream << _s.pop().val();
} else if (poppedH == EVAL) {
} else if (poppedCmd == EVAL) {
Handle code = _s.pop();
Handle newc = Compiler::compile(code, nullptr);
Logger::log(
@@ -136,9 +140,9 @@ void VM::step() {
Logger::DEBUG);
newc.splice(_c);
_c = newc;
} else if (poppedH == PRINT) {
} else if (poppedCmd == PRINT) {
_outstream << _s.pop();
} else if (poppedH == READ) {
} else if (poppedCmd == READ) {
std::string read;
std::getline(_instream, read);
Parser parser;

View File

@@ -1,7 +1,9 @@
#include <gtest/gtest.h>
#include "Command.h"
#include "VM.h"
using namespace Command;
TEST(VMTest, BasicHello) {
std::stringstream ssin;
std::stringstream ssout;
@@ -9,11 +11,11 @@ TEST(VMTest, BasicHello) {
VM vm(ssin, ssout);
Handle newc(Handle::cons(nullptr, nullptr));
newc.append(Handle::makeStrCell("NIL"));
newc.append(Handle::makeStrCell("LDC"));
newc.append(Handle::makeNumCell(NIL));
newc.append(Handle::makeNumCell(LDC));
newc.append(Handle::makeNumCell('h'));
newc.append(Handle::makeStrCell("PUTCHAR"));
newc.append(Handle::makeStrCell("STOP"));
newc.append(Handle::makeNumCell(PUTCHAR));
newc.append(Handle::makeNumCell(STOP));
vm.loadControl(newc);
vm.run();
}