mirror of
https://github.com/usatiuk/psil.git
synced 2025-10-28 18:57:48 +01:00
better commands
This commit is contained in:
35
src/main.cpp
35
src/main.cpp
@@ -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
49
src/vm/include/Command.h
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user