Merge branch 'main' into beta-0.4
This commit is contained in:
commit
472c9ef73f
@ -201,7 +201,12 @@ std::ostream& operator<<(std::ostream& os, Error const& err)
|
|||||||
print_error_line(loc);
|
print_error_line(loc);
|
||||||
|
|
||||||
os << "Variables can only be references in scope (block) where they been created\n";
|
os << "Variables can only be references in scope (block) where they been created\n";
|
||||||
os << "or from parent blocks to variable block\n";
|
os << "or from parent blocks to variable block\n\n";
|
||||||
|
|
||||||
|
pretty::begin_comment(os);
|
||||||
|
os << "Maybe you want to defined it. To do this you must use ':=' operator.\n";
|
||||||
|
os << " name := value\n";
|
||||||
|
pretty::end(os);
|
||||||
},
|
},
|
||||||
[&](errors::Unrecognized_Character const& err) {
|
[&](errors::Unrecognized_Character const& err) {
|
||||||
os << "I encountered character in the source code that was not supposed to be here.\n";
|
os << "I encountered character in the source code that was not supposed to be here.\n";
|
||||||
@ -268,7 +273,7 @@ std::ostream& operator<<(std::ostream& os, Error const& err)
|
|||||||
|
|
||||||
[&](errors::Unsupported_Types_For const& err) {
|
[&](errors::Unsupported_Types_For const& err) {
|
||||||
switch (err.type) {
|
switch (err.type) {
|
||||||
case errors::Unsupported_Types_For::Function:
|
break; case errors::Unsupported_Types_For::Function:
|
||||||
{
|
{
|
||||||
os << "I tried to call function '" << err.name << "' but you gave me wrong types for it!\n";
|
os << "I tried to call function '" << err.name << "' but you gave me wrong types for it!\n";
|
||||||
|
|
||||||
@ -281,9 +286,26 @@ std::ostream& operator<<(std::ostream& os, Error const& err)
|
|||||||
os << " " << possibility << '\n';
|
os << " " << possibility << '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break; case errors::Unsupported_Types_For::Operator:
|
||||||
case errors::Unsupported_Types_For::Operator:
|
|
||||||
{
|
{
|
||||||
|
if (err.name == "=") {
|
||||||
|
os << "Operator '=' expects name on it's left side.\n";
|
||||||
|
os << "\n";
|
||||||
|
|
||||||
|
print_error_line(loc);
|
||||||
|
|
||||||
|
pretty::begin_comment(os);
|
||||||
|
os << "If you want to test if two values are equal use '==' operator:\n";
|
||||||
|
// TODO Maybe we can use code serialization mechanism to print here actual equation
|
||||||
|
// but transformed to account for use of == operator. If produced string is too big
|
||||||
|
// then we can skip and show this silly example
|
||||||
|
os << " 3 == 4\n";
|
||||||
|
os << "If you want to change element of an array use update function:\n";
|
||||||
|
os << " instead of a[i] = x you may write a = update a i x\n";
|
||||||
|
pretty::end(os);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
os << "I tried and failed to evaluate operator '" << err.name << "' due to values with wrong types provided\n";
|
os << "I tried and failed to evaluate operator '" << err.name << "' due to values with wrong types provided\n";
|
||||||
os << "Make sure that both values matches one of supported signatures listed below!\n";
|
os << "Make sure that both values matches one of supported signatures listed below!\n";
|
||||||
os << '\n';
|
os << '\n';
|
||||||
@ -297,7 +319,6 @@ std::ostream& operator<<(std::ostream& os, Error const& err)
|
|||||||
os << " " << possibility << '\n';
|
os << " " << possibility << '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -45,19 +45,19 @@ namespace errors
|
|||||||
/// When user forgot semicolon or brackets
|
/// When user forgot semicolon or brackets
|
||||||
struct Expected_Expression_Separator_Before
|
struct Expected_Expression_Separator_Before
|
||||||
{
|
{
|
||||||
std::string_view what;
|
std::string what;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// When some keywords are not allowed in given context
|
/// When some keywords are not allowed in given context
|
||||||
struct Unexpected_Keyword
|
struct Unexpected_Keyword
|
||||||
{
|
{
|
||||||
std::string_view keyword;
|
std::string keyword;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// When user tried to use operator that was not defined
|
/// When user tried to use operator that was not defined
|
||||||
struct Undefined_Operator
|
struct Undefined_Operator
|
||||||
{
|
{
|
||||||
std::string_view op;
|
std::string op;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// When user tries to use operator with wrong arity of arguments
|
/// When user tries to use operator with wrong arity of arguments
|
||||||
@ -67,7 +67,7 @@ namespace errors
|
|||||||
enum Type { Operator, Function } type;
|
enum Type { Operator, Function } type;
|
||||||
|
|
||||||
/// Name of operation
|
/// Name of operation
|
||||||
std::string_view name;
|
std::string name;
|
||||||
|
|
||||||
/// Arity that was expected by given operation
|
/// Arity that was expected by given operation
|
||||||
size_t expected_arity;
|
size_t expected_arity;
|
||||||
@ -79,15 +79,15 @@ namespace errors
|
|||||||
/// 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
|
||||||
{
|
{
|
||||||
std::string_view type;
|
std::string type;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// When user provides literal where identifier should be
|
/// When user provides literal where identifier should be
|
||||||
struct Literal_As_Identifier
|
struct Literal_As_Identifier
|
||||||
{
|
{
|
||||||
std::string_view type_name;
|
std::string type_name;
|
||||||
std::string_view source;
|
std::string source;
|
||||||
std::string_view context;
|
std::string context;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// When user provides wrong type for given operation
|
/// When user provides wrong type for given operation
|
||||||
@ -108,6 +108,10 @@ namespace errors
|
|||||||
{
|
{
|
||||||
/// Name of variable
|
/// Name of variable
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
||||||
|
// TODO std::vector<std::string> similar_names;
|
||||||
|
// Pull all names reachable from given point and similar onces
|
||||||
|
// put in this array
|
||||||
};
|
};
|
||||||
|
|
||||||
/// When user tries to invoke some MIDI action but haven't established MIDI connection
|
/// When user tries to invoke some MIDI action but haven't established MIDI connection
|
||||||
@ -155,13 +159,13 @@ namespace errors
|
|||||||
struct Unexpected_Token
|
struct Unexpected_Token
|
||||||
{
|
{
|
||||||
/// Type of the token
|
/// Type of the token
|
||||||
std::string_view type;
|
std::string type;
|
||||||
|
|
||||||
/// Source of the token
|
/// Source of the token
|
||||||
std::string_view source;
|
std::string source;
|
||||||
|
|
||||||
/// Where this token was encountered that was unexpected?
|
/// Where this token was encountered that was unexpected?
|
||||||
std::string_view when;
|
std::string when;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,11 +90,27 @@ Result<Value> Interpreter::eval(Ast &&ast)
|
|||||||
if (ast.token.source == "=") {
|
if (ast.token.source == "=") {
|
||||||
auto lhs = std::move(ast.arguments.front());
|
auto lhs = std::move(ast.arguments.front());
|
||||||
auto rhs = std::move(ast.arguments.back());
|
auto rhs = std::move(ast.arguments.back());
|
||||||
ensure(lhs.type == Ast::Type::Literal && lhs.token.type == Token::Type::Symbol,
|
|
||||||
"Currently LHS of assigment must be an identifier"); // TODO(assert)
|
if (lhs.type != Ast::Type::Literal || lhs.token.type != Token::Type::Symbol) {
|
||||||
|
return Error {
|
||||||
|
.details = errors::Unsupported_Types_For {
|
||||||
|
.type = errors::Unsupported_Types_For::Operator,
|
||||||
|
.name = "=",
|
||||||
|
.possibilities = {},
|
||||||
|
},
|
||||||
|
.location = ast.token.location,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
Value *v = env->find(std::string(lhs.token.source));
|
Value *v = env->find(std::string(lhs.token.source));
|
||||||
ensure(v, "Cannot resolve variable: "s + std::string(lhs.token.source)); // TODO(assert)
|
if (v == nullptr) {
|
||||||
|
return Error {
|
||||||
|
.details = errors::Missing_Variable {
|
||||||
|
.name = std::string(lhs.token.source)
|
||||||
|
},
|
||||||
|
.location = lhs.location,
|
||||||
|
};
|
||||||
|
}
|
||||||
return *v = Try(eval(std::move(rhs)).with_location(ast.token.location));
|
return *v = Try(eval(std::move(rhs)).with_location(ast.token.location));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +134,7 @@ Result<Value> Interpreter::eval(Ast &&ast)
|
|||||||
auto op = operators.find(std::string(ast.token.source.substr(0, ast.token.source.size()-1)));
|
auto op = operators.find(std::string(ast.token.source.substr(0, ast.token.source.size()-1)));
|
||||||
if (op == operators.end()) {
|
if (op == operators.end()) {
|
||||||
return Error {
|
return Error {
|
||||||
.details = errors::Undefined_Operator { .op = ast.token.source },
|
.details = errors::Undefined_Operator { .op = std::string(ast.token.source) },
|
||||||
.location = ast.token.location
|
.location = ast.token.location
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -137,7 +153,7 @@ Result<Value> Interpreter::eval(Ast &&ast)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Error {
|
return Error {
|
||||||
.details = errors::Undefined_Operator { .op = ast.token.source },
|
.details = errors::Undefined_Operator { .op = std::string(ast.token.source) },
|
||||||
.location = ast.token.location
|
.location = ast.token.location
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -248,7 +248,7 @@ Result<Ast> Parser::parse_atomic_expression()
|
|||||||
// So we need to explicitly allow only keywords that are also literals
|
// So we need to explicitly allow only keywords that are also literals
|
||||||
if (std::find(Literal_Keywords.begin(), Literal_Keywords.end(), peek()->source) == Literal_Keywords.end()) {
|
if (std::find(Literal_Keywords.begin(), Literal_Keywords.end(), peek()->source) == Literal_Keywords.end()) {
|
||||||
return Error {
|
return Error {
|
||||||
.details = errors::Unexpected_Keyword { .keyword = peek()->source },
|
.details = errors::Unexpected_Keyword { .keyword = std::string(peek()->source) },
|
||||||
.location = peek()->location
|
.location = peek()->location
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -313,8 +313,8 @@ Result<Ast> Parser::parse_atomic_expression()
|
|||||||
if (success && invalid_token) {
|
if (success && invalid_token) {
|
||||||
return Error {
|
return Error {
|
||||||
.details = errors::Literal_As_Identifier {
|
.details = errors::Literal_As_Identifier {
|
||||||
.type_name = type_name(invalid_token->type),
|
.type_name = std::string(type_name(invalid_token->type)),
|
||||||
.source = invalid_token->source,
|
.source = std::string(invalid_token->source),
|
||||||
.context = "block parameter list"
|
.context = "block parameter list"
|
||||||
},
|
},
|
||||||
.location = invalid_token->location
|
.location = invalid_token->location
|
||||||
@ -329,7 +329,7 @@ Result<Ast> Parser::parse_atomic_expression()
|
|||||||
return Error {
|
return Error {
|
||||||
.details = errors::Wrong_Arity_Of {
|
.details = errors::Wrong_Arity_Of {
|
||||||
.type = errors::Wrong_Arity_Of::Operator,
|
.type = errors::Wrong_Arity_Of::Operator,
|
||||||
.name = peek()->source,
|
.name = std::string(peek()->source),
|
||||||
.expected_arity = 2, // TODO This should be resolved based on operator
|
.expected_arity = 2, // TODO This should be resolved based on operator
|
||||||
.actual_arity = 0,
|
.actual_arity = 0,
|
||||||
},
|
},
|
||||||
@ -340,8 +340,8 @@ Result<Ast> Parser::parse_atomic_expression()
|
|||||||
default:
|
default:
|
||||||
return Error {
|
return Error {
|
||||||
.details = errors::internal::Unexpected_Token {
|
.details = errors::internal::Unexpected_Token {
|
||||||
.type = type_name(peek()->type),
|
.type = std::string(type_name(peek()->type)),
|
||||||
.source = peek()->source,
|
.source = std::string(peek()->source),
|
||||||
.when = "atomic expression parsing"
|
.when = "atomic expression parsing"
|
||||||
},
|
},
|
||||||
.location = peek()->location
|
.location = peek()->location
|
||||||
@ -355,8 +355,8 @@ Result<Ast> Parser::parse_identifier_with_trailing_separators()
|
|||||||
// TODO Specific error message
|
// TODO Specific error message
|
||||||
return Error {
|
return Error {
|
||||||
.details = errors::internal::Unexpected_Token {
|
.details = errors::internal::Unexpected_Token {
|
||||||
.type = type_name(peek()->type),
|
.type = std::string(type_name(peek()->type)),
|
||||||
.source = peek()->source,
|
.source = std::string(peek()->source),
|
||||||
.when = "identifier parsing"
|
.when = "identifier parsing"
|
||||||
},
|
},
|
||||||
.location = peek()->location
|
.location = peek()->location
|
||||||
@ -373,8 +373,8 @@ Result<Ast> Parser::parse_identifier()
|
|||||||
// TODO Specific error message
|
// TODO Specific error message
|
||||||
return Error {
|
return Error {
|
||||||
.details = errors::internal::Unexpected_Token {
|
.details = errors::internal::Unexpected_Token {
|
||||||
.type = type_name(peek()->type),
|
.type = std::string(type_name(peek()->type)),
|
||||||
.source = peek()->source,
|
.source = std::string(peek()->source),
|
||||||
.when = "identifier parsing"
|
.when = "identifier parsing"
|
||||||
},
|
},
|
||||||
.location = peek()->location
|
.location = peek()->location
|
||||||
|
@ -113,7 +113,7 @@ Result<Value> Value::operator()(Interpreter &i, std::vector<Value> args) const
|
|||||||
return (*func)(i, std::move(args));
|
return (*func)(i, std::move(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors::Not_Callable { .type = type_name(*this) };
|
return errors::Not_Callable { .type = std::string(type_name(*this)) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user