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); 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";

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

@ -97,13 +97,21 @@ Result<Value> Interpreter::eval(Ast &&ast)
.details = errors::Unsupported_Types_For { .details = errors::Unsupported_Types_For {
.type = errors::Unsupported_Types_For::Operator, .type = errors::Unsupported_Types_For::Operator,
.name = "=", .name = "=",
.possibilities = {},
}, },
.location = ast.token.location, .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));
} }
@ -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))); 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
}; };
} }
@ -146,7 +154,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)) };
} }