From 7f69f6b2e1c4fb932238a83d24c6ec60eff84ba1 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Wed, 23 Aug 2023 20:23:09 +0000 Subject: [PATCH] ast: improve error messages --- ast_emitter.cpp | 56 +++++++++++++++++++++++++++++++++++++++++-------- ast_emitter.hpp | 7 +++++++ parser.cpp | 16 +++++++------- stmt.hpp | 13 ++++++------ 4 files changed, 70 insertions(+), 22 deletions(-) diff --git a/ast_emitter.cpp b/ast_emitter.cpp index e506f88..1b804de 100644 --- a/ast_emitter.cpp +++ b/ast_emitter.cpp @@ -1,11 +1,33 @@ #include #include "ast_emitter.hpp" +#include "error.hpp" namespace dsp { namespace ast { +static emitter_error_t error(const token_t& token, const std::string message) +{ + dsp::error(token, message); + return emitter_error_t(message); +} + +template +static emitter_error_t imm_out_of_range(const imm_t& imm, num_t value) +{ + using imm_type = imm_t; + std::string message = "immediate value is out of range"; + dsp::error(imm.token, message); + std::cerr << "note:" << std::endl + << " expect range: [" + << imm_type::min << ',' << imm_type::max + << ']' << std::endl + << " actual value: " << value << std::endl; + + return emitter_error_t(message); +} + // expressions uint32_t emitter_t::visit(const binary_t * binary) const @@ -41,7 +63,7 @@ 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"); + throw ast::error(identifier->name, "undefined identifier"); } } @@ -113,7 +135,7 @@ uint32_t emitter_t::visit(const op::mov_imm_d1_t * mov_imm_d1) const 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"); + throw imm_out_of_range(mov_imm_d1->imm, value); } uint32_t emitter_t::visit(const op::mov_ram_d1_t * mov_ram_d1) const @@ -130,12 +152,20 @@ uint32_t emitter_t::visit(const op::control_word_t * control_word) const uint32_t emitter_t::visit(const load::mvi_t * mvi) const { - return mvi->code() | mvi->bits(); + num_t value = mvi->imm.expr->accept(this); + if (mvi->imm.in_range(value)) + return mvi->code() | mvi->bits() | value; + else + throw imm_out_of_range(mvi->imm, value); } uint32_t emitter_t::visit(const load::mvi_cond_t * mvi_cond) const { - return mvi_cond->code() | mvi_cond->bits(); + num_t value = mvi_cond->imm.expr->accept(this); + if (mvi_cond->imm.in_range(value)) + return mvi_cond->code() | mvi_cond->bits() | value; + else + throw imm_out_of_range(mvi_cond->imm, value); } uint32_t emitter_t::visit(const dma::src_d0_imm_t * src_d0_imm) const @@ -144,7 +174,7 @@ uint32_t emitter_t::visit(const dma::src_d0_imm_t * src_d0_imm) const 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"); + throw imm_out_of_range(src_d0_imm->imm, value); } uint32_t emitter_t::visit(const dma::d0_dst_imm_t * d0_dst_imm) const @@ -153,7 +183,7 @@ uint32_t emitter_t::visit(const dma::d0_dst_imm_t * d0_dst_imm) const 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"); + throw imm_out_of_range(d0_dst_imm->imm, value); } uint32_t emitter_t::visit(const dma::src_d0_ram_t * src_d0_ram) const @@ -168,12 +198,20 @@ uint32_t emitter_t::visit(const dma::d0_dst_ram_t * d0_dst_ram) const uint32_t emitter_t::visit(const jump::jmp_t * jmp) const { - return jmp->code() | jmp->bits(); + num_t value = jmp->imm.expr->accept(this); + if (jmp->imm.in_range(value)) + return jmp->code() | jmp->bits() | value; + else + throw imm_out_of_range(jmp->imm, value); } uint32_t emitter_t::visit(const jump::jmp_cond_t * jmp_cond) const { - return jmp_cond->code() | jmp_cond->bits(); + num_t value = jmp_cond->imm.expr->accept(this); + if (jmp_cond->imm.in_range(value)) + return jmp_cond->code() | jmp_cond->bits() | value; + else + throw imm_out_of_range(jmp_cond->imm, value); } uint32_t emitter_t::visit(const loop::btm_t * btm) const @@ -204,7 +242,7 @@ uint32_t emitter_t::visit(const nop::nop_t * nop) const 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"); + throw ast::error(assign->name, "assignment redefinition is not allowed"); } else { num_t value = assign->value->accept(this); variables.insert({assign->name.lexeme, value}); diff --git a/ast_emitter.hpp b/ast_emitter.hpp index dc7d522..988041a 100644 --- a/ast_emitter.hpp +++ b/ast_emitter.hpp @@ -13,6 +13,13 @@ namespace dsp { namespace ast { +struct emitter_error_t : std::runtime_error +{ + emitter_error_t(const std::string& msg) + : std::runtime_error(msg) + { } +}; + struct emitter_t : visitor_t { emitter_t(variables_t& variables, const addresses_t& addresses) diff --git a/parser.cpp b/parser.cpp index f86157a..7eef07b 100644 --- a/parser.cpp +++ b/parser.cpp @@ -280,7 +280,8 @@ std::optional parser_t::xyd1_bus() else throw error(peek(), "expected x-bus, y-bus, or d-bus destination operand"); } else { - simm_t<8> imm = simm_t<8>(expression()); + uimm_t<8> imm = uimm_t<8>(peek(), expression()); + consume(comma, "expected `,`"); if (auto dest_o = d1_dest()) return {new op::mov_imm_d1_t(imm, *dest_o)}; else @@ -365,15 +366,16 @@ load::cond_t parser_t::load_cond() std::optional parser_t::load() { if (match(_mvi)) { + const token_t& expr_token = peek(); expr_t * expr = expression(); consume(comma, "expected `,`"); load::dest_t dest = parser_t::load_dest(); if (match(comma)) { load::cond_t cond = load_cond(); - uimm_t<19> imm = uimm_t<19>(expr); + uimm_t<19> imm = uimm_t<19>(expr_token, expr); return {new load::mvi_cond_t(imm, dest, cond)}; } else { - uimm_t<25> imm = uimm_t<25>(expr); + uimm_t<25> imm = uimm_t<25>(expr_token, expr); return {new load::mvi_t(imm, dest)}; } } else @@ -510,7 +512,7 @@ std::optional parser_t::dma() if (auto length_ram_o = dma_length_ram()) { return {new dma::d0_dst_ram_t(hold, add, dst, *length_ram_o)}; } else { - uimm_t<8> imm = uimm_t<8>(expression()); + uimm_t<8> imm = uimm_t<8>(peek(), expression()); return {new dma::d0_dst_imm_t(hold, add, dst, imm)}; } } else { @@ -521,7 +523,7 @@ std::optional parser_t::dma() if (auto length_ram_o = dma_length_ram()) { return {new dma::src_d0_ram_t(hold, add, src, *length_ram_o)}; } else { - uimm_t<8> imm = uimm_t<8>(expression()); + uimm_t<8> imm = uimm_t<8>(peek(), expression()); return {new dma::src_d0_imm_t(hold, add, src, imm)}; } } @@ -551,10 +553,10 @@ std::optional parser_t::jump() if (match(_jmp)) { if (auto cond_o = jump_cond()) { consume(comma, "expected `,` after jump condition"); - uimm_t<8> imm = uimm_t<8>(expression()); + uimm_t<8> imm = uimm_t<8>(peek(), expression()); return {new jump::jmp_cond_t(*cond_o, imm)}; } else { - uimm_t<8> imm = uimm_t<8>(expression()); + uimm_t<8> imm = uimm_t<8>(peek(), expression()); return {new jump::jmp_t(imm)}; } } else diff --git a/stmt.hpp b/stmt.hpp index 5f1d651..850fd61 100644 --- a/stmt.hpp +++ b/stmt.hpp @@ -29,18 +29,19 @@ struct stmt_accept_t : stmt_t { template struct imm_t { - imm_t(expr_t * expr) - : expr(expr) {} + imm_t(const token_t& token, const expr_t * expr) + : token(token), expr(expr) {} + const token_t& token; const expr_t * expr; static constexpr bool sign = S; static constexpr int bits = N; + static constexpr num_t max = (1L << (bits - static_cast(sign))) - 1; + static constexpr num_t min = sign ? -(max + 1) : 0; 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; } }; @@ -227,10 +228,10 @@ static uint32_t d1_src_bits(d1_src_t src) struct mov_imm_d1_t : op_t, stmt_accept_t { - mov_imm_d1_t(simm_t<8> imm, d1_dest_t dest) + mov_imm_d1_t(uimm_t<8> imm, d1_dest_t dest) : imm(imm), dest(dest) {} - const simm_t<8> imm; + const uimm_t<8> imm; const d1_dest_t dest; uint32_t mask() const { return op_mask(0b11'1111'1111'1111 << 0 ); }