mirror of
https://codeberg.org/ProgramSnail/lang.git
synced 2025-12-06 06:58:46 +00:00
api improvements, part of expression type checks
This commit is contained in:
parent
a2abb598ac
commit
512d011f72
4 changed files with 96 additions and 9 deletions
|
|
@ -473,6 +473,8 @@ public:
|
|||
|
||||
const Type *get_type() const { return constructor_type_.get(); }
|
||||
|
||||
TypeProxy get_type_proxy() const { return constructor_type_; }
|
||||
|
||||
size_t arguments_size() const { return arguments_.size(); }
|
||||
|
||||
Expression *get_argument_value(size_t id) {
|
||||
|
|
|
|||
|
|
@ -86,6 +86,8 @@ public:
|
|||
|
||||
void set_modifier(Modifier modifier) { modifier_ = modifier; }
|
||||
|
||||
bool is_modifier(Modifier modifier) const { return modifier_ == modifier; }
|
||||
|
||||
//
|
||||
|
||||
std::optional<std::string *> get_annotation() {
|
||||
|
|
@ -102,6 +104,12 @@ public:
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool is_no_annotation() const { return !annotation_.has_value(); }
|
||||
|
||||
bool is_annotation(const std::string &annotation) const {
|
||||
return annotation_.has_value() && annotation_.value() == annotation;
|
||||
}
|
||||
|
||||
void set_annotation(std::string &&annotation) {
|
||||
annotation_ = std::move(annotation);
|
||||
}
|
||||
|
|
@ -176,7 +184,7 @@ public:
|
|||
bool operator>=(const Type &other) const { return !operator<(other); }
|
||||
|
||||
// is parameters count check necessary ??
|
||||
builtin::types::Type to_builtin() {
|
||||
builtin::types::Type to_builtin() const {
|
||||
auto builtin_type = builtin::types::to_type(*name_.get());
|
||||
|
||||
auto builtin_type_parameters_count =
|
||||
|
|
@ -191,7 +199,9 @@ public:
|
|||
return builtin_type;
|
||||
}
|
||||
|
||||
bool is_builtin(builtin::types::Type type) { return to_builtin() == type; }
|
||||
bool is_builtin(builtin::types::Type type) const {
|
||||
return to_builtin() == type;
|
||||
}
|
||||
|
||||
private:
|
||||
Identifier name_;
|
||||
|
|
|
|||
|
|
@ -16,16 +16,18 @@ class State {
|
|||
friend ContextHolder;
|
||||
|
||||
public:
|
||||
bool insert_variable(const std::string &name, nodes::TypeProxy type) {
|
||||
bool insert_variable(const std::string &name, nodes::TypeProxy type,
|
||||
nodes::NameDefinition::Modifier modifier) {
|
||||
if (contexts_.empty()) {
|
||||
error_handling::handle_general_error(
|
||||
"Insert variable into contexts_ with zero elements in State");
|
||||
}
|
||||
|
||||
return contexts_.back().variables.insert({name, type}).second;
|
||||
return contexts_.back().variables.insert({name, {type, modifier}}).second;
|
||||
}
|
||||
|
||||
nodes::MaybeTypeProxy find_variable(const std::string &name) {
|
||||
std::optional<std::pair<nodes::TypeProxy, nodes::NameDefinition::Modifier>>
|
||||
find_variable(const std::string &name) {
|
||||
for (ssize_t i = contexts_.size(); i >= 0; --i) {
|
||||
auto iter = contexts_[i].variables.find(name);
|
||||
if (iter != contexts_[i].variables.end()) {
|
||||
|
|
@ -70,6 +72,7 @@ private:
|
|||
contexts_.emplace_back(node, error_log);
|
||||
}
|
||||
|
||||
// TODO: argument for property is returned type should be merged
|
||||
// returns brought type, return type is merged with next context or with
|
||||
// brought type in last context
|
||||
nodes::MaybeTypeProxy exit_context() {
|
||||
|
|
@ -125,7 +128,9 @@ public:
|
|||
public:
|
||||
nodes::MaybeTypeProxy brought_type;
|
||||
nodes::MaybeTypeProxy returned_type;
|
||||
std::unordered_map<std::string, nodes::TypeProxy> variables;
|
||||
std::unordered_map<std::string, std::pair<nodes::TypeProxy,
|
||||
nodes::NameDefinition::Modifier>>
|
||||
variables;
|
||||
|
||||
private:
|
||||
const nodes::Node &node;
|
||||
|
|
|
|||
|
|
@ -111,6 +111,8 @@ nodes::TypeCheckResult type_check_condition(const nodes::Condition &expression,
|
|||
SourcesManager &sources_manager,
|
||||
State &state,
|
||||
const Arguments &arguments) {
|
||||
// TODO: extract functiona argument names
|
||||
// typecheck in statements ??
|
||||
} // IN PROGRESS
|
||||
|
||||
nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression,
|
||||
|
|
@ -128,7 +130,6 @@ nodes::TypeCheckResult type_check_loop(const nodes::Loop &expression,
|
|||
nodes::TypeCheckResult expression_result = type_check_expression(
|
||||
*expression.get_expression(), sources_manager, state, {});
|
||||
|
||||
// detect maximum amount of errors
|
||||
switch (expression.get_type()) {
|
||||
case nodes::Loop::LOOP: // infinity loop, no params
|
||||
break;
|
||||
|
|
@ -229,6 +230,9 @@ nodes::TypeCheckResult type_check_block(const nodes::Container &expression,
|
|||
SourcesManager &sources_manager,
|
||||
State &state,
|
||||
const Arguments &arguments) {
|
||||
ContextHolder context_holder(state, expression,
|
||||
*sources_manager.get_error_log());
|
||||
|
||||
} // IN PROGRESS
|
||||
|
||||
nodes::TypeCheckResult type_check_container(const nodes::Container &expression,
|
||||
|
|
@ -289,7 +293,36 @@ nodes::TypeCheckResult type_check_return(const nodes::Return &expression,
|
|||
nodes::TypeCheckResult
|
||||
type_check_name_definition(const nodes::NameDefinition &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments) {} // IN PROGRESS
|
||||
const Arguments &arguments) {
|
||||
if (!arguments.expected_type.has_value()) {
|
||||
sources_manager.get_error_log()->add_error(
|
||||
error_handling::ErrorLog::ErrorMessage(
|
||||
expression, "Can't deduce type of new variable from context",
|
||||
error_handling::ErrorType::TYPE_CHECK));
|
||||
}
|
||||
|
||||
// defined name modifier should be -> (or contain -> ??)
|
||||
// TODO: deal with ...|...|... modifiers
|
||||
const auto &expected_type = arguments.expected_type.value();
|
||||
if (!expected_type.get()->is_modifier(
|
||||
nodes::Modifier::OUT)) { // TODO: utils::modifier_contains_OUT
|
||||
sources_manager.get_error_log()->add_error(
|
||||
error_handling::ErrorLog::ErrorMessage(
|
||||
expression, "Type of lambda function should be function",
|
||||
error_handling::ErrorType::TYPE_CHECK));
|
||||
}
|
||||
|
||||
// TODO: remove modifier ??
|
||||
if (!state.insert_variable(*expression.get_name()->get(), expected_type,
|
||||
expression.get_modifier())) {
|
||||
sources_manager.get_error_log()->add_error(
|
||||
error_handling::ErrorLog::ErrorMessage(
|
||||
expression, "Variable is already defined in this context",
|
||||
error_handling::ErrorType::TYPE_CHECK));
|
||||
}
|
||||
|
||||
return nodes::TypeCheckResult{expected_type};
|
||||
} // IN PROGRESS
|
||||
|
||||
nodes::TypeCheckResult type_check_array_access(const nodes::Access &expression,
|
||||
SourcesManager &sources_manager,
|
||||
|
|
@ -421,13 +454,50 @@ type_check_name_expression(const nodes::NameExpression &expression,
|
|||
nodes::TypeCheckResult
|
||||
type_check_constructor(const nodes::Constructor &expression,
|
||||
SourcesManager &sources_manager, State &state,
|
||||
const Arguments &arguments) {} // IN PROGRESS
|
||||
const Arguments &arguments) {
|
||||
// TODO: find definition
|
||||
for (size_t i = 0; i < expression.arguments_size(); ++i) {
|
||||
const auto annotation = expression.get_argument_annotation(i);
|
||||
auto argument_type = type_check_expression(
|
||||
*expression.get_argument_value(i), sources_manager, state,
|
||||
/* TODO: type from definition by annotation */);
|
||||
}
|
||||
// TODO: expect types of arguments by type definition
|
||||
return type_same_to_expected(expression.get_type_proxy(),
|
||||
arguments.expected_type, expression,
|
||||
*sources_manager.get_error_log());
|
||||
// TODO: add <- modifiier to type ??
|
||||
|
||||
} // IN PROGRESS
|
||||
|
||||
// TODO
|
||||
nodes::TypeCheckResult type_check_lambda(const nodes::Lambda &expression,
|
||||
SourcesManager &sources_manager,
|
||||
State &state,
|
||||
const Arguments &arguments) {
|
||||
if (!arguments.expected_type.has_value()) {
|
||||
sources_manager.get_error_log()->add_error(
|
||||
error_handling::ErrorLog::ErrorMessage(
|
||||
expression, "Can't deduce type of lambda function from context",
|
||||
error_handling::ErrorType::TYPE_CHECK));
|
||||
}
|
||||
|
||||
const auto &expected_type = arguments.expected_type.value();
|
||||
if (!expected_type.get()->is_builtin(builtin::types::Type::FUNCTION)) {
|
||||
sources_manager.get_error_log()->add_error(
|
||||
error_handling::ErrorLog::ErrorMessage(
|
||||
expression, "Type of lambda function should be function",
|
||||
error_handling::ErrorType::TYPE_CHECK));
|
||||
}
|
||||
|
||||
// TODO: define vars
|
||||
// TODO: expect returned type as type of internal expression
|
||||
// TODO: merge returned and brought type
|
||||
// TODO: add context
|
||||
// auto returned_type = type_check_expression(
|
||||
// *expression.get_expression(), sources_manager, state, Arguments{});
|
||||
|
||||
return nodes::TypeCheckResult{expected_type};
|
||||
} // IN PROGRESS
|
||||
|
||||
} // namespace type_check
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue