From a9050fc9b9f91a0cddbd9cbbcc5907d1a9772567 Mon Sep 17 00:00:00 2001 From: Stepan Usatiuk Date: Sat, 23 Dec 2023 19:21:05 +0100 Subject: [PATCH] secd parser --- src/vm/src/Parser.cpp | 51 +++++++++++++++++++++++++++++++----- test/vm/VMWithParserTest.cpp | 28 ++++++++++++++++++++ 2 files changed, 72 insertions(+), 7 deletions(-) diff --git a/src/vm/src/Parser.cpp b/src/vm/src/Parser.cpp index 7ff7fbf..6fa981d 100644 --- a/src/vm/src/Parser.cpp +++ b/src/vm/src/Parser.cpp @@ -43,6 +43,34 @@ void Parser::compileBody(const std::function &sink) { int64_t loc = std::stoi(_tokenizer.getNext()); if (_tokenizer.getNext() != ")") throw std::invalid_argument("Expected )"); sink(_vm.makeCell(_vm.makeCell(frame), _vm.makeCell(loc))); + } else if (token == "SEL") { + std::stack outt; + compileBody([&outt](Cell *cmd) { outt.emplace(cmd); }); + std::stack outf; + compileBody([&outf](Cell *cmd) { outf.emplace(cmd); }); + + if (outt.empty()) throw std::invalid_argument("Function body empty"); + if (outf.empty()) throw std::invalid_argument("Function body empty"); + + ConsCell *ttop = _vm.makeCell(outt.top()); + outt.pop(); + while (!outt.empty()) { + _vm.push(ttop, outt.top()); + outt.pop(); + } + + ConsCell *ftop = _vm.makeCell(outf.top()); + outf.pop(); + while (!outf.empty()) { + _vm.push(ftop, outf.top()); + outf.pop(); + } + + sink(_vm.makeCell(CommandCell::CommandNum::SEL)); + sink(ttop); + sink(ftop); + } else if (token == "JOIN") { + sink(_vm.makeCell(CommandCell::CommandNum::JOIN)); } else if (token == "LDF") { std::stack out; @@ -59,22 +87,31 @@ void Parser::compileBody(const std::function &sink) { } sink(_vm.makeCell(CommandCell::CommandNum::LDF)); sink(fntop); - } else if (token == "CONS") { - sink(_vm.makeCell(CommandCell::CommandNum::CONS)); } else if (token == "AP") { sink(_vm.makeCell(CommandCell::CommandNum::AP)); - } else if (token == "ADD") { - sink(_vm.makeCell(CommandCell::CommandNum::ADD)); } else if (token == "RET") { sink(_vm.makeCell(CommandCell::CommandNum::RET)); + } else if (token == "DUM") { + sink(_vm.makeCell(CommandCell::CommandNum::DUM)); + } else if (token == "RAP") { + sink(_vm.makeCell(CommandCell::CommandNum::RAP)); + } else if (token == "STOP") { + sink(_vm.makeCell(CommandCell::CommandNum::STOP)); + } else if (token == "ADD") { + sink(_vm.makeCell(CommandCell::CommandNum::ADD)); + } else if (token == "SUB") { + sink(_vm.makeCell(CommandCell::CommandNum::SUB)); + } else if (token == "READCHAR") { + sink(_vm.makeCell(CommandCell::CommandNum::READCHAR)); } else if (token == "PUTCHAR") { sink(_vm.makeCell(CommandCell::CommandNum::PUTCHAR)); } else if (token == "PUTNUM") { sink(_vm.makeCell(CommandCell::CommandNum::PUTNUM)); - } else if (token == "STOP") { - sink(_vm.makeCell(CommandCell::CommandNum::STOP)); + } else if (token == "CONS") { + sink(_vm.makeCell(CommandCell::CommandNum::CONS)); } else { - if (token != ")")throw std::invalid_argument("Unknown token " + token); + if (token != ")") + throw std::invalid_argument("Unknown token " + token); } } } diff --git a/test/vm/VMWithParserTest.cpp b/test/vm/VMWithParserTest.cpp index 9a0ce9c..086f990 100644 --- a/test/vm/VMWithParserTest.cpp +++ b/test/vm/VMWithParserTest.cpp @@ -16,6 +16,20 @@ TEST(VMWithParserTest, BasicHello) { EXPECT_EQ(ssout.str(), "h"); } +TEST(VMWithParserTest, BasicBranch) { + std::stringstream ssin; + std::stringstream ssout; + { + VM vm(ssin, ssout); + Parser parser(vm); + parser.loadSecd( + "( LDC 1 SEL ( LDC 10 PUTNUM JOIN ) ( LDC 20 PUTNUM JOIN ) LDC 0 SEL ( LDC 30 PUTNUM JOIN ) ( LDC 40 PUTNUM JOIN ) STOP )"); + vm.run(); + } + ssout.flush(); + EXPECT_EQ(ssout.str(), "1040"); +} + TEST(VMWithParserTest, BasicFunction) { std::stringstream ssin; std::stringstream ssout; @@ -27,4 +41,18 @@ TEST(VMWithParserTest, BasicFunction) { } ssout.flush(); EXPECT_EQ(ssout.str(), "3"); +} + +TEST(VMWithParserTest, RecFunction) { + std::stringstream ssin; + std::stringstream ssout; + { + VM vm(ssin, ssout); + Parser parser(vm); + parser.loadSecd( + "( DUM NIL LDF ( LD ( 1 . 1 ) SEL ( LD ( 1 . 1 ) LDC -1 ADD SEL ( NIL LD ( 1 . 1 ) LDC -1 ADD CONS LD ( 2 . 1 ) AP NIL LD ( 1 . 1 ) LDC -2 ADD CONS LD ( 2 . 1 ) AP ADD JOIN ) ( LDC 1 JOIN ) JOIN ) ( LDC 0 JOIN ) RET ) CONS LDF ( NIL LDC 20 CONS LD ( 1 . 1 ) AP RET ) RAP PUTNUM STOP )"); + vm.run(); + } + ssout.flush(); + EXPECT_EQ(ssout.str(), "6765"); } \ No newline at end of file