Eliminated unimplemented() that ware missing error reporting

This commit is contained in:
Robert Bendun 2022-09-21 13:36:58 +02:00
parent 3ed11fd33b
commit 1384e5f96e
7 changed files with 94 additions and 16 deletions

View File

@ -122,6 +122,22 @@ namespace errors
std::string_view op; std::string_view op;
}; };
/// When user tries to use operator with wrong arity of arguments
struct Wrong_Arity_Of
{
/// Type of operation
enum Type { Operator, Function } type;
/// Name of operation
std::string_view name;
/// Arity that was expected by given operation
size_t expected_arity;
/// Arit that user provided
size_t actual_arity;
};
/// When user tried to call something that can't be called /// When user tried to call something that can't be called
struct Not_Callable struct Not_Callable
{ {
@ -227,6 +243,7 @@ namespace errors
Unexpected_Keyword, Unexpected_Keyword,
Unrecognized_Character, Unrecognized_Character,
Unsupported_Types_For, Unsupported_Types_For,
Wrong_Arity_Of,
internal::Unexpected_Token internal::Unexpected_Token
>; >;
} }

View File

@ -350,7 +350,14 @@ static Result<Value> builtin_sim(Interpreter &interpreter, std::vector<Value> ar
return {}; return {};
} }
unimplemented(); // Invalid type for sim function
return errors::Unsupported_Types_For {
.type = errors::Unsupported_Types_For::Function,
.name = "sim",
.possibilities = {
"(music | array of music)+"
},
};
} }
} append { interpreter }; } append { interpreter };
@ -600,7 +607,17 @@ static Result<Value> builtin_try(Interpreter &interpreter, std::vector<Value> ar
/// Update value inside of array /// Update value inside of array
static Result<Value> builtin_update(Interpreter &i, std::vector<Value> args) static Result<Value> builtin_update(Interpreter &i, std::vector<Value> args)
{ {
assert(args.size() == 3, "Update requires 3 arguments"); // TODO(assert) auto const guard = Guard<1> {
.name = "update",
.possibilities = {
"array index:number new_value"
}
};
if (args.size() != 3) {
return guard.yield_error();
}
using Eager_And_Number = Shape<Value::Type::Array, Value::Type::Number>; using Eager_And_Number = Shape<Value::Type::Array, Value::Type::Number>;
using Lazy_And_Number = Shape<Value::Type::Block, Value::Type::Number>; using Lazy_And_Number = Shape<Value::Type::Block, Value::Type::Number>;
@ -617,7 +634,7 @@ static Result<Value> builtin_update(Interpreter &i, std::vector<Value> args)
return Value::from(std::move(array)); return Value::from(std::move(array));
} }
unimplemented("Wrong shape of update function"); return guard.yield_error();
} }
/// Return typeof variable /// Return typeof variable

View File

@ -134,18 +134,19 @@ void unreachable(Location loc)
std::ostream& operator<<(std::ostream& os, Error const& err) std::ostream& operator<<(std::ostream& os, Error const& err)
{ {
std::string_view short_description = visit(Overloaded { std::string_view short_description = visit(Overloaded {
[](errors::Operation_Requires_Midi_Connection const&) { return "Operation requires MIDI connection"; }, [](errors::Expected_Expression_Separator_Before const&) { return "Missing semicolon"; },
[](errors::Missing_Variable const&) { return "Cannot find variable"; },
[](errors::Failed_Numeric_Parsing const&) { return "Failed to parse a number"; }, [](errors::Failed_Numeric_Parsing const&) { return "Failed to parse a number"; },
[](errors::Literal_As_Identifier const&) { return "Literal used in place of an identifier"; },
[](errors::Missing_Variable const&) { return "Cannot find variable"; },
[](errors::Not_Callable const&) { return "Value not callable"; }, [](errors::Not_Callable const&) { return "Value not callable"; },
[](errors::Operation_Requires_Midi_Connection const&) { return "Operation requires MIDI connection"; },
[](errors::Out_Of_Range const&) { return "Index out of range"; },
[](errors::Undefined_Operator const&) { return "Undefined operator"; }, [](errors::Undefined_Operator const&) { return "Undefined operator"; },
[](errors::Unexpected_Empty_Source const&) { return "Unexpected end of file"; }, [](errors::Unexpected_Empty_Source const&) { return "Unexpected end of file"; },
[](errors::Unexpected_Keyword const&) { return "Unexpected keyword"; }, [](errors::Unexpected_Keyword const&) { return "Unexpected keyword"; },
[](errors::Unrecognized_Character const&) { return "Unrecognized character"; }, [](errors::Unrecognized_Character const&) { return "Unrecognized character"; },
[](errors::Wrong_Arity_Of const&) { return "Different arity then expected"; },
[](errors::internal::Unexpected_Token const&) { return "Unexpected token"; }, [](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::Arithmetic const& err) { [](errors::Arithmetic const& err) {
switch (err.type) { switch (err.type) {
case errors::Arithmetic::Division_By_Zero: return "Division by 0"; case errors::Arithmetic::Division_By_Zero: return "Division by 0";
@ -296,6 +297,19 @@ std::ostream& operator<<(std::ostream& os, Error const& err)
} }
}, },
[&](errors::Wrong_Arity_Of const& err) {
switch (err.type) {
break; case errors::Wrong_Arity_Of::Function:
os << "Function " << err.name << " expects " << err.expected_arity << " arguments but you provided " << err.actual_arity << "\n";
os << "\n";
print_error_line(loc);
break; case errors::Wrong_Arity_Of::Operator:
os << "Operator " << err.name << " expects " << err.expected_arity << " arguments but you provided " << err.actual_arity << "\n";
os << "\n";
print_error_line(loc);
}
},
[&](errors::Not_Callable const& err) { [&](errors::Not_Callable const& err) {
os << "Value of type " << err.type << " cannot be called.\n"; os << "Value of type " << err.type << " cannot be called.\n";
os << "\n"; os << "\n";
@ -403,7 +417,11 @@ std::ostream& operator<<(std::ostream& os, Error const& err)
} }
}, },
[&](errors::Unexpected_Keyword const&) { unimplemented(); }, [&](errors::Unexpected_Keyword const& err) {
os << "Keyword " << err.keyword << " should not be used here\n\n";
print_error_line(loc);
},
}, err.details); }, err.details);
return os; return os;

View File

@ -201,10 +201,9 @@ Result<Value> Interpreter::eval(Ast &&ast)
block.body = std::move(ast.arguments.back()); block.body = std::move(ast.arguments.back());
return Value::from(std::move(block)); return Value::from(std::move(block));
} }
default:
unimplemented();
} }
unreachable();
} }
void Interpreter::enter_scope() void Interpreter::enter_scope()

View File

@ -332,7 +332,7 @@ Result<Number> Number::pow(Number n) const
// Hard case, we raise this to fractional power. // Hard case, we raise this to fractional power.
// Essentialy finding n.den root of (x to n.num power). // Essentialy finding n.den root of (x to n.num power).
// We need to protect ourselfs against even roots of negative numbers. // We need to protect ourselfs against even roots of negative numbers.
unimplemented(); unimplemented("nth root calculation is not implemented yet");
} }
std::size_t std::hash<Number>::operator()(Number const& value) const std::size_t std::hash<Number>::operator()(Number const& value) const

View File

@ -310,6 +310,18 @@ Result<Ast> Parser::parse_atomic_expression()
return ast; return ast;
} }
break; case Token::Type::Operator:
return Error {
.details = errors::Wrong_Arity_Of {
.type = errors::Wrong_Arity_Of::Operator,
.name = peek()->source,
.expected_arity = 2, // TODO This should be resolved based on operator
.actual_arity = 0,
},
.location = peek()->location,
};
default: default:
return Error { return Error {
.details = errors::internal::Unexpected_Token { .details = errors::internal::Unexpected_Token {

View File

@ -71,7 +71,7 @@ Result<Value> Value::from(Token t)
return Value::from(Chord::from(t.source)); return Value::from(Chord::from(t.source));
default: default:
unimplemented(); unreachable();
} }
} }
@ -329,7 +329,16 @@ Result<Value> Block::operator()(Interpreter &i, std::vector<Value> arguments)
auto old_scope = std::exchange(i.env, context); auto old_scope = std::exchange(i.env, context);
i.enter_scope(); i.enter_scope();
assert(parameters.size() == arguments.size(), "wrong number of arguments"); if (parameters.size() != arguments.size()) {
return errors::Wrong_Arity_Of {
.type = errors::Wrong_Arity_Of::Function,
// TODO Let user defined functions have name of their first assigment (Zig like)
// or from place of definition like <block at file:line:column>
.name = "<block>",
.expected_arity = parameters.size(),
.actual_arity = arguments.size(),
};
}
for (usize j = 0; j < parameters.size(); ++j) { for (usize j = 0; j < parameters.size(); ++j) {
i.env->force_define(parameters[j], std::move(arguments[j])); i.env->force_define(parameters[j], std::move(arguments[j]));
@ -521,7 +530,13 @@ Result<Value> Chord::operator()(Interpreter&, std::vector<Value> args)
continue; continue;
default: default:
unimplemented(); return errors::Unsupported_Types_For {
.type = errors::Unsupported_Types_For::Function,
.name = "note creation",
.possibilities = {
"(note:music [octave:number [duration:number]])+"
}
};
} }
} }