ast: improve error messages
This commit is contained in:
parent
d4e6c1c717
commit
7f69f6b2e1
@ -1,11 +1,33 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "ast_emitter.hpp"
|
#include "ast_emitter.hpp"
|
||||||
|
#include "error.hpp"
|
||||||
|
|
||||||
namespace dsp {
|
namespace dsp {
|
||||||
|
|
||||||
namespace ast {
|
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
|
// expressions
|
||||||
|
|
||||||
uint32_t emitter_t::visit(const binary_t * binary) const
|
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)) {
|
if (variables.contains(identifier->name.lexeme)) {
|
||||||
return variables.at(identifier->name.lexeme);
|
return variables.at(identifier->name.lexeme);
|
||||||
} else {
|
} 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))
|
if (mov_imm_d1->imm.in_range(value))
|
||||||
return mov_imm_d1->code() | mov_imm_d1->bits() | value;
|
return mov_imm_d1->code() | mov_imm_d1->bits() | value;
|
||||||
else
|
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
|
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
|
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
|
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
|
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))
|
if (src_d0_imm->imm.in_range(value))
|
||||||
return src_d0_imm->code() | src_d0_imm->bits() | value;
|
return src_d0_imm->code() | src_d0_imm->bits() | value;
|
||||||
else
|
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
|
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))
|
if (d0_dst_imm->imm.in_range(value))
|
||||||
return d0_dst_imm->code() | d0_dst_imm->bits() | value;
|
return d0_dst_imm->code() | d0_dst_imm->bits() | value;
|
||||||
else
|
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
|
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
|
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
|
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
|
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
|
uint32_t emitter_t::visit(const assign_t * assign) const
|
||||||
{
|
{
|
||||||
if (variables.contains(assign->name.lexeme)) {
|
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 {
|
} else {
|
||||||
num_t value = assign->value->accept(this);
|
num_t value = assign->value->accept(this);
|
||||||
variables.insert({assign->name.lexeme, value});
|
variables.insert({assign->name.lexeme, value});
|
||||||
|
@ -13,6 +13,13 @@ namespace dsp {
|
|||||||
|
|
||||||
namespace ast {
|
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>
|
struct emitter_t : visitor_t<uint32_t>
|
||||||
{
|
{
|
||||||
emitter_t(variables_t& variables, const addresses_t& addresses)
|
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
|
else
|
||||||
throw error(peek(), "expected x-bus, y-bus, or d-bus destination operand");
|
throw error(peek(), "expected x-bus, y-bus, or d-bus destination operand");
|
||||||
} else {
|
} 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())
|
if (auto dest_o = d1_dest())
|
||||||
return {new op::mov_imm_d1_t(imm, *dest_o)};
|
return {new op::mov_imm_d1_t(imm, *dest_o)};
|
||||||
else
|
else
|
||||||
@ -365,15 +366,16 @@ load::cond_t parser_t::load_cond()
|
|||||||
std::optional<stmt_t *> parser_t::load()
|
std::optional<stmt_t *> parser_t::load()
|
||||||
{
|
{
|
||||||
if (match(_mvi)) {
|
if (match(_mvi)) {
|
||||||
|
const token_t& expr_token = peek();
|
||||||
expr_t * expr = expression();
|
expr_t * expr = expression();
|
||||||
consume(comma, "expected `,`");
|
consume(comma, "expected `,`");
|
||||||
load::dest_t dest = parser_t::load_dest();
|
load::dest_t dest = parser_t::load_dest();
|
||||||
if (match(comma)) {
|
if (match(comma)) {
|
||||||
load::cond_t cond = load_cond();
|
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)};
|
return {new load::mvi_cond_t(imm, dest, cond)};
|
||||||
} else {
|
} 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)};
|
return {new load::mvi_t(imm, dest)};
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
@ -510,7 +512,7 @@ std::optional<stmt_t *> parser_t::dma()
|
|||||||
if (auto length_ram_o = dma_length_ram()) {
|
if (auto length_ram_o = dma_length_ram()) {
|
||||||
return {new dma::d0_dst_ram_t(hold, add, dst, *length_ram_o)};
|
return {new dma::d0_dst_ram_t(hold, add, dst, *length_ram_o)};
|
||||||
} else {
|
} 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)};
|
return {new dma::d0_dst_imm_t(hold, add, dst, imm)};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -521,7 +523,7 @@ std::optional<stmt_t *> parser_t::dma()
|
|||||||
if (auto length_ram_o = dma_length_ram()) {
|
if (auto length_ram_o = dma_length_ram()) {
|
||||||
return {new dma::src_d0_ram_t(hold, add, src, *length_ram_o)};
|
return {new dma::src_d0_ram_t(hold, add, src, *length_ram_o)};
|
||||||
} else {
|
} 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)};
|
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 (match(_jmp)) {
|
||||||
if (auto cond_o = jump_cond()) {
|
if (auto cond_o = jump_cond()) {
|
||||||
consume(comma, "expected `,` after jump condition");
|
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)};
|
return {new jump::jmp_cond_t(*cond_o, imm)};
|
||||||
} else {
|
} else {
|
||||||
uimm_t<8> imm = uimm_t<8>(expression());
|
uimm_t<8> imm = uimm_t<8>(peek(), expression());
|
||||||
return {new jump::jmp_t(imm)};
|
return {new jump::jmp_t(imm)};
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
|
13
stmt.hpp
13
stmt.hpp
@ -29,18 +29,19 @@ struct stmt_accept_t : stmt_t {
|
|||||||
|
|
||||||
template <bool S, int N>
|
template <bool S, int N>
|
||||||
struct imm_t {
|
struct imm_t {
|
||||||
imm_t(expr_t * expr)
|
imm_t(const token_t& token, const expr_t * expr)
|
||||||
: expr(expr) {}
|
: token(token), expr(expr) {}
|
||||||
|
|
||||||
|
const token_t& token;
|
||||||
const expr_t * expr;
|
const expr_t * expr;
|
||||||
|
|
||||||
static constexpr bool sign = S;
|
static constexpr bool sign = S;
|
||||||
static constexpr int bits = N;
|
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
|
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;
|
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>
|
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) {}
|
: imm(imm), dest(dest) {}
|
||||||
|
|
||||||
const simm_t<8> imm;
|
const uimm_t<8> imm;
|
||||||
const d1_dest_t dest;
|
const d1_dest_t dest;
|
||||||
|
|
||||||
uint32_t mask() const { return op_mask(0b11'1111'1111'1111 << 0 ); }
|
uint32_t mask() const { return op_mask(0b11'1111'1111'1111 << 0 ); }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user