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); 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;
} }
}, },

View File

@ -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;
}; };
} }

View File

@ -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
}; };
} }

View File

@ -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

View File

@ -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)) };
} }