ast: improve error messages
This commit is contained in:
parent
d4e6c1c717
commit
7f69f6b2e1
@ -1,11 +1,33 @@
|
||||
#include <unordered_map>
|
||||
|
||||
#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 <bool S, int N>
|
||||
static emitter_error_t imm_out_of_range(const imm_t<S, N>& imm, num_t value)
|
||||
{
|
||||
using imm_type = imm_t<S, N>;
|
||||
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});
|
||||
|
@ -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<uint32_t>
|
||||
{
|
||||
emitter_t(variables_t& variables, const addresses_t& addresses)
|
||||
|
16
parser.cpp
16
parser.cpp
@ -280,7 +280,8 @@ std::optional<op::op_t *> 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<stmt_t *> 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<stmt_t *> 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<stmt_t *> 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<stmt_t *> 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
|
||||
|
13
stmt.hpp
13
stmt.hpp
@ -29,18 +29,19 @@ struct stmt_accept_t : stmt_t {
|
||||
|
||||
template <bool S, int N>
|
||||
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<num_t>(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<num_t>(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>
|
||||
{
|
||||
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 ); }
|
||||
|
Loading…
x
Reference in New Issue
Block a user