Skip to content

Commit

Permalink
#76 fail?
Browse files Browse the repository at this point in the history
  • Loading branch information
c71n93 committed Dec 20, 2023
1 parent f357d34 commit 9630114
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 27 deletions.
16 changes: 13 additions & 3 deletions include/frontend/assembler/asmlex.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class AsmLex final : public yyFlexLexer {
OP_CURLY_BRACKET,
CL_CURLY_BRACKET,
COMMA,
EOF_,
UNKNOWN
};

Expand Down Expand Up @@ -74,6 +75,11 @@ class AsmLex final : public yyFlexLexer {
Coma(LexemType t) : Lexem(t) {}
~Coma() override {}
};
class Eof final : public Lexem {
public:
Eof(LexemType t) : Lexem(t) {}
~Eof() override {}
};
class Unknown final : public Lexem {
public:
Unknown(LexemType t) : Lexem(t) {}
Expand Down Expand Up @@ -107,15 +113,15 @@ class AsmLex final : public yyFlexLexer {
return 0;
}
int processFunc() {
currentLexem_ = std::make_unique<Coma>(LexemType::FUNC);
currentLexem_ = std::make_unique<Func>(LexemType::FUNC);
return 0;
}
int processOpCurlyBracket() {
currentLexem_ = std::make_unique<Coma>(LexemType::OP_CURLY_BRACKET);
currentLexem_ = std::make_unique<OpCurlyBracket>(LexemType::OP_CURLY_BRACKET);
return 0;
}
int processClCurlyBracket() {
currentLexem_ = std::make_unique<Coma>(LexemType::CL_CURLY_BRACKET);
currentLexem_ = std::make_unique<ClCurlyBracket>(LexemType::CL_CURLY_BRACKET);
return 0;
}
int processComma() {
Expand All @@ -128,6 +134,10 @@ class AsmLex final : public yyFlexLexer {
LexemType::STRING, withQuotes.substr(1, withQuotes.size() - 2));
return 0;
}
int processEOF() {
currentLexem_ = std::make_unique<Eof>(LexemType::EOF_);
return 0;
}
int processUnknown() {
currentLexem_ = std::make_unique<Unknown>(LexemType::UNKNOWN);
return 1;
Expand Down
56 changes: 40 additions & 16 deletions include/frontend/assembler/assembler.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <sstream>
#include <utility>

#include "ChaiVM/interpreter/autogen/operations.hpp"
#include "ChaiVM/utils/file-format/chai-file.hpp"
Expand Down Expand Up @@ -30,6 +31,10 @@ class Assembler final {
*/
void assemble() {
processMain();
while (lex_.currentLexem()->type != AsmLex::EOF_) {
processFunction();
lex_.nextLexem();
}
chaiFile_.toFile(outPath_);
}

Expand All @@ -50,15 +55,32 @@ class Assembler final {
checkError();
chaiFile_.addInstr(processInstruction());
lex_.nextLexem();
if (lex_.currentLexem()->type == AsmLex::IDENTIFIER &&
OpString(
static_cast<AsmLex::Identifier *>(lex_.currentLexem().get())
->value) == chai::interpreter::Ret) {
chaiFile_.addInstr(processInstruction());
break;
}
}
}
/*
* @todo #76:90min Add function description to assembler
*/
/*
* @todo #76:90min Add function to constant pool before parsing instructions (for recursion)
*/
void processFunction() {
expectCurrentLexem(AsmLex::FUNC, "Expected function declaration");
expectNextLexem(AsmLex::IDENTIFIER, "Expected function name");
std::string func_name = static_cast<AsmLex::Identifier *>(lex_.currentLexem().get())->value;
expectNextLexem(AsmLex::INTEGER, "Expected number of registers in function frame");
auto num_regs = static_cast<uint8_t>(static_cast<AsmLex::Int *>(lex_.currentLexem().get())->value);
expectNextLexem(AsmLex::INTEGER, "Expected number of function arguments");
auto num_args = static_cast<uint8_t>(static_cast<AsmLex::Int *>(lex_.currentLexem().get())->value);
expectNextLexem(AsmLex::OP_CURLY_BRACKET, "Expected opening curly bracket");
std::vector<chai::bytecode_t> instrs;
lex_.nextLexem();
while (lex_.currentLexem()->type != AsmLex::CL_CURLY_BRACKET) {
instrs.push_back(processInstruction());
lex_.nextLexem();
}
expectCurrentLexem(AsmLex::CL_CURLY_BRACKET, "Expected closing curly bracket");
chaiFile_.addFunction(UINT16_MAX, func_name, "V(V)", instrs, num_args, num_regs);
}
chai::bytecode_t processInstruction() {
chai::interpreter::Operation op = OpString(
static_cast<AsmLex::Identifier *>(lex_.currentLexem().get())
Expand Down Expand Up @@ -94,7 +116,7 @@ class Assembler final {
}
chai::bytecode_t processRR(chai::interpreter::Operation op) {
chai::interpreter::RegisterId reg1Id = processReg();
expectComma();
expectNextLexem(AsmLex::COMMA, "Expected coma");
chai::interpreter::RegisterId reg2Id = processReg();
return chai::utils::instr2Raw(op, reg1Id, reg2Id);
}
Expand Down Expand Up @@ -125,7 +147,7 @@ class Assembler final {
}
chai::bytecode_t processRI(chai::interpreter::Operation op) {
chai::interpreter::RegisterId regId = processReg();
expectComma();
expectNextLexem(AsmLex::COMMA, "Expected coma");
lex_.nextLexem();
if (lex_.currentLexem()->type == AsmLex::INTEGER) {
auto val = static_cast<int64_t>(
Expand All @@ -152,10 +174,7 @@ class Assembler final {
}

chai::interpreter::RegisterId processReg() {
lex_.nextLexem();
if (lex_.currentLexem()->type != AsmLex::IDENTIFIER) {
throw AssembleError("Expected register", lex_.lineno());
}
expectNextLexem(AsmLex::IDENTIFIER, "Expected register name");
return regNameToRegId(
static_cast<AsmLex::Identifier *>(lex_.currentLexem().get())
->value);
Expand All @@ -166,10 +185,15 @@ class Assembler final {
throw AssembleError("Unknown lexem", lex_.lineno());
}
}
void expectComma() {
void expectNextLexem(AsmLex::LexemType type, std::string msg) {
lex_.nextLexem();
if (lex_.currentLexem()->type != AsmLex::COMMA) {
throw AssembleError("Expected comma", lex_.lineno());
if (lex_.currentLexem()->type != type) {
throw AssembleError(std::move(msg), lex_.lineno());
}
}
void expectCurrentLexem(AsmLex::LexemType type, std::string msg) {
if (lex_.currentLexem()->type != type) {
throw AssembleError(std::move(msg), lex_.lineno());
}
}
/*
Expand Down
3 changes: 2 additions & 1 deletion src/frontend/assembler/asmlex.l
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@ COMMA ,
{COMMENT} /* skip */
{INT} return processInt();
{FLOAT} return processFloat();
{IDENTIFIER} return processIdentifier();
"fn" return processFunc();
"{" return processOpCurlyBracket();
"}" return processClCurlyBracket();
{COMMA} return processComma();
{IDENTIFIER} return processIdentifier();
{STRING} return processString();
<<EOF>> return processEOF();
. return processUnknown();

%%
Expand Down
20 changes: 20 additions & 0 deletions test/frontend/assembler/assembler-test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,23 @@ TEST_F(AssemblerTest, runWithStrings) {
exec_.run();
EXPECT_EQ(codeManager_.getCnstString(exec_.acc()), "Hello world");
}

TEST_F(AssemblerTest, runWithFunctions) {
write_input_ << "Ldia 271\n"
<< "Star r99\n"
<< "Ldia 314\n"
<< "Star r98\n"
<< "Call 5\n"
<< "Ret\n"
<< "fn aboba_func 50 2 {\n"
<< "Ldra r49\n"
<< "Sub r48\n"
<< "Ret\n"
<< "}\n" << std::endl;
Assembler asM{input_, output_};
asM.assemble();
codeManager_.load(output_);
exec_.run();
EXPECT_EQ(static_cast<int64_t>(exec_.acc()), 314 - 271);
EXPECT_EQ(exec_.getCurrentFrame(), nullptr);
}
7 changes: 0 additions & 7 deletions test/frontend/assembler/run.chai

This file was deleted.

0 comments on commit 9630114

Please sign in to comment.