From d4e6c1c717931d7d535e4ac7aec390ebcd62d6f2 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Mon, 21 Aug 2023 10:30:42 +0000 Subject: [PATCH] ast: add emitter and resolver --- Makefile | 6 +- ast.hpp | 69 +----------- ast_emitter.cpp | 223 +++++++++++++++++++++++++++++++++++++ ast_emitter.hpp | 67 +++++++++++ ast.cpp => ast_printer.cpp | 88 ++++++++------- ast_printer.hpp | 76 +++++++++++++ ast_resolver.cpp | 186 +++++++++++++++++++++++++++++++ ast_resolver.hpp | 77 +++++++++++++ expr.hpp | 4 +- main.cpp | 29 +++-- stmt.hpp | 11 +- 11 files changed, 718 insertions(+), 118 deletions(-) create mode 100644 ast_emitter.cpp create mode 100644 ast_emitter.hpp rename ast.cpp => ast_printer.cpp (55%) create mode 100644 ast_printer.hpp create mode 100644 ast_resolver.cpp create mode 100644 ast_resolver.hpp diff --git a/Makefile b/Makefile index 5f42fb0..bbba52d 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,9 @@ CXX = $(TARGET)clang++ SRC = main.cpp SRC += lexer.cpp -SRC += ast.cpp +SRC += ast_printer.cpp +SRC += ast_resolver.cpp +SRC += ast_emitter.cpp SRC += parser.cpp SRC += stmt_string.cpp OBJ = $(patsubst %.cpp,%.o,$(SRC)) @@ -23,7 +25,7 @@ main: $(OBJ) $(CXX) $(LDFLAGS) $^ -o $@ clean: - rm -f *.o *.d *.gch + rm -f *.o *.d *.gch main .SUFFIXES: .INTERMEDIATE: diff --git a/ast.hpp b/ast.hpp index 62faf2f..1177f33 100644 --- a/ast.hpp +++ b/ast.hpp @@ -1,72 +1,15 @@ #pragma once -#include #include - -#include "visitor.hpp" -#include "expr.hpp" -#include "num.hpp" -#include "stmt.hpp" +#include namespace dsp { -struct ast_printer_t : visitor_t -{ - ast_printer_t(std::ostream& os) - : os(os) {} +namespace ast { - std::ostream& os; - - void visit(const binary_t * binary) const; - void visit(const grouping_t * grouping) const; - void visit(const identifier_t * identifier) const; - void visit(const literal_t * literal) const; - void visit(const unary_t * unary) const; - - void visit(const op::alu_t * alu) const; - void visit(const op::mov_ram_x_t * mov_ram_x) const; - void visit(const op::mov_mul_p_t * mov_mul_p) const; - void visit(const op::mov_ram_p_t * mov_ram_p) const; - void visit(const op::mov_ram_y_t * mov_ram_y) const; - void visit(const op::clr_a_t * clr_a) const; - void visit(const op::mov_alu_a_t * mov_alu_a) const; - void visit(const op::mov_ram_a_t * mov_ram_a) const; - void visit(const op::mov_imm_d1_t * mov_imm_d1) const; - void visit(const op::mov_ram_d1_t * mov_ram_d1) const; - void visit(const op::control_word_t * control_word) const; - - void visit(const load::mvi_t * mvi) const; - void visit(const load::mvi_cond_t * mvi_cond) const; - - void visit(const dma::src_d0_imm_t * src_d0_imm) const; - void visit(const dma::d0_dst_imm_t * d0_dst_imm) const; - void visit(const dma::src_d0_ram_t * src_d0_ram) const; - void visit(const dma::d0_dst_ram_t * d0_dst_ram) const; - - void visit(const jump::jmp_t * jmp) const; - void visit(const jump::jmp_cond_t * jmp_cond) const; - - void visit(const loop::btm_t * btm) const; - void visit(const loop::lps_t * lps) const; - - void visit(const end::end_t * end) const; - void visit(const end::endi_t * endi) const; - - void visit(const nop::nop_t * nop) const; - - void visit(const assign_t * assign) const; - void visit(const label_t * label) const; - - void parenthesize(const std::string_view s, const expr_t * a) const; - void parenthesize(const std::string_view s1, const std::string_view s2, const expr_t * a) const; - void parenthesize(const std::string_view s1, const std::string_view s2, const std::string_view s3, const expr_t * a) const; - void parenthesize(const std::string_view s1, const expr_t * a, const std::string_view s2) const; - void parenthesize(const std::string_view s1, const expr_t * a, const std::string_view s2, const std::string_view s3) const; - void parenthesize(const std::string_view s, const expr_t * a, const expr_t * b) const; - void parenthesize(const std::string_view s) const; - void parenthesize(const std::string_view s1, const std::string_view s2) const; - void parenthesize(const std::string_view s1, const std::string_view s2, const std::string_view s3) const; - void parenthesize(const std::string_view s1, const std::string_view s2, const std::string_view s3, const std::string_view s4) const; -}; +using addresses_t = std::unordered_map; +using variables_t = std::unordered_map; + +} } diff --git a/ast_emitter.cpp b/ast_emitter.cpp new file mode 100644 index 0000000..e506f88 --- /dev/null +++ b/ast_emitter.cpp @@ -0,0 +1,223 @@ +#include + +#include "ast_emitter.hpp" + +namespace dsp { + +namespace ast { + +// expressions + +uint32_t emitter_t::visit(const binary_t * binary) const +{ + uint32_t l = binary->left->accept(this); + uint32_t r = binary->right->accept(this); + + using enum dsp::token_t::type_t; + + switch (binary->oper.type) { + case plus: return l + r; // add + case minus: return l - r; // subtract + case star: return l * r; // multiply + case slash: return l / r; // divide + case percent: return l % r; // modulus + case ampersand: return l & r; // logical and + case bar: return l | r; // logical or + case carot: return l ^ r; // logical xor + case left_shift: return l << r; // logical left shift + case right_shift: return l >> r; // logical right shift + default: + throw std::runtime_error("invalid binary operand"); + } +} + +uint32_t emitter_t::visit(const grouping_t * grouping) const +{ + return grouping->expr->accept(this); +} + +uint32_t emitter_t::visit(const identifier_t * identifier) const +{ + if (variables.contains(identifier->name.lexeme)) { + return variables.at(identifier->name.lexeme); + } else { + throw std::runtime_error("undefined identifier"); + } +} + +uint32_t emitter_t::visit(const literal_t * literal) const +{ + return literal->value; +} + +uint32_t emitter_t::visit(const unary_t * unary) const +{ + uint32_t r = unary->right->accept(this); + + using enum dsp::token_t::type_t; + + switch (unary->oper.type) { + case tilde: return ~r; + case plus: return +r; + case minus: return -r; + default: + throw std::runtime_error("invalid binary operand"); + } +} + +// instructions + +uint32_t emitter_t::visit(const op::alu_t * alu) const +{ + return alu->code() | alu->bits(); +} + +uint32_t emitter_t::visit(const op::mov_ram_x_t * mov_ram_x) const +{ + return mov_ram_x->code() | mov_ram_x->bits(); +} + +uint32_t emitter_t::visit(const op::mov_mul_p_t * mov_mul_p) const +{ + return mov_mul_p->code() | mov_mul_p->bits(); +} + +uint32_t emitter_t::visit(const op::mov_ram_p_t * mov_ram_p) const +{ + return mov_ram_p->code() | mov_ram_p->bits(); +} + +uint32_t emitter_t::visit(const op::mov_ram_y_t * mov_ram_y) const +{ + return mov_ram_y->code() | mov_ram_y->bits(); +} + +uint32_t emitter_t::visit(const op::clr_a_t * clr_a) const +{ + return clr_a->code() | clr_a->bits(); +} + +uint32_t emitter_t::visit(const op::mov_alu_a_t * mov_alu_a) const +{ + return mov_alu_a->code() | mov_alu_a->bits(); +} + +uint32_t emitter_t::visit(const op::mov_ram_a_t * mov_ram_a) const +{ + return mov_ram_a->code() | mov_ram_a->bits(); +} + +uint32_t emitter_t::visit(const op::mov_imm_d1_t * mov_imm_d1) const +{ + num_t value = mov_imm_d1->imm.expr->accept(this); + if (mov_imm_d1->imm.in_range(value)) + return mov_imm_d1->code() | mov_imm_d1->bits() | value; + else + throw std::runtime_error("out of range"); +} + +uint32_t emitter_t::visit(const op::mov_ram_d1_t * mov_ram_d1) const +{ + return mov_ram_d1->code() | mov_ram_d1->bits(); +} + +uint32_t emitter_t::visit(const op::control_word_t * control_word) const +{ + uint32_t word = 0; + for (auto& op : control_word->ops) { word |= dynamic_cast(op)->accept(this); } + return word; +} + +uint32_t emitter_t::visit(const load::mvi_t * mvi) const +{ + return mvi->code() | mvi->bits(); +} + +uint32_t emitter_t::visit(const load::mvi_cond_t * mvi_cond) const +{ + return mvi_cond->code() | mvi_cond->bits(); +} + +uint32_t emitter_t::visit(const dma::src_d0_imm_t * src_d0_imm) const +{ + num_t value = src_d0_imm->imm.expr->accept(this); + if (src_d0_imm->imm.in_range(value)) + return src_d0_imm->code() | src_d0_imm->bits() | value; + else + throw std::runtime_error("out of range"); +} + +uint32_t emitter_t::visit(const dma::d0_dst_imm_t * d0_dst_imm) const +{ + num_t value = d0_dst_imm->imm.expr->accept(this); + if (d0_dst_imm->imm.in_range(value)) + return d0_dst_imm->code() | d0_dst_imm->bits() | value; + else + throw std::runtime_error("out of range"); +} + +uint32_t emitter_t::visit(const dma::src_d0_ram_t * src_d0_ram) const +{ + return src_d0_ram->code() | src_d0_ram->bits(); +} + +uint32_t emitter_t::visit(const dma::d0_dst_ram_t * d0_dst_ram) const +{ + return d0_dst_ram->code() | d0_dst_ram->bits(); +} + +uint32_t emitter_t::visit(const jump::jmp_t * jmp) const +{ + return jmp->code() | jmp->bits(); +} + +uint32_t emitter_t::visit(const jump::jmp_cond_t * jmp_cond) const +{ + return jmp_cond->code() | jmp_cond->bits(); +} + +uint32_t emitter_t::visit(const loop::btm_t * btm) const +{ + return btm->code() | btm->bits(); +} + +uint32_t emitter_t::visit(const loop::lps_t * lps) const +{ + return lps->code() | lps->bits(); +} + +uint32_t emitter_t::visit(const end::end_t * end) const +{ + return end->code() | end->bits(); +} + +uint32_t emitter_t::visit(const end::endi_t * endi) const +{ + return endi->code() | endi->bits(); +} + +uint32_t emitter_t::visit(const nop::nop_t * nop) const +{ + return nop->code() | nop->bits(); +} + +uint32_t emitter_t::visit(const assign_t * assign) const +{ + if (variables.contains(assign->name.lexeme)) { + throw std::runtime_error("assignment redefinition is not allowed"); + } else { + num_t value = assign->value->accept(this); + variables.insert({assign->name.lexeme, value}); + } + return 0xffff'ffff; // lazy hack +} + +uint32_t emitter_t::visit(const label_t * label) const +{ + (void)label; + return 0xffff'ffff; // lazy hack +} + +} + +} diff --git a/ast_emitter.hpp b/ast_emitter.hpp new file mode 100644 index 0000000..dc7d522 --- /dev/null +++ b/ast_emitter.hpp @@ -0,0 +1,67 @@ +#pragma once + +#include +#include +#include + +#include "visitor.hpp" +#include "expr.hpp" +#include "stmt.hpp" +#include "ast.hpp" + +namespace dsp { + +namespace ast { + +struct emitter_t : visitor_t +{ + emitter_t(variables_t& variables, const addresses_t& addresses) + : variables(variables), addresses(addresses) {} + + variables_t& variables; + const addresses_t& addresses; + + uint32_t visit(const binary_t * binary) const; + uint32_t visit(const grouping_t * grouping) const; + uint32_t visit(const identifier_t * identifier) const; + uint32_t visit(const literal_t * literal) const; + uint32_t visit(const unary_t * unary) const; + + uint32_t visit(const op::alu_t * alu) const; + uint32_t visit(const op::mov_ram_x_t * mov_ram_x) const; + uint32_t visit(const op::mov_mul_p_t * mov_mul_p) const; + uint32_t visit(const op::mov_ram_p_t * mov_ram_p) const; + uint32_t visit(const op::mov_ram_y_t * mov_ram_y) const; + uint32_t visit(const op::clr_a_t * clr_a) const; + uint32_t visit(const op::mov_alu_a_t * mov_alu_a) const; + uint32_t visit(const op::mov_ram_a_t * mov_ram_a) const; + uint32_t visit(const op::mov_imm_d1_t * mov_imm_d1) const; + uint32_t visit(const op::mov_ram_d1_t * mov_ram_d1) const; + uint32_t visit(const op::control_word_t * control_word) const; + + uint32_t visit(const load::mvi_t * mvi) const; + uint32_t visit(const load::mvi_cond_t * mvi_cond) const; + + uint32_t visit(const dma::src_d0_imm_t * src_d0_imm) const; + uint32_t visit(const dma::d0_dst_imm_t * d0_dst_imm) const; + uint32_t visit(const dma::src_d0_ram_t * src_d0_ram) const; + uint32_t visit(const dma::d0_dst_ram_t * d0_dst_ram) const; + + uint32_t visit(const jump::jmp_t * jmp) const; + uint32_t visit(const jump::jmp_cond_t * jmp_cond) const; + + uint32_t visit(const loop::btm_t * btm) const; + uint32_t visit(const loop::lps_t * lps) const; + + uint32_t visit(const end::end_t * end) const; + uint32_t visit(const end::endi_t * endi) const; + + uint32_t visit(const nop::nop_t * nop) const; + + uint32_t visit(const assign_t * assign) const; + uint32_t visit(const label_t * label) const; +}; + +} + +} diff --git a/ast.cpp b/ast_printer.cpp similarity index 55% rename from ast.cpp rename to ast_printer.cpp index b66c579..06c73ce 100644 --- a/ast.cpp +++ b/ast_printer.cpp @@ -1,89 +1,91 @@ -#include "ast.hpp" +#include "ast_printer.hpp" #include "stmt_string.hpp" namespace dsp { -void ast_printer_t::visit(const binary_t * binary) const +namespace ast { + +void printer_t::visit(const binary_t * binary) const { parenthesize((binary->oper).lexeme, binary->left, binary->right); } -void ast_printer_t::visit(const grouping_t * grouping) const +void printer_t::visit(const grouping_t * grouping) const { parenthesize("grouping", grouping->expr); } -void ast_printer_t::visit(const identifier_t * identifier) const +void printer_t::visit(const identifier_t * identifier) const { parenthesize("identifier", identifier->name.lexeme); } -void ast_printer_t::visit(const literal_t * literal) const +void printer_t::visit(const literal_t * literal) const { os << std::to_string(literal->value); } -void ast_printer_t::visit(const unary_t * unary) const +void printer_t::visit(const unary_t * unary) const { parenthesize((unary->oper).lexeme, unary->right); } -void ast_printer_t::parenthesize(const std::string_view s, const expr_t * a) const +void printer_t::parenthesize(const std::string_view s, const expr_t * a) const { os << '(' << s << ' '; a->accept(this); os << ')'; } -void ast_printer_t::parenthesize(const std::string_view s1, const std::string_view s2, const expr_t * a) const +void printer_t::parenthesize(const std::string_view s1, const std::string_view s2, const expr_t * a) const { os << '(' << s1 << ' ' << s2 << ' '; a->accept(this); os << ')'; } -void ast_printer_t::parenthesize(const std::string_view s1, const std::string_view s2, const std::string_view s3, const expr_t * a) const +void printer_t::parenthesize(const std::string_view s1, const std::string_view s2, const std::string_view s3, const expr_t * a) const { os << '(' << s1 << ' ' << s2 << ' ' << s3 << ' '; a->accept(this); os << ')'; } -void ast_printer_t::parenthesize(const std::string_view s1, const expr_t * a, const std::string_view s2) const +void printer_t::parenthesize(const std::string_view s1, const expr_t * a, const std::string_view s2) const { os << '(' << s1 << ' '; a->accept(this); os << ' ' << s2 << ')'; } -void ast_printer_t::parenthesize(const std::string_view s1, const expr_t * a, const std::string_view s2, const std::string_view s3) const +void printer_t::parenthesize(const std::string_view s1, const expr_t * a, const std::string_view s2, const std::string_view s3) const { os << '(' << s1 << ' '; a->accept(this); os << ' ' << s2 << ' ' << s3 << ')'; } -void ast_printer_t::parenthesize(const std::string_view s) const +void printer_t::parenthesize(const std::string_view s) const { os << '(' << s << ')'; } -void ast_printer_t::parenthesize(const std::string_view s1, const std::string_view s2) const +void printer_t::parenthesize(const std::string_view s1, const std::string_view s2) const { os << '(' << s1 << ' ' << s2 << ')'; } -void ast_printer_t::parenthesize(const std::string_view s1, const std::string_view s2, const std::string_view s3) const +void printer_t::parenthesize(const std::string_view s1, const std::string_view s2, const std::string_view s3) const { os << '(' << s1 << ' ' << s2 << ' ' << s3 << ')'; } -void ast_printer_t::parenthesize(const std::string_view s1, const std::string_view s2, const std::string_view s3, const std::string_view s4) const +void printer_t::parenthesize(const std::string_view s1, const std::string_view s2, const std::string_view s3, const std::string_view s4) const { os << '(' << s1 << ' ' << s2 << ' ' << s3 << ' ' << s4 << ')'; } -void ast_printer_t::parenthesize(const std::string_view s, const expr_t * a, const expr_t * b) const +void printer_t::parenthesize(const std::string_view s, const expr_t * a, const expr_t * b) const { os << '(' << s << ' '; a->accept(this); @@ -94,64 +96,64 @@ void ast_printer_t::parenthesize(const std::string_view s, const expr_t * a, con // instructions -void ast_printer_t::visit(const op::alu_t * alu) const +void printer_t::visit(const op::alu_t * alu) const { parenthesize(op::alu_type_string[static_cast(alu->type)]); } -void ast_printer_t::visit(const op::mov_ram_x_t * mov_ram_x) const +void printer_t::visit(const op::mov_ram_x_t * mov_ram_x) const { parenthesize("mov", op::xy_src_string[static_cast(mov_ram_x->src)], "x"); } -void ast_printer_t::visit(const op::mov_mul_p_t * mov_mul_p) const +void printer_t::visit(const op::mov_mul_p_t * mov_mul_p) const { (void)mov_mul_p; parenthesize("mov mul p"); } -void ast_printer_t::visit(const op::mov_ram_p_t * mov_ram_p) const +void printer_t::visit(const op::mov_ram_p_t * mov_ram_p) const { parenthesize("mov", op::xy_src_string[static_cast(mov_ram_p->src)], "p"); } -void ast_printer_t::visit(const op::mov_ram_y_t * mov_ram_y) const +void printer_t::visit(const op::mov_ram_y_t * mov_ram_y) const { parenthesize("mov", op::xy_src_string[static_cast(mov_ram_y->src)], "y"); } -void ast_printer_t::visit(const op::clr_a_t * clr_a) const +void printer_t::visit(const op::clr_a_t * clr_a) const { (void)clr_a; parenthesize("clr a"); } -void ast_printer_t::visit(const op::mov_alu_a_t * mov_alu_a) const +void printer_t::visit(const op::mov_alu_a_t * mov_alu_a) const { (void)mov_alu_a; parenthesize("mov alu a"); } -void ast_printer_t::visit(const op::mov_ram_a_t * mov_ram_a) const +void printer_t::visit(const op::mov_ram_a_t * mov_ram_a) const { parenthesize("mov", op::xy_src_string[static_cast(mov_ram_a->src)], "a"); } -void ast_printer_t::visit(const op::mov_imm_d1_t * mov_imm_d1) const +void printer_t::visit(const op::mov_imm_d1_t * mov_imm_d1) const { parenthesize("mov", mov_imm_d1->imm.expr, op::d1_dest_string[static_cast(mov_imm_d1->dest)]); } -void ast_printer_t::visit(const op::mov_ram_d1_t * mov_ram_d1) const +void printer_t::visit(const op::mov_ram_d1_t * mov_ram_d1) const { parenthesize("mov", op::d1_src_string[static_cast(mov_ram_d1->src)], op::d1_dest_string[static_cast(mov_ram_d1->dest)]); } -void ast_printer_t::visit(const op::control_word_t * control_word) const +void printer_t::visit(const op::control_word_t * control_word) const { os << "(control_word "; for (const auto& op : control_word->ops) { @@ -161,12 +163,12 @@ void ast_printer_t::visit(const op::control_word_t * control_word) const os << ')'; } -void ast_printer_t::visit(const load::mvi_t * mvi) const +void printer_t::visit(const load::mvi_t * mvi) const { parenthesize("mvi", mvi->imm.expr, load::dest_string[static_cast(mvi->dest)]); } -void ast_printer_t::visit(const load::mvi_cond_t * mvi_cond) const +void printer_t::visit(const load::mvi_cond_t * mvi_cond) const { parenthesize("mvi", mvi_cond->imm.expr, @@ -180,7 +182,7 @@ static std::string dma_hold_add(bool hold, dma::add_mode_t add) + dma::add_mode_string[static_cast(add)]; } -void ast_printer_t::visit(const dma::src_d0_imm_t * src_d0_imm) const +void printer_t::visit(const dma::src_d0_imm_t * src_d0_imm) const { parenthesize(dma_hold_add(src_d0_imm->hold, src_d0_imm->add), dma::src_string[static_cast(src_d0_imm->src)], @@ -188,7 +190,7 @@ void ast_printer_t::visit(const dma::src_d0_imm_t * src_d0_imm) const src_d0_imm->imm.expr); } -void ast_printer_t::visit(const dma::d0_dst_imm_t * d0_dst_imm) const +void printer_t::visit(const dma::d0_dst_imm_t * d0_dst_imm) const { parenthesize(dma_hold_add(d0_dst_imm->hold, d0_dst_imm->add), "d0", @@ -196,7 +198,7 @@ void ast_printer_t::visit(const dma::d0_dst_imm_t * d0_dst_imm) const d0_dst_imm->imm.expr); } -void ast_printer_t::visit(const dma::src_d0_ram_t * src_d0_ram) const +void printer_t::visit(const dma::src_d0_ram_t * src_d0_ram) const { parenthesize(dma_hold_add(src_d0_ram->hold, src_d0_ram->add), dma::src_string[static_cast(src_d0_ram->src)], @@ -204,7 +206,7 @@ void ast_printer_t::visit(const dma::src_d0_ram_t * src_d0_ram) const dma::length_ram_string[static_cast(src_d0_ram->ram)]); } -void ast_printer_t::visit(const dma::d0_dst_ram_t * d0_dst_ram) const +void printer_t::visit(const dma::d0_dst_ram_t * d0_dst_ram) const { parenthesize(dma_hold_add(d0_dst_ram->hold, d0_dst_ram->add), "d0", @@ -212,56 +214,58 @@ void ast_printer_t::visit(const dma::d0_dst_ram_t * d0_dst_ram) const dma::length_ram_string[static_cast(d0_dst_ram->ram)]); } -void ast_printer_t::visit(const jump::jmp_t * jmp) const +void printer_t::visit(const jump::jmp_t * jmp) const { parenthesize("jmp", jmp->imm.expr); } -void ast_printer_t::visit(const jump::jmp_cond_t * jmp_cond) const +void printer_t::visit(const jump::jmp_cond_t * jmp_cond) const { parenthesize("jmp", jump::cond_string[static_cast(jmp_cond->cond)], jmp_cond->imm.expr); } -void ast_printer_t::visit(const loop::btm_t * btm) const +void printer_t::visit(const loop::btm_t * btm) const { (void)btm; parenthesize("btm"); } -void ast_printer_t::visit(const loop::lps_t * lps) const +void printer_t::visit(const loop::lps_t * lps) const { (void)lps; parenthesize("lps"); } -void ast_printer_t::visit(const end::end_t * end) const +void printer_t::visit(const end::end_t * end) const { (void)end; parenthesize("end"); } -void ast_printer_t::visit(const end::endi_t * endi) const +void printer_t::visit(const end::endi_t * endi) const { (void)endi; parenthesize("endi"); } -void ast_printer_t::visit(const nop::nop_t * nop) const +void printer_t::visit(const nop::nop_t * nop) const { (void)nop; parenthesize("nop"); } -void ast_printer_t::visit(const assign_t * assign) const +void printer_t::visit(const assign_t * assign) const { parenthesize("assign", assign->name.lexeme, assign->value); } -void ast_printer_t::visit(const label_t * label) const +void printer_t::visit(const label_t * label) const { parenthesize("label", label->name.lexeme); } } + +} diff --git a/ast_printer.hpp b/ast_printer.hpp new file mode 100644 index 0000000..5f76ae2 --- /dev/null +++ b/ast_printer.hpp @@ -0,0 +1,76 @@ +#pragma once + +#include +#include + +#include "visitor.hpp" +#include "expr.hpp" +#include "num.hpp" +#include "stmt.hpp" + +namespace dsp { + +namespace ast { + +struct printer_t : visitor_t +{ + printer_t(std::ostream& os) + : os(os) {} + + std::ostream& os; + + void visit(const binary_t * binary) const; + void visit(const grouping_t * grouping) const; + void visit(const identifier_t * identifier) const; + void visit(const literal_t * literal) const; + void visit(const unary_t * unary) const; + + void visit(const op::alu_t * alu) const; + void visit(const op::mov_ram_x_t * mov_ram_x) const; + void visit(const op::mov_mul_p_t * mov_mul_p) const; + void visit(const op::mov_ram_p_t * mov_ram_p) const; + void visit(const op::mov_ram_y_t * mov_ram_y) const; + void visit(const op::clr_a_t * clr_a) const; + void visit(const op::mov_alu_a_t * mov_alu_a) const; + void visit(const op::mov_ram_a_t * mov_ram_a) const; + void visit(const op::mov_imm_d1_t * mov_imm_d1) const; + void visit(const op::mov_ram_d1_t * mov_ram_d1) const; + void visit(const op::control_word_t * control_word) const; + + void visit(const load::mvi_t * mvi) const; + void visit(const load::mvi_cond_t * mvi_cond) const; + + void visit(const dma::src_d0_imm_t * src_d0_imm) const; + void visit(const dma::d0_dst_imm_t * d0_dst_imm) const; + void visit(const dma::src_d0_ram_t * src_d0_ram) const; + void visit(const dma::d0_dst_ram_t * d0_dst_ram) const; + + void visit(const jump::jmp_t * jmp) const; + void visit(const jump::jmp_cond_t * jmp_cond) const; + + void visit(const loop::btm_t * btm) const; + void visit(const loop::lps_t * lps) const; + + void visit(const end::end_t * end) const; + void visit(const end::endi_t * endi) const; + + void visit(const nop::nop_t * nop) const; + + void visit(const assign_t * assign) const; + void visit(const label_t * label) const; + + void parenthesize(const std::string_view s, const expr_t * a) const; + void parenthesize(const std::string_view s1, const std::string_view s2, const expr_t * a) const; + void parenthesize(const std::string_view s1, const std::string_view s2, const std::string_view s3, const expr_t * a) const; + void parenthesize(const std::string_view s1, const expr_t * a, const std::string_view s2) const; + void parenthesize(const std::string_view s1, const expr_t * a, const std::string_view s2, const std::string_view s3) const; + void parenthesize(const std::string_view s, const expr_t * a, const expr_t * b) const; + void parenthesize(const std::string_view s) const; + void parenthesize(const std::string_view s1, const std::string_view s2) const; + void parenthesize(const std::string_view s1, const std::string_view s2, const std::string_view s3) const; + void parenthesize(const std::string_view s1, const std::string_view s2, const std::string_view s3, const std::string_view s4) const; +}; + +} + +} diff --git a/ast_resolver.cpp b/ast_resolver.cpp new file mode 100644 index 0000000..c4f6db8 --- /dev/null +++ b/ast_resolver.cpp @@ -0,0 +1,186 @@ +#include "ast_resolver.hpp" + +namespace dsp { + +namespace ast { + +// expressions + +void resolver_t::visit(const binary_t * binary) const +{ + (void)binary; +} + +void resolver_t::visit(const grouping_t * grouping) const +{ + (void)grouping; +} + +void resolver_t::visit(const identifier_t * identifier) const +{ + (void)identifier; +} + +void resolver_t::visit(const literal_t * literal) const +{ + (void)literal; +} + +void resolver_t::visit(const unary_t * unary) const +{ + (void)unary; +} + +// instructions + +void resolver_t::visit(const op::alu_t * alu) const +{ + (void)alu; +} + +void resolver_t::visit(const op::mov_ram_x_t * mov_ram_x) const +{ + (void)mov_ram_x; +} + +void resolver_t::visit(const op::mov_mul_p_t * mov_mul_p) const +{ + (void)mov_mul_p; +} + +void resolver_t::visit(const op::mov_ram_p_t * mov_ram_p) const +{ + (void)mov_ram_p; +} + +void resolver_t::visit(const op::mov_ram_y_t * mov_ram_y) const +{ + (void)mov_ram_y; +} + +void resolver_t::visit(const op::clr_a_t * clr_a) const +{ + (void)clr_a; +} + +void resolver_t::visit(const op::mov_alu_a_t * mov_alu_a) const +{ + (void)mov_alu_a; +} + +void resolver_t::visit(const op::mov_ram_a_t * mov_ram_a) const +{ + (void)mov_ram_a; +} + +void resolver_t::visit(const op::mov_imm_d1_t * mov_imm_d1) const +{ + (void)mov_imm_d1; +} + +void resolver_t::visit(const op::mov_ram_d1_t * mov_ram_d1) const +{ + (void)mov_ram_d1; +} + +void resolver_t::visit(const op::control_word_t * control_word) const +{ + (void)control_word; + pc.increment(); +} + +void resolver_t::visit(const load::mvi_t * mvi) const +{ + (void)mvi; + pc.increment(); +} + +void resolver_t::visit(const load::mvi_cond_t * mvi_cond) const +{ + (void)mvi_cond; + pc.increment(); +} + +void resolver_t::visit(const dma::src_d0_imm_t * src_d0_imm) const +{ + (void)src_d0_imm; + pc.increment(); +} + +void resolver_t::visit(const dma::d0_dst_imm_t * d0_dst_imm) const +{ + (void)d0_dst_imm; + pc.increment(); +} + +void resolver_t::visit(const dma::src_d0_ram_t * src_d0_ram) const +{ + (void)src_d0_ram; + pc.increment(); +} + +void resolver_t::visit(const dma::d0_dst_ram_t * d0_dst_ram) const +{ + (void)d0_dst_ram; + pc.increment(); +} + +void resolver_t::visit(const jump::jmp_t * jmp) const +{ + (void)jmp; + pc.increment(); +} + +void resolver_t::visit(const jump::jmp_cond_t * jmp_cond) const +{ + (void)jmp_cond; + pc.increment(); +} + +void resolver_t::visit(const loop::btm_t * btm) const +{ + (void)btm; + pc.increment(); +} + +void resolver_t::visit(const loop::lps_t * lps) const +{ + (void)lps; + pc.increment(); +} + +void resolver_t::visit(const end::end_t * end) const +{ + (void)end; + pc.increment(); +} + +void resolver_t::visit(const end::endi_t * endi) const +{ + (void)endi; + pc.increment(); +} + +void resolver_t::visit(const nop::nop_t * nop) const +{ + (void)nop; + pc.increment(); +} + +void resolver_t::visit(const assign_t * assign) const +{ + (void)assign; +} + +void resolver_t::visit(const label_t * label) const +{ + if (addresses.contains(label->name.lexeme)) { + throw std::runtime_error("label redefinition is not allowed"); + } else { + addresses.insert({label->name.lexeme, pc.value}); + } +} + +} + +} diff --git a/ast_resolver.hpp b/ast_resolver.hpp new file mode 100644 index 0000000..5959b33 --- /dev/null +++ b/ast_resolver.hpp @@ -0,0 +1,77 @@ +#pragma once + +#include +#include +#include +#include + +#include "visitor.hpp" +#include "expr.hpp" +#include "stmt.hpp" +#include "ast.hpp" + +namespace dsp { + +namespace ast { + +struct pc_t +{ + pc_t() + : value() {} + + uint32_t value; + void increment() { value += 1; } +}; + +struct resolver_t : visitor_t +{ + resolver_t(pc_t& pc, addresses_t& addresses) + : pc(pc), addresses(addresses) {} + + pc_t& pc; + addresses_t& addresses; + + void visit(const binary_t * binary) const; + void visit(const grouping_t * grouping) const; + void visit(const identifier_t * identifier) const; + void visit(const literal_t * literal) const; + void visit(const unary_t * unary) const; + + void visit(const op::alu_t * alu) const; + void visit(const op::mov_ram_x_t * mov_ram_x) const; + void visit(const op::mov_mul_p_t * mov_mul_p) const; + void visit(const op::mov_ram_p_t * mov_ram_p) const; + void visit(const op::mov_ram_y_t * mov_ram_y) const; + void visit(const op::clr_a_t * clr_a) const; + void visit(const op::mov_alu_a_t * mov_alu_a) const; + void visit(const op::mov_ram_a_t * mov_ram_a) const; + void visit(const op::mov_imm_d1_t * mov_imm_d1) const; + void visit(const op::mov_ram_d1_t * mov_ram_d1) const; + void visit(const op::control_word_t * control_word) const; + + void visit(const load::mvi_t * mvi) const; + void visit(const load::mvi_cond_t * mvi_cond) const; + + void visit(const dma::src_d0_imm_t * src_d0_imm) const; + void visit(const dma::d0_dst_imm_t * d0_dst_imm) const; + void visit(const dma::src_d0_ram_t * src_d0_ram) const; + void visit(const dma::d0_dst_ram_t * d0_dst_ram) const; + + void visit(const jump::jmp_t * jmp) const; + void visit(const jump::jmp_cond_t * jmp_cond) const; + + void visit(const loop::btm_t * btm) const; + void visit(const loop::lps_t * lps) const; + + void visit(const end::end_t * end) const; + void visit(const end::endi_t * endi) const; + + void visit(const nop::nop_t * nop) const; + + void visit(const assign_t * assign) const; + void visit(const label_t * label) const; +}; + +} + +} diff --git a/expr.hpp b/expr.hpp index db2becc..af636f3 100644 --- a/expr.hpp +++ b/expr.hpp @@ -11,7 +11,7 @@ namespace dsp { struct expr_t { virtual void accept(visitor_t const * visitor) const = 0; - virtual std::string accept(visitor_t const * visitor) const = 0; + virtual uint32_t accept(visitor_t const * visitor) const = 0; }; template @@ -20,7 +20,7 @@ struct expr_accept_t : expr_t { return visitor->visit(static_cast(this)); } - virtual std::string accept(visitor_t const * visitor) const + virtual uint32_t accept(visitor_t const * visitor) const { return visitor->visit(static_cast(this)); } diff --git a/main.cpp b/main.cpp index 00a53f8..5b7d303 100644 --- a/main.cpp +++ b/main.cpp @@ -2,10 +2,13 @@ #include #include #include +#include #include "lexer.hpp" #include "token.hpp" -#include "ast.hpp" +#include "ast_printer.hpp" +#include "ast_resolver.hpp" +#include "ast_emitter.hpp" #include "parser.hpp" namespace dsp { @@ -21,13 +24,25 @@ static void run(std::string source) std::string_view buf(source); lexer_t lexer(buf); std::vector tokens = lexer.lex_tokens(); - parser_t parser(tokens); - std::optional stmt_o = parser.statement(); - if (stmt_o) { - dsp::ast_printer_t p(std::cout); - (*stmt_o)->accept(&p); + parser_t pass1(tokens); + parser_t pass2(tokens); + ast::printer_t printer(std::cout); + ast::pc_t pc; + ast::addresses_t addresses; + ast::resolver_t resolver(pc, addresses); + while (auto stmt_o = pass1.statement()) { + (*stmt_o)->accept(&printer); + std::cout << std::endl << std::flush; + (*stmt_o)->accept(&resolver); + } + ast::variables_t variables; + ast::emitter_t emitter(variables, addresses); + while (auto stmt_o = pass2.statement()) { + uint32_t output = (*stmt_o)->accept(&emitter); + if (output != 0xffff'ffff) { + std::cout << std::bitset<32>(output) << std::endl; + } } - std::cout << std::endl << std::flush; } static void run_prompt() diff --git a/stmt.hpp b/stmt.hpp index bc326d7..5f1d651 100644 --- a/stmt.hpp +++ b/stmt.hpp @@ -12,7 +12,7 @@ namespace dsp { struct stmt_t { virtual void accept(visitor_t const * visitor) const = 0; - virtual std::string accept(visitor_t const * visitor) const = 0; + virtual uint32_t accept(visitor_t const * visitor) const = 0; }; template @@ -21,7 +21,7 @@ struct stmt_accept_t : stmt_t { return visitor->visit(static_cast(this)); } - virtual std::string accept(visitor_t const * visitor) const + virtual uint32_t accept(visitor_t const * visitor) const { return visitor->visit(static_cast(this)); } @@ -36,6 +36,13 @@ struct imm_t { static constexpr bool sign = S; static constexpr int bits = N; + + bool in_range(num_t value) const + { + constexpr num_t max = (1L << (bits - static_cast(sign))) - 1; + constexpr num_t min = sign ? -(max + 1) : 0; + return value <= max && value >= min; + } }; template