Report error when index is too large
This commit is contained in:
parent
3b1500313c
commit
1597b678e1
@ -166,6 +166,16 @@ namespace errors
|
||||
std::string name;
|
||||
};
|
||||
|
||||
/// When user tries to get element from collection with index higher then collection size
|
||||
struct Out_Of_Range
|
||||
{
|
||||
/// Index that was required by the user
|
||||
size_t required_index;
|
||||
|
||||
/// Size of accessed collection
|
||||
size_t size;
|
||||
};
|
||||
|
||||
/// Collection of messages that are considered internal and should not be printed to the end user.
|
||||
namespace internal
|
||||
{
|
||||
@ -191,6 +201,7 @@ namespace errors
|
||||
Missing_Variable,
|
||||
Not_Callable,
|
||||
Operation_Requires_Midi_Connection,
|
||||
Out_Of_Range,
|
||||
Undefined_Operator,
|
||||
Unexpected_Empty_Source,
|
||||
Unexpected_Keyword,
|
||||
|
@ -145,6 +145,7 @@ std::ostream& operator<<(std::ostream& os, Error const& err)
|
||||
[](errors::internal::Unexpected_Token const&) { return "Unexpected token"; },
|
||||
[](errors::Expected_Expression_Separator_Before const&) { return "Missing semicolon"; },
|
||||
[](errors::Literal_As_Identifier const&) { return "Literal used in place of an identifier"; },
|
||||
[](errors::Out_Of_Range const&) { return "Index out of range"; },
|
||||
[](errors::Unsupported_Types_For const& type) {
|
||||
return type.type == errors::Unsupported_Types_For::Function
|
||||
? "Function called with wrong arguments"
|
||||
@ -339,6 +340,18 @@ std::ostream& operator<<(std::ostream& os, Error const& err)
|
||||
}
|
||||
os << '\n' << pretty::end;
|
||||
},
|
||||
|
||||
[&](errors::Out_Of_Range const& err) {
|
||||
if (err.size == 0) {
|
||||
os << "Can't get " << err.required_index << " element out of empty collection\n";
|
||||
} else {
|
||||
os << "Can't get " << err.required_index << " element from collection with only " << err.size << " elements\n";
|
||||
}
|
||||
|
||||
os << '\n';
|
||||
print_error_line(loc);
|
||||
},
|
||||
|
||||
[&](errors::Unexpected_Keyword const&) { unimplemented(); },
|
||||
}, err.details);
|
||||
|
||||
|
15
src/value.cc
15
src/value.cc
@ -348,16 +348,25 @@ Result<Value> Block::operator()(Interpreter &i, std::vector<Value> arguments)
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Helper that produces error when trying to access container with too few elements for given index
|
||||
static inline Result<void> guard_index(unsigned index, unsigned size)
|
||||
{
|
||||
if (index < size) return {};
|
||||
return Error {
|
||||
.details = errors::Out_Of_Range { .required_index = index, .size = size }
|
||||
};
|
||||
}
|
||||
|
||||
// TODO Add memoization
|
||||
Result<Value> Block::index(Interpreter &i, unsigned position)
|
||||
{
|
||||
assert(parameters.size() == 0, "cannot index into block with parameters (for now)");
|
||||
if (body.type != Ast::Type::Sequence) {
|
||||
assert(position == 0, "Out of range"); // TODO(assert)
|
||||
Try(guard_index(position, 1));
|
||||
return i.eval((Ast)body);
|
||||
}
|
||||
|
||||
assert(position < body.arguments.size(), "Out of range"); // TODO(assert)
|
||||
Try(guard_index(position, body.arguments.size()));
|
||||
return i.eval((Ast)body.arguments[position]);
|
||||
}
|
||||
|
||||
@ -368,7 +377,7 @@ usize Block::size() const
|
||||
|
||||
Result<Value> Array::index(Interpreter &, unsigned position)
|
||||
{
|
||||
assert(position < elements.size(), "Out of range"); // TODO(assert)
|
||||
Try(guard_index(position, elements.size()));
|
||||
return elements[position];
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user