Merge branch 'main' into beta-0.4

This commit is contained in:
Robert Bendun 2023-01-12 22:58:10 +01:00
commit 472c9ef73f
5 changed files with 73 additions and 32 deletions

View File

@ -201,7 +201,12 @@ std::ostream& operator<<(std::ostream& os, Error const& err)
print_error_line(loc);
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) {
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) {
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";
@ -281,9 +286,26 @@ std::ostream& operator<<(std::ostream& os, Error const& err)
os << " " << possibility << '\n';
}
}
break;
case errors::Unsupported_Types_For::Operator:
break; 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 << "Make sure that both values matches one of supported signatures listed below!\n";
os << '\n';
@ -297,7 +319,6 @@ std::ostream& operator<<(std::ostream& os, Error const& err)
os << " " << possibility << '\n';
}
}
break;
}
},

View File

@ -45,19 +45,19 @@ namespace errors
/// When user forgot semicolon or brackets
struct Expected_Expression_Separator_Before
{
std::string_view what;
std::string what;
};
/// When some keywords are not allowed in given context
struct Unexpected_Keyword
{
std::string_view keyword;
std::string keyword;
};
/// When user tried to use operator that was not defined
struct Undefined_Operator
{
std::string_view op;
std::string op;
};
/// When user tries to use operator with wrong arity of arguments
@ -67,7 +67,7 @@ namespace errors
enum Type { Operator, Function } type;
/// Name of operation
std::string_view name;
std::string name;
/// Arity that was expected by given operation
size_t expected_arity;
@ -79,15 +79,15 @@ namespace errors
/// When user tried to call something that can't be called
struct Not_Callable
{
std::string_view type;
std::string type;
};
/// When user provides literal where identifier should be
struct Literal_As_Identifier
{
std::string_view type_name;
std::string_view source;
std::string_view context;
std::string type_name;
std::string source;
std::string context;
};
/// When user provides wrong type for given operation
@ -108,6 +108,10 @@ namespace errors
{
/// Name of variable
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
@ -155,13 +159,13 @@ namespace errors
struct Unexpected_Token
{
/// Type of the token
std::string_view type;
std::string type;
/// Source of the token
std::string_view source;
std::string source;
/// Where this token was encountered that was unexpected?
std::string_view when;
std::string when;
};
}

View File

@ -90,11 +90,27 @@ Result<Value> Interpreter::eval(Ast &&ast)
if (ast.token.source == "=") {
auto lhs = std::move(ast.arguments.front());
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));
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));
}
@ -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)));
if (op == operators.end()) {
return Error {
.details = errors::Undefined_Operator { .op = ast.token.source },
.details = errors::Undefined_Operator { .op = std::string(ast.token.source) },
.location = ast.token.location
};
}
@ -137,7 +153,7 @@ Result<Value> Interpreter::eval(Ast &&ast)
}
return Error {
.details = errors::Undefined_Operator { .op = ast.token.source },
.details = errors::Undefined_Operator { .op = std::string(ast.token.source) },
.location = ast.token.location
};
}

View File

@ -248,7 +248,7 @@ Result<Ast> Parser::parse_atomic_expression()
// 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()) {
return Error {
.details = errors::Unexpected_Keyword { .keyword = peek()->source },
.details = errors::Unexpected_Keyword { .keyword = std::string(peek()->source) },
.location = peek()->location
};
}
@ -313,8 +313,8 @@ Result<Ast> Parser::parse_atomic_expression()
if (success && invalid_token) {
return Error {
.details = errors::Literal_As_Identifier {
.type_name = type_name(invalid_token->type),
.source = invalid_token->source,
.type_name = std::string(type_name(invalid_token->type)),
.source = std::string(invalid_token->source),
.context = "block parameter list"
},
.location = invalid_token->location
@ -329,7 +329,7 @@ Result<Ast> Parser::parse_atomic_expression()
return Error {
.details = errors::Wrong_Arity_Of {
.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
.actual_arity = 0,
},
@ -340,8 +340,8 @@ Result<Ast> Parser::parse_atomic_expression()
default:
return Error {
.details = errors::internal::Unexpected_Token {
.type = type_name(peek()->type),
.source = peek()->source,
.type = std::string(type_name(peek()->type)),
.source = std::string(peek()->source),
.when = "atomic expression parsing"
},
.location = peek()->location
@ -355,8 +355,8 @@ Result<Ast> Parser::parse_identifier_with_trailing_separators()
// TODO Specific error message
return Error {
.details = errors::internal::Unexpected_Token {
.type = type_name(peek()->type),
.source = peek()->source,
.type = std::string(type_name(peek()->type)),
.source = std::string(peek()->source),
.when = "identifier parsing"
},
.location = peek()->location
@ -373,8 +373,8 @@ Result<Ast> Parser::parse_identifier()
// TODO Specific error message
return Error {
.details = errors::internal::Unexpected_Token {
.type = type_name(peek()->type),
.source = peek()->source,
.type = std::string(type_name(peek()->type)),
.source = std::string(peek()->source),
.when = "identifier parsing"
},
.location = peek()->location

View File

@ -113,7 +113,7 @@ Result<Value> Value::operator()(Interpreter &i, std::vector<Value> args) const
return (*func)(i, std::move(args));
}
return errors::Not_Callable { .type = type_name(*this) };
return errors::Not_Callable { .type = std::string(type_name(*this)) };
}