overalocate strings to ensure correctness; diagnostic for assigment to undefined variable

This commit is contained in:
Robert Bendun 2023-01-12 20:51:15 +01:00
parent 8c4aecf6e0
commit e008a45cf7
5 changed files with 43 additions and 26 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";

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

@ -97,13 +97,21 @@ Result<Value> Interpreter::eval(Ast &&ast)
.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));
}
@ -127,7 +135,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
};
}
@ -146,7 +154,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)) };
}