mirror of
https://github.com/usatiuk/psil.git
synced 2025-10-29 03:07:49 +01:00
almost working something
This commit is contained in:
21
clitests/coffee.psil
Normal file
21
clitests/coffee.psil
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
(define (getmax a b)
|
||||||
|
(if (> a b) a b)
|
||||||
|
)
|
||||||
|
|
||||||
|
(define (coffee-shop-impl times last cur max)
|
||||||
|
(if (= times (nil))
|
||||||
|
(getmax cur max)
|
||||||
|
(if (= last (car times))
|
||||||
|
(coffee-shop-impl (cdr times) last (+ cur 1) max)
|
||||||
|
(coffee-shop-impl (cdr times) (car times) 1 (getmax cur max))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(define (coffee-shop times)
|
||||||
|
(coffee-shop-impl times (nil) 0 0)
|
||||||
|
)
|
||||||
|
|
||||||
|
(coffee-shop (nil))
|
||||||
|
(coffee-shop (quote( (8 0) (8 10) (8 10) (8 45) )))
|
||||||
|
(coffee-shop (quote( (8 12) (10 11) (10 11) (15 15) (15 15) (15 15) (22 22) (22 22) (22 59) )))
|
||||||
3
clitests/coffee.res
Normal file
3
clitests/coffee.res
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
0
|
||||||
|
2
|
||||||
|
3
|
||||||
@@ -20,6 +20,7 @@ for FILE in *.psil; do
|
|||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo "$FILE OK"
|
||||||
rm $FILE.res
|
rm $FILE.res
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
#include <set>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@@ -53,21 +54,59 @@ struct ConsCell : public Cell {
|
|||||||
std::atomic<Cell *> _car = nullptr;
|
std::atomic<Cell *> _car = nullptr;
|
||||||
std::atomic<Cell *> _cdr = nullptr;
|
std::atomic<Cell *> _cdr = nullptr;
|
||||||
|
|
||||||
void print(std::ostream &out) override {
|
void print_cons(std::ostream &out, std::set<Cell *> &seen) {
|
||||||
std::stringstream res;
|
std::stringstream res;
|
||||||
if (_car) {
|
if (_car) {
|
||||||
if (_car.load()->_type == CellType::CONS) {
|
if (_car.load()->_type == CellType::CONS) {
|
||||||
res << "(";
|
if (seen.find(_car) == seen.end()) {
|
||||||
_car.load()->print(res);
|
res << "(";
|
||||||
res << ")";
|
seen.emplace(_car.load());
|
||||||
|
dynamic_cast<ConsCell &>(*_car.load()).print_cons(res, seen);
|
||||||
|
res << ")";
|
||||||
|
} else {
|
||||||
|
res << "(recursive)";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
_car.load()->print(res);
|
_car.load()->print(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_cdr) {
|
if (_cdr) {
|
||||||
if (_cdr.load()->_type == CellType::CONS) {
|
if (_cdr.load()->_type == CellType::CONS) {
|
||||||
res << " ";
|
if (seen.find(_cdr) == seen.end()) {
|
||||||
|
res << " ";
|
||||||
|
seen.emplace(_cdr.load());
|
||||||
|
dynamic_cast<ConsCell &>(*_cdr.load()).print_cons(res, seen);
|
||||||
|
} else {
|
||||||
|
res << " recursive";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res << ".";
|
||||||
_cdr.load()->print(res);
|
_cdr.load()->print(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out << res.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void print(std::ostream &out) override {
|
||||||
|
std::stringstream res;
|
||||||
|
std::set<Cell *> seen;
|
||||||
|
if (_car) {
|
||||||
|
if (_car.load()->_type == CellType::CONS) {
|
||||||
|
res << "(";
|
||||||
|
seen.emplace(_car.load());
|
||||||
|
dynamic_cast<ConsCell &>(*_car.load()).print_cons(res, seen);
|
||||||
|
res << ")";
|
||||||
|
} else {
|
||||||
|
_car.load()->print(res);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res << "null ";
|
||||||
|
}
|
||||||
|
if (_cdr) {
|
||||||
|
if (_cdr.load()->_type == CellType::CONS) {
|
||||||
|
res << " ";
|
||||||
|
seen.emplace(_cdr.load());
|
||||||
|
dynamic_cast<ConsCell &>(*_cdr.load()).print_cons(res, seen);
|
||||||
} else {
|
} else {
|
||||||
res << ".";
|
res << ".";
|
||||||
_cdr.load()->print(res);
|
_cdr.load()->print(res);
|
||||||
|
|||||||
@@ -30,14 +30,15 @@ public:
|
|||||||
} else if (_target->_type == CellType::STRATOM) {
|
} else if (_target->_type == CellType::STRATOM) {
|
||||||
return dynamic_cast<StrAtomCell &>(*_target)._val == dynamic_cast<StrAtomCell &>(*rhs._target)._val;
|
return dynamic_cast<StrAtomCell &>(*_target)._val == dynamic_cast<StrAtomCell &>(*rhs._target)._val;
|
||||||
}
|
}
|
||||||
}
|
} else if (null() && rhs.null())
|
||||||
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Handle cons(const Handle &car, const Handle &cdr);
|
static Handle cons(const Handle &car, const Handle &cdr);
|
||||||
|
|
||||||
Handle car() { return dynamic_cast<ConsCell &>(*_target)._car.load(); }
|
Handle car() const { return dynamic_cast<ConsCell &>(*_target)._car.load(); }
|
||||||
Handle cdr() { return dynamic_cast<ConsCell &>(*_target)._cdr.load(); }
|
Handle cdr() const { return dynamic_cast<ConsCell &>(*_target)._cdr.load(); }
|
||||||
CellValType val() { return dynamic_cast<NumAtomCell &>(*_target)._val; }
|
CellValType val() { return dynamic_cast<NumAtomCell &>(*_target)._val; }
|
||||||
std::string_view strval() { return dynamic_cast<StrAtomCell &>(*_target)._val; }
|
std::string_view strval() { return dynamic_cast<StrAtomCell &>(*_target)._val; }
|
||||||
|
|
||||||
@@ -48,7 +49,7 @@ public:
|
|||||||
|
|
||||||
bool atom() const { return type() != CellType::CONS; }
|
bool atom() const { return type() != CellType::CONS; }
|
||||||
|
|
||||||
bool null() {
|
bool null() const {
|
||||||
if (!_target) return true;
|
if (!_target) return true;
|
||||||
if (type() == CellType::CONS && car() == nullptr && cdr() == nullptr) return true;
|
if (type() == CellType::CONS && car() == nullptr && cdr() == nullptr) return true;
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -4,37 +4,55 @@
|
|||||||
|
|
||||||
#include "Compiler.h"
|
#include "Compiler.h"
|
||||||
|
|
||||||
#include "Command.h"
|
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <stack>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "Command.h"
|
||||||
|
#include "Logger.h"
|
||||||
|
|
||||||
|
|
||||||
using namespace Command;
|
using namespace Command;
|
||||||
|
|
||||||
|
|
||||||
static std::unordered_map<std::string_view, CommandE> builtins{{"+", ADD}, {"-", SUB}, {"cons", CONS}, {"car", CAR},
|
static std::unordered_map<std::string_view, CommandE> builtins{{"+", ADD}, {"-", SUB}, {"cons", CONS}, {"car", CAR}, {"cdr", CDR},
|
||||||
{"cdr", CDR}, {"=", EQ}, {">", GT}, {"<", LT}};
|
{"=", EQ}, {">", GT}, {"<", LT}, {"nil", NIL}};
|
||||||
|
|
||||||
Handle Compiler::compile(const Handle &src, Handle fake_env, const Handle &suffix) {
|
Handle Compiler::compile(const Handle &src, Handle fake_env, const Handle &suffix) {
|
||||||
Handle out;
|
Handle out;
|
||||||
|
|
||||||
std::function<Handle(Handle)> compileArgsRaw = [&](Handle args) {
|
std::function<Handle(Handle)> compileArgsRaw = [&](Handle args) {
|
||||||
Handle out;
|
Handle out;
|
||||||
|
std::stack<Handle> rev;
|
||||||
while (!args.null()) {
|
while (!args.null()) {
|
||||||
out.splice(compile(args.car(), fake_env));
|
rev.push(args.car());
|
||||||
args = args.cdr();
|
args = args.cdr();
|
||||||
}
|
}
|
||||||
|
while (!rev.empty()) {
|
||||||
|
out.splice(compile(rev.top(), fake_env));
|
||||||
|
rev.pop();
|
||||||
|
}
|
||||||
return out;
|
return out;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::function<Handle(Handle, Handle)> compileArgsList = [&](Handle args, Handle env) {
|
std::function<Handle(Handle, Handle)> compileArgsList = [&](Handle args, Handle env) {
|
||||||
Handle out;
|
Handle out;
|
||||||
out.append(make_cmd(NIL));
|
out.append(make_cmd(NIL));
|
||||||
|
std::stack<Handle> rev;
|
||||||
while (!args.null()) {
|
while (!args.null()) {
|
||||||
out.splice(compile(args.car(), env));
|
rev.push(args.car());
|
||||||
out.append(make_cmd(CONS));
|
|
||||||
args = args.cdr();
|
args = args.cdr();
|
||||||
}
|
}
|
||||||
|
while (!args.null()) {
|
||||||
|
rev.push(args.car());
|
||||||
|
args = args.cdr();
|
||||||
|
}
|
||||||
|
while (!rev.empty()) {
|
||||||
|
out.splice(compile(rev.top(), env));
|
||||||
|
out.append(make_cmd(CONS));
|
||||||
|
rev.pop();
|
||||||
|
}
|
||||||
return out;
|
return out;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -60,7 +78,10 @@ Handle Compiler::compile(const Handle &src, Handle fake_env, const Handle &suffi
|
|||||||
Handle car = expr.car();
|
Handle car = expr.car();
|
||||||
Handle cdr = expr.cdr();
|
Handle cdr = expr.cdr();
|
||||||
if (car.atom()) {
|
if (car.atom()) {
|
||||||
if (builtins.find(car.strval()) != builtins.end()) {
|
if (car.strval() == "quote") {
|
||||||
|
out.append(make_cmd(LDC));
|
||||||
|
out.splice(cdr);
|
||||||
|
} else if (builtins.find(car.strval()) != builtins.end()) {
|
||||||
out.splice(compileArgsRaw(cdr));
|
out.splice(compileArgsRaw(cdr));
|
||||||
out.append(make_cmd(builtins.at(car.strval())));
|
out.append(make_cmd(builtins.at(car.strval())));
|
||||||
} else if (car.strval() == "read") {
|
} else if (car.strval() == "read") {
|
||||||
@@ -78,8 +99,6 @@ Handle Compiler::compile(const Handle &src, Handle fake_env, const Handle &suffi
|
|||||||
out.append(make_cmd(LDG));
|
out.append(make_cmd(LDG));
|
||||||
out.append(compile(cdr.cdr().car(), Handle::cons(cdr.car().cdr(), fake_env), make_cmd(RET)));
|
out.append(compile(cdr.cdr().car(), Handle::cons(cdr.car().cdr(), fake_env), make_cmd(RET)));
|
||||||
} else if (car.strval() == "let" || car.strval() == "letrec") {
|
} else if (car.strval() == "let" || car.strval() == "letrec") {
|
||||||
std::vector<std::pair<Handle, Handle>> argBody;
|
|
||||||
|
|
||||||
Handle definitions = cdr.car();
|
Handle definitions = cdr.car();
|
||||||
|
|
||||||
Handle argNames;
|
Handle argNames;
|
||||||
@@ -88,7 +107,6 @@ Handle Compiler::compile(const Handle &src, Handle fake_env, const Handle &suffi
|
|||||||
Handle body = cdr.cdr().car();
|
Handle body = cdr.cdr().car();
|
||||||
|
|
||||||
while (!definitions.null()) {
|
while (!definitions.null()) {
|
||||||
argBody.emplace_back(definitions.car().car(), definitions.car().cdr().car());
|
|
||||||
argNames.append(definitions.car().car());
|
argNames.append(definitions.car().car());
|
||||||
argBodies.append(definitions.car().cdr().car());
|
argBodies.append(definitions.car().cdr().car());
|
||||||
definitions = definitions.cdr();
|
definitions = definitions.cdr();
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ Handle Parser::parseExpr() {
|
|||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
if (_tokenizer.peek() == ")") {
|
||||||
|
token = _tokenizer.peek();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
out.append(parseExpr());
|
out.append(parseExpr());
|
||||||
token = _tokenizer.peek();
|
token = _tokenizer.peek();
|
||||||
}
|
}
|
||||||
@@ -37,7 +41,7 @@ Handle Parser::parseExpr() {
|
|||||||
} else {
|
} else {
|
||||||
token = _tokenizer.getNext();
|
token = _tokenizer.getNext();
|
||||||
if (token.find_first_not_of("0123456789") == std::string::npos ||
|
if (token.find_first_not_of("0123456789") == std::string::npos ||
|
||||||
(token.length() > 1 && token.at(0) == '0' && token.find_first_not_of("0123456789", 1) == std::string::npos)) {
|
(token.length() > 1 && token.at(0) == '-' && token.find_first_not_of("0123456789", 1) == std::string::npos)) {
|
||||||
CellValType val = std::stoi(token);
|
CellValType val = std::stoi(token);
|
||||||
return Handle::makeNumCell(val);
|
return Handle::makeNumCell(val);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -23,6 +23,19 @@ void VM::step() {
|
|||||||
Handle poppedH = _c.pop();
|
Handle poppedH = _c.pop();
|
||||||
// as to not complicate parser for tests...
|
// as to not complicate parser for tests...
|
||||||
CellValType poppedCmd = poppedH.type() == CellType::STRATOM ? str_to_cmd.at(poppedH.strval()) : poppedH.val();
|
CellValType poppedCmd = poppedH.type() == CellType::STRATOM ? str_to_cmd.at(poppedH.strval()) : poppedH.val();
|
||||||
|
|
||||||
|
|
||||||
|
Logger::log(
|
||||||
|
"VM",
|
||||||
|
[&](std::ostream &out) {
|
||||||
|
out << "Executing " << cmd_to_str.at(poppedCmd) << "\n";
|
||||||
|
if (!_s.null()) out << "s:" << _s << "\n";
|
||||||
|
if (!_e.null()) out << "e:" << _e << "\n";
|
||||||
|
if (!_c.null()) out << "c:" << _c << "\n";
|
||||||
|
if (!_d.null()) out << "d:" << _d << "\n";
|
||||||
|
},
|
||||||
|
Logger::TRACE);
|
||||||
|
|
||||||
if (poppedCmd == NIL) {
|
if (poppedCmd == NIL) {
|
||||||
_s.push(nullptr);
|
_s.push(nullptr);
|
||||||
} else if (poppedCmd == LDC) {
|
} else if (poppedCmd == LDC) {
|
||||||
@@ -115,17 +128,17 @@ void VM::step() {
|
|||||||
} else if (poppedCmd == SUB) {
|
} else if (poppedCmd == SUB) {
|
||||||
CellValType a1 = _s.pop().val();
|
CellValType a1 = _s.pop().val();
|
||||||
CellValType a2 = _s.pop().val();
|
CellValType a2 = _s.pop().val();
|
||||||
_s.push(a2 - a1);
|
_s.push(a1 - a2);
|
||||||
} else if (poppedCmd == EQ) {
|
} else if (poppedCmd == EQ) {
|
||||||
_s.push(_s.pop() == _s.pop() ? 1 : 0);
|
_s.push(_s.pop() == _s.pop() ? 1 : 0);
|
||||||
} else if (poppedCmd == LT) {
|
} else if (poppedCmd == LT) {
|
||||||
CellValType a1 = _s.pop().val();
|
CellValType a1 = _s.pop().val();
|
||||||
CellValType a2 = _s.pop().val();
|
CellValType a2 = _s.pop().val();
|
||||||
_s.push(a2 < a1 ? 1 : 0);
|
_s.push(a1 < a2 ? 1 : 0);
|
||||||
} else if (poppedCmd == GT) {
|
} else if (poppedCmd == GT) {
|
||||||
CellValType a1 = _s.pop().val();
|
CellValType a1 = _s.pop().val();
|
||||||
CellValType a2 = _s.pop().val();
|
CellValType a2 = _s.pop().val();
|
||||||
_s.push(a2 > a1 ? 1 : 0);
|
_s.push(a1 > a2 ? 1 : 0);
|
||||||
} else if (poppedCmd == CAR) {
|
} else if (poppedCmd == CAR) {
|
||||||
_s.push(_s.pop().car());
|
_s.push(_s.pop().car());
|
||||||
} else if (poppedCmd == CDR) {
|
} else if (poppedCmd == CDR) {
|
||||||
@@ -159,7 +172,14 @@ void VM::step() {
|
|||||||
} else if (poppedCmd == LDG) {
|
} else if (poppedCmd == LDG) {
|
||||||
_globals_vals.append(Handle::cons(_c.pop(), _e));
|
_globals_vals.append(Handle::cons(_c.pop(), _e));
|
||||||
} else if (poppedCmd == PRINT) {
|
} else if (poppedCmd == PRINT) {
|
||||||
if (!_s.null()) _outstream << _s.pop() << std::endl;
|
if (!_s.null()) {
|
||||||
|
Handle val = _s.pop();
|
||||||
|
bool cons = !val.atom();
|
||||||
|
if (cons) _outstream << "(";
|
||||||
|
_outstream << val;
|
||||||
|
if (cons) _outstream << ")";
|
||||||
|
_outstream << std::endl;
|
||||||
|
}
|
||||||
} else if (poppedCmd == READ) {
|
} else if (poppedCmd == READ) {
|
||||||
std::string read;
|
std::string read;
|
||||||
std::getline(_instream, read);
|
std::getline(_instream, read);
|
||||||
@@ -169,4 +189,16 @@ void VM::step() {
|
|||||||
} else {
|
} else {
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Logger::log(
|
||||||
|
"VM",
|
||||||
|
[&](std::ostream &out) {
|
||||||
|
out << "Executed " << cmd_to_str.at(poppedCmd) << "\n";
|
||||||
|
if (!_s.null()) out << "s:" << _s << "\n";
|
||||||
|
if (!_e.null()) out << "e:" << _e << "\n";
|
||||||
|
if (!_c.null()) out << "c:" << _c << "\n";
|
||||||
|
if (!_d.null()) out << "d:" << _d << "\n";
|
||||||
|
},
|
||||||
|
Logger::TRACE);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ TEST(CompilerTest, BasicHello) {
|
|||||||
vm.run();
|
vm.run();
|
||||||
}
|
}
|
||||||
ssout.flush();
|
ssout.flush();
|
||||||
EXPECT_EQ(ssout.str(), "3");
|
EXPECT_EQ(ssout.str(), "3\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CompilerTest, BasicLet) {
|
TEST(CompilerTest, BasicLet) {
|
||||||
@@ -52,7 +52,7 @@ TEST(CompilerTest, BasicLet) {
|
|||||||
vm.run();
|
vm.run();
|
||||||
}
|
}
|
||||||
ssout.flush();
|
ssout.flush();
|
||||||
EXPECT_EQ(ssout.str(), "1");
|
EXPECT_EQ(ssout.str(), "1\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CompilerTest, BasicFn) {
|
TEST(CompilerTest, BasicFn) {
|
||||||
@@ -67,9 +67,48 @@ TEST(CompilerTest, BasicFn) {
|
|||||||
vm.run();
|
vm.run();
|
||||||
}
|
}
|
||||||
ssout.flush();
|
ssout.flush();
|
||||||
EXPECT_EQ(ssout.str(), "5");
|
EXPECT_EQ(ssout.str(), "5\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(CompilerTest, BasicFn2) {
|
||||||
|
std::stringstream ssin;
|
||||||
|
std::stringstream ssout;
|
||||||
|
{
|
||||||
|
|
||||||
|
VM vm(ssin, ssout);
|
||||||
|
Parser parser;
|
||||||
|
parser.loadStr("(LDC (let ((plfn (lambda (a b) (- a b)))) (plfn 2 3)) EVAL PRINT STOP)");
|
||||||
|
vm.loadControl(parser.parseExpr());
|
||||||
|
vm.run();
|
||||||
|
}
|
||||||
|
ssout.flush();
|
||||||
|
EXPECT_EQ(ssout.str(), "-1\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CompilerTest, MultiLet) {
|
||||||
|
std::stringstream ssin;
|
||||||
|
std::stringstream ssout;
|
||||||
|
{
|
||||||
|
|
||||||
|
VM vm(ssin, ssout);
|
||||||
|
Parser parser;
|
||||||
|
parser.loadStr("(LDC (let ((plfn (lambda (a b) (- a b))) (plfn2 (lambda (a b) (- b a)))) (plfn 2 3)) EVAL PRINT STOP)");
|
||||||
|
vm.loadControl(parser.parseExpr());
|
||||||
|
vm.run();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
|
||||||
|
VM vm(ssin, ssout);
|
||||||
|
Parser parser;
|
||||||
|
parser.loadStr("(LDC (let ((plfn (lambda (a b) (- a b))) (plfn2 (lambda (a b) (- b a)))) (plfn2 2 3)) EVAL PRINT STOP)");
|
||||||
|
vm.loadControl(parser.parseExpr());
|
||||||
|
vm.run();
|
||||||
|
}
|
||||||
|
ssout.flush();
|
||||||
|
EXPECT_EQ(ssout.str(), "-1\n1\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(CompilerTest, BasicFnIfT) {
|
TEST(CompilerTest, BasicFnIfT) {
|
||||||
std::stringstream ssin;
|
std::stringstream ssin;
|
||||||
std::stringstream ssout;
|
std::stringstream ssout;
|
||||||
@@ -82,7 +121,7 @@ TEST(CompilerTest, BasicFnIfT) {
|
|||||||
vm.run();
|
vm.run();
|
||||||
}
|
}
|
||||||
ssout.flush();
|
ssout.flush();
|
||||||
EXPECT_EQ(ssout.str(), "1");
|
EXPECT_EQ(ssout.str(), "1\n");
|
||||||
}
|
}
|
||||||
TEST(CompilerTest, BasicFnIfF) {
|
TEST(CompilerTest, BasicFnIfF) {
|
||||||
std::stringstream ssin;
|
std::stringstream ssin;
|
||||||
@@ -96,7 +135,7 @@ TEST(CompilerTest, BasicFnIfF) {
|
|||||||
vm.run();
|
vm.run();
|
||||||
}
|
}
|
||||||
ssout.flush();
|
ssout.flush();
|
||||||
EXPECT_EQ(ssout.str(), "2");
|
EXPECT_EQ(ssout.str(), "2\n");
|
||||||
}
|
}
|
||||||
TEST(CompilerTest, RecursiveFn) {
|
TEST(CompilerTest, RecursiveFn) {
|
||||||
std::stringstream ssin;
|
std::stringstream ssin;
|
||||||
@@ -111,7 +150,7 @@ TEST(CompilerTest, RecursiveFn) {
|
|||||||
vm.run();
|
vm.run();
|
||||||
}
|
}
|
||||||
ssout.flush();
|
ssout.flush();
|
||||||
EXPECT_EQ(ssout.str(), "55");
|
EXPECT_EQ(ssout.str(), "55\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CompilerTest, GlobalDefine) {
|
TEST(CompilerTest, GlobalDefine) {
|
||||||
@@ -126,7 +165,7 @@ TEST(CompilerTest, GlobalDefine) {
|
|||||||
vm.run();
|
vm.run();
|
||||||
}
|
}
|
||||||
ssout.flush();
|
ssout.flush();
|
||||||
EXPECT_EQ(ssout.str(), "1");
|
EXPECT_EQ(ssout.str(), "1\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -142,7 +181,61 @@ TEST(CompilerTest, GlobalDefineFn) {
|
|||||||
vm.run();
|
vm.run();
|
||||||
}
|
}
|
||||||
ssout.flush();
|
ssout.flush();
|
||||||
EXPECT_EQ(ssout.str(), "5");
|
EXPECT_EQ(ssout.str(), "5\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CompilerTest, GlobalDefineFnQuote) {
|
||||||
|
std::stringstream ssin;
|
||||||
|
std::stringstream ssout;
|
||||||
|
{
|
||||||
|
|
||||||
|
VM vm(ssin, ssout);
|
||||||
|
Parser parser;
|
||||||
|
parser.loadStr("(LDC (define (one) (quote (1 2))) EVAL LDC (one) EVAL PRINT STOP)");
|
||||||
|
vm.loadControl(parser.parseExpr());
|
||||||
|
vm.run();
|
||||||
|
}
|
||||||
|
ssout.flush();
|
||||||
|
EXPECT_EQ(ssout.str(), "(1 2)\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CompilerTest, GlobalDefineFnCar) {
|
||||||
|
std::stringstream ssin;
|
||||||
|
std::stringstream ssout;
|
||||||
|
{
|
||||||
|
|
||||||
|
VM vm(ssin, ssout);
|
||||||
|
Parser parser;
|
||||||
|
parser.loadStr(
|
||||||
|
"(LDC (define (carr l) (car l)) EVAL LDC (carr (quote (1 2))) EVAL PRINT LDC (carr (cdr (quote (1 2)))) EVAL PRINT STOP)");
|
||||||
|
vm.loadControl(parser.parseExpr());
|
||||||
|
vm.run();
|
||||||
|
}
|
||||||
|
ssout.flush();
|
||||||
|
EXPECT_EQ(ssout.str(), "1\n2\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CompilerTest, GlobalDefineFnEq) {
|
||||||
|
std::stringstream ssin;
|
||||||
|
std::stringstream ssout;
|
||||||
|
{
|
||||||
|
|
||||||
|
VM vm(ssin, ssout);
|
||||||
|
Parser parser;
|
||||||
|
parser.loadStr("(LDC (define (eqtest l) (= l ())) EVAL LDC (eqtest (quote ())) EVAL PRINT LDC (eqtest (nil)) EVAL PRINT STOP)");
|
||||||
|
vm.loadControl(parser.parseExpr());
|
||||||
|
vm.run();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
|
||||||
|
VM vm(ssin, ssout);
|
||||||
|
Parser parser;
|
||||||
|
parser.loadStr("(LDC (define (eqtest l) (= l (nil))) EVAL LDC (eqtest (quote ())) EVAL PRINT LDC (eqtest (nil)) EVAL PRINT STOP)");
|
||||||
|
vm.loadControl(parser.parseExpr());
|
||||||
|
vm.run();
|
||||||
|
}
|
||||||
|
ssout.flush();
|
||||||
|
EXPECT_EQ(ssout.str(), "1\n1\n1\n1\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CompilerTest, GlobalDefineFnMulti) {
|
TEST(CompilerTest, GlobalDefineFnMulti) {
|
||||||
@@ -157,9 +250,25 @@ TEST(CompilerTest, GlobalDefineFnMulti) {
|
|||||||
vm.run();
|
vm.run();
|
||||||
}
|
}
|
||||||
ssout.flush();
|
ssout.flush();
|
||||||
EXPECT_EQ(ssout.str(), "6");
|
EXPECT_EQ(ssout.str(), "6\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(CompilerTest, GlobalDefineFnMultiTwo) {
|
||||||
|
std::stringstream ssin;
|
||||||
|
std::stringstream ssout;
|
||||||
|
{
|
||||||
|
|
||||||
|
VM vm(ssin, ssout);
|
||||||
|
Parser parser;
|
||||||
|
parser.loadStr("(LDC (define (one x y) (- x y)) EVAL LDC (define (two x y) (one (+ x 1) y)) EVAL LDC (two 2 3) EVAL PRINT STOP)");
|
||||||
|
vm.loadControl(parser.parseExpr());
|
||||||
|
vm.run();
|
||||||
|
}
|
||||||
|
ssout.flush();
|
||||||
|
EXPECT_EQ(ssout.str(), "0\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(CompilerTest, GlobalDefineFnRec) {
|
TEST(CompilerTest, GlobalDefineFnRec) {
|
||||||
std::stringstream ssin;
|
std::stringstream ssin;
|
||||||
std::stringstream ssout;
|
std::stringstream ssout;
|
||||||
@@ -176,5 +285,5 @@ TEST(CompilerTest, GlobalDefineFnRec) {
|
|||||||
Options::set_bool("command_strs", true);
|
Options::set_bool("command_strs", true);
|
||||||
Logger::set_level("MemoryContext", Options::get_int("default_log_level"));
|
Logger::set_level("MemoryContext", Options::get_int("default_log_level"));
|
||||||
ssout.flush();
|
ssout.flush();
|
||||||
EXPECT_EQ(ssout.str(), "6765");
|
EXPECT_EQ(ssout.str(), "6765\n");
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user