fixes, part of execute_visitor

This commit is contained in:
ProgramSnail 2023-05-09 23:36:47 +03:00
parent 7d96fe5a86
commit 802b736e15
7 changed files with 345 additions and 92 deletions

View file

@ -18,6 +18,7 @@ include_directories(include
add_executable(lang_interpreter src/main.cpp add_executable(lang_interpreter src/main.cpp
src/types.cpp src/types.cpp
src/values.cpp
src/global_info.cpp src/global_info.cpp
include/definitions.hpp include/definitions.hpp
src/visitor.cpp src/visitor.cpp

View file

@ -141,6 +141,7 @@ private:
bool HandleCondition(Expression& condition, const BaseNode& base_node); bool HandleCondition(Expression& condition, const BaseNode& base_node);
void CollectTypeContext(const ParametrizedType& type); void CollectTypeContext(const ParametrizedType& type);
void CheckPattern(Pattern& node, const BaseNode& base_node);
template<typename T> template<typename T>
T* ExtractValue(utils::IdType value, const BaseNode& base_node) { T* ExtractValue(utils::IdType value, const BaseNode& base_node) {
@ -169,6 +170,7 @@ private:
std::optional<LoopControlExpression> active_loop_control_expression_; std::optional<LoopControlExpression> active_loop_control_expression_;
std::optional<utils::IdType> return_value_; // TODO: work outside block ?? std::optional<utils::IdType> return_value_; // TODO: work outside block ??
std::optional<utils::IsConstModifier> is_const_definition_; std::optional<utils::IsConstModifier> is_const_definition_;
bool case_matched_;
}; };
} // namespace interpreter } // namespace interpreter

View file

@ -11,6 +11,8 @@
namespace info::value { namespace info::value {
struct ValueManager;
struct Unit {}; struct Unit {};
struct InternalValue { struct InternalValue {
@ -27,6 +29,8 @@ public:
} }
return &std::get<T>(value); return &std::get<T>(value);
} }
std::optional<utils::IdType> GetFieldValue(const std::string& name);
public: public:
std::variant<double, std::variant<double,
long long, long long,
@ -38,67 +42,104 @@ public:
struct TupleValue { struct TupleValue {
public: public:
TupleValue() = default; explicit TupleValue(ValueManager* value_manager) : value_manager_(value_manager) {}
explicit TupleValue(std::vector<std::pair<std::optional<std::string>, utils::IdType>>&& fields) : fields(std::move(fields)) {}
explicit TupleValue(std::vector<std::pair<std::optional<std::string>, utils::IdType>>&& fields,
ValueManager* value_manager)
: fields(std::move(fields)), value_manager_(value_manager) {}
std::optional<utils::IdType> GetFieldValue(const std::string& name);
public: public:
std::vector<std::pair<std::optional<std::string>, utils::IdType>> fields; std::vector<std::pair<std::optional<std::string>, utils::IdType>> fields;
private:
ValueManager* value_manager_;
}; };
struct VariantValue { struct VariantValue {
public: public:
VariantValue() = default; explicit VariantValue(ValueManager* value_manager) : value_manager_(value_manager) {}
VariantValue(utils::IdType value) // TupleValue ?? // TODO: add type & constructor??
: value(value) {} // TupleValue ?? // TODO: add type??
VariantValue(utils::IdType value, size_t current_constructor, ValueManager* value_manager)
: value(value), current_constructor(current_constructor), value_manager_(value_manager) {}
public: public:
utils::IdType value; utils::IdType value;
size_t current_constructor;
std::optional<utils::IdType> GetFieldValue(const std::string& name);
private:
ValueManager* value_manager_;
}; };
struct ReferenceToValue { struct ReferenceToValue {
public: public:
ReferenceToValue() = default; explicit ReferenceToValue(ValueManager* value_manager) : value_manager_(value_manager) {}
ReferenceToValue(const std::vector<utils::ReferenceModifier>& references, ReferenceToValue(const std::vector<utils::ReferenceModifier>& references,
utils::IdType value) utils::IdType value,
: references(references), value(value) {} ValueManager* value_manager)
: references(references), value(value), value_manager_(value_manager) {}
public: public:
std::vector<utils::ReferenceModifier> references; std::vector<utils::ReferenceModifier> references;
utils::IdType value; utils::IdType value;
std::optional<utils::IdType> GetFieldValue(const std::string& name);
private:
ValueManager* value_manager_;
}; };
struct FunctionValue { struct FunctionValue {
public: public:
FunctionValue() = default; explicit FunctionValue(ValueManager* value_manager) : value_manager_(value_manager) {}
FunctionValue(std::variant<interpreter::tokens::FunctionDeclaration*,
interpreter::tokens::LambdaFunction*> function) template<typename T>
: function(function) {} FunctionValue(const T& function, ValueManager* value_manager)
: function(function), value_manager_(value_manager) {}
public: public:
std::variant<interpreter::tokens::FunctionDeclaration*, std::variant<interpreter::tokens::FunctionDeclaration*,
interpreter::tokens::LambdaFunction*> function; interpreter::tokens::LambdaFunction*> function;
std::optional<utils::IdType> GetFieldValue(const std::string& name);
private:
ValueManager* value_manager_;
}; };
struct ArrayValue { struct ArrayValue {
public: public:
ArrayValue() = default; explicit ArrayValue(ValueManager* value_manager) : value_manager_(value_manager) {}
explicit ArrayValue(std::vector<utils::IdType>&& elements, explicit ArrayValue(std::vector<utils::IdType>&& elements,
bool is_constant_size) bool is_constant_size,
: elements(std::move(elements)), is_constant_size(is_constant_size) {} ValueManager* value_manager)
: elements(std::move(elements)), is_constant_size(is_constant_size), value_manager_(value_manager) {}
public: public:
std::vector<utils::IdType> elements; std::vector<utils::IdType> elements;
bool is_constant_size = false; bool is_constant_size = false;
std::optional<utils::IdType> GetFieldValue(const std::string& name);
private:
ValueManager* value_manager_;
}; };
struct OptionalValue { struct OptionalValue {
public: public:
OptionalValue() = default; explicit OptionalValue(ValueManager* value_manager) : value_manager_(value_manager) {}
explicit OptionalValue(utils::IdType value) : value(value) {}
explicit OptionalValue(utils::IdType value, ValueManager* value_manager)
: value(value), value_manager_(value_manager) {}
std::optional<utils::IdType> GetFieldValue(const std::string& name);
public: public:
std::optional<utils::IdType> value; std::optional<utils::IdType> value;
private:
ValueManager* value_manager_;
}; };
struct Value { // DefinedValue ?? struct Value { // DefinedValue ??
@ -108,6 +149,7 @@ public:
template<typename T> template<typename T>
explicit Value(const T& value) : value(value) {} // move ?? explicit Value(const T& value) : value(value) {} // move ??
std::optional<utils::IdType> GetFieldValue(const std::string& name);
public: public:
std::variant<InternalValue, std::variant<InternalValue,
TupleValue, TupleValue,

View file

@ -60,50 +60,82 @@ void ExecuteVisitor::Visit(PartitionStatement* node) {
// Flow control ----------------- // Flow control -----------------
// TODO void ExecuteVisitor::Visit(TypeConstructorPatternParameter* node) {} // handled in TypeConstructorPattern
void ExecuteVisitor::Visit(TypeConstructorPatternParameter* node) {
if (node->name.has_value()) {
// Visit(&node->name.value());
}
Visitor::Visit(node->value);
}
// TODO // TODO
void ExecuteVisitor::Visit(TypeConstructorPattern* node) { void ExecuteVisitor::Visit(TypeConstructorPattern* node) {
// TODO: not only tuples // TODO: not only tuples
Visit(node->constructor.get()); Visit(node->constructor.get()); // TODO: ?? check is same constructor_id ??
for (auto& parameter : node->parameters) { for (auto& parameter : node->parameters) { // TODO: pass parameters separately
Visit(&parameter); Visitor::Visit(parameter.value); // handle TypeConstructorPatternParameter
} }
} }
// TODO void ExecuteVisitor::Visit(MatchCase* node) {} // handeled in Match
void ExecuteVisitor::Visit(MatchCase* node) {
Visitor::Visit(node->value);
if (node->condition.has_value()) {
Visitor::Visit(node->condition.value());
}
if (node->statement.has_value()) {
Visitor::Visit(node->statement.value());
}
}
// TODO
void ExecuteVisitor::Visit(Match* node) { void ExecuteVisitor::Visit(Match* node) {
context_manager_.EnterContext();
Visitor::Visit(node->value); Visitor::Visit(node->value);
utils::IdType value = current_value_;
bool case_choosen = false;
bool statement_visited = false;
for (auto& match_case : node->matches) { for (auto& match_case : node->matches) {
Visit(&match_case); if (case_choosen) {
if (match_case.statement.has_value()) {
Visitor::Visit(match_case.statement.value());
statement_visited = true;
break;
}
} else {
current_value_ = value;
case_matched_ = true;
context_manager_.EnterContext();
Visitor::Visit(node->value);
if (case_matched_ && (match_case.condition.has_value() ? HandleCondition(match_case.condition.value(), match_case.base) : true)) {
case_choosen = true;
if (match_case.statement.has_value()) {
Visitor::Visit(match_case.statement.value());
statement_visited = true;
break;
}
} else {
context_manager_.ExitContext();
}
}
} }
if (case_choosen) {
context_manager_.ExitContext();
}
if (statement_visited) {
current_value_ = context_manager_.AddValue<info::value::OptionalValue>(
info::value::OptionalValue(current_value_, context_manager_.GetValueManager()),
utils::ValueType::Tmp);
} else {
current_value_ = context_manager_.AddValue<info::value::OptionalValue>(
info::value::OptionalValue(context_manager_.GetValueManager()),
utils::ValueType::Tmp);
}
context_manager_.ExitContext();
} }
void ExecuteVisitor::Visit(Condition* node) { void ExecuteVisitor::Visit(Condition* node) {
context_manager_.EnterContext();
for (size_t i = 0; i < node->conditions.size(); ++i) { for (size_t i = 0; i < node->conditions.size(); ++i) {
if (HandleCondition(node->conditions[i], node->base)) { if (HandleCondition(node->conditions[i], node->base)) {
Visitor::Visit(node->statements[i]); Visitor::Visit(node->statements[i]);
if (node->statements.size() == node->conditions.size()) { if (node->statements.size() == node->conditions.size()) {
current_value_ = context_manager_.AddValue<info::value::OptionalValue>( current_value_ = context_manager_.AddValue<info::value::OptionalValue>(
info::value::OptionalValue(current_value_), info::value::OptionalValue(current_value_, context_manager_.GetValueManager()),
utils::ValueType::Tmp); // take value type from current_value_ ?? utils::ValueType::Tmp); // take value type from current_value_ ??
} }
return; // current_value_ passed from statement return; // current_value_ passed from statement
@ -113,12 +145,16 @@ void ExecuteVisitor::Visit(Condition* node) {
Visitor::Visit(node->statements[node->conditions.size()]); Visitor::Visit(node->statements[node->conditions.size()]);
} else { } else {
current_value_ = context_manager_.AddValue<info::value::OptionalValue>( current_value_ = context_manager_.AddValue<info::value::OptionalValue>(
info::value::OptionalValue(), info::value::OptionalValue(context_manager_.GetValueManager()),
utils::ValueType::Tmp); utils::ValueType::Tmp);
} }
context_manager_.ExitContext();
} }
void ExecuteVisitor::Visit(DoWhileLoop* node) { void ExecuteVisitor::Visit(DoWhileLoop* node) {
context_manager_.EnterContext();
std::vector<utils::IdType> result; std::vector<utils::IdType> result;
do { do {
Visitor::Visit(node->statement); Visitor::Visit(node->statement);
@ -135,11 +171,15 @@ void ExecuteVisitor::Visit(DoWhileLoop* node) {
} while(HandleCondition(node->condition, node->base)); } while(HandleCondition(node->condition, node->base));
current_value_ = context_manager_.AddValue<info::value::ArrayValue>( current_value_ = context_manager_.AddValue<info::value::ArrayValue>(
info::value::ArrayValue(std::move(result), false), info::value::ArrayValue(std::move(result), false, context_manager_.GetValueManager()),
utils::ValueType::Tmp); utils::ValueType::Tmp);
context_manager_.ExitContext();
} }
void ExecuteVisitor::Visit(WhileLoop* node) { void ExecuteVisitor::Visit(WhileLoop* node) {
context_manager_.EnterContext();
std::vector<utils::IdType> result; std::vector<utils::IdType> result;
while(HandleCondition(node->condition, node->base)) { while(HandleCondition(node->condition, node->base)) {
Visitor::Visit(node->statement); Visitor::Visit(node->statement);
@ -156,10 +196,14 @@ void ExecuteVisitor::Visit(WhileLoop* node) {
} }
current_value_ = context_manager_.AddValue<info::value::ArrayValue>( current_value_ = context_manager_.AddValue<info::value::ArrayValue>(
info::value::ArrayValue(std::move(result), false), info::value::ArrayValue(std::move(result), false, context_manager_.GetValueManager()),
utils::ValueType::Tmp); utils::ValueType::Tmp);
context_manager_.ExitContext();
} }
void ExecuteVisitor::Visit(ForLoop* node) { void ExecuteVisitor::Visit(ForLoop* node) {
context_manager_.EnterContext();
std::vector<utils::IdType> result; std::vector<utils::IdType> result;
// TODO: extend to different interval types (not only array) // TODO: extend to different interval types (not only array)
@ -184,11 +228,15 @@ void ExecuteVisitor::Visit(ForLoop* node) {
} }
current_value_ = context_manager_.AddValue<info::value::ArrayValue>( current_value_ = context_manager_.AddValue<info::value::ArrayValue>(
info::value::ArrayValue(std::move(result), false), info::value::ArrayValue(std::move(result), false, context_manager_.GetValueManager()),
utils::ValueType::Tmp); utils::ValueType::Tmp);
context_manager_.ExitContext();
} }
void ExecuteVisitor::Visit(LoopLoop* node) { void ExecuteVisitor::Visit(LoopLoop* node) {
context_manager_.EnterContext();
std::vector<utils::IdType> result; std::vector<utils::IdType> result;
while(true) { while(true) {
Visitor::Visit(node->statement); Visitor::Visit(node->statement);
@ -205,8 +253,10 @@ void ExecuteVisitor::Visit(LoopLoop* node) {
} }
current_value_ = context_manager_.AddValue<info::value::ArrayValue>( current_value_ = context_manager_.AddValue<info::value::ArrayValue>(
info::value::ArrayValue(std::move(result), false), info::value::ArrayValue(std::move(result), false, context_manager_.GetValueManager()),
utils::ValueType::Tmp); utils::ValueType::Tmp);
context_manager_.ExitContext();
} }
// Statements, expressions, blocks, etc. ----------------- // Statements, expressions, blocks, etc. -----------------
@ -297,7 +347,7 @@ void ExecuteVisitor::Visit(ReferenceExpression* node) {
utils::ValueType value_type = context_manager_.GetValueType(current_value_); utils::ValueType value_type = context_manager_.GetValueType(current_value_);
current_value_ = context_manager_.AddValue( current_value_ = context_manager_.AddValue(
info::value::ReferenceToValue(node->references, current_value_), info::value::ReferenceToValue(node->references, current_value_, context_manager_.GetValueManager()),
value_type); value_type);
} }
@ -376,29 +426,29 @@ void ExecuteVisitor::Visit(TupleExpression* node) {
} }
current_value_ = context_manager_.AddValue<info::value::TupleValue>( current_value_ = context_manager_.AddValue<info::value::TupleValue>(
info::value::TupleValue(std::move(fields)), info::value::TupleValue(std::move(fields), context_manager_.GetValueManager()),
utils::ValueType::Tmp); utils::ValueType::Tmp);
} }
void ExecuteVisitor::Visit(VariantExpression* node) { void ExecuteVisitor::Visit(VariantExpression* node) {
// TODO: decide about return type (variant) // TODO: decide about return type (variant)
for (auto& expression : node->expressions) { for (size_t i = 0; i < node->expressions.size(); ++i) {
Visitor::Visit(expression); Visitor::Visit(node->expressions[i]);
info::value::OptionalValue* expression_value = ExtractValue<info::value::OptionalValue>(current_value_, node->base); info::value::OptionalValue* expression_value = ExtractValue<info::value::OptionalValue>(current_value_, node->base);
if (expression_value->value.has_value()) { if (expression_value->value.has_value()) {
current_value_ = context_manager_.AddValue<info::value::VariantValue>( current_value_ = context_manager_.AddValue<info::value::VariantValue>(
info::value::VariantValue(expression_value->value.value()), info::value::VariantValue(expression_value->value.value(), i, context_manager_.GetValueManager()),
utils::ValueType::Tmp); utils::ValueType::Tmp);
current_value_ = context_manager_.AddValue<info::value::OptionalValue>( current_value_ = context_manager_.AddValue<info::value::OptionalValue>(
info::value::OptionalValue(current_value_), info::value::OptionalValue(current_value_, context_manager_.GetValueManager()),
utils::ValueType::Tmp); utils::ValueType::Tmp);
return; return;
} }
} }
current_value_ = context_manager_.AddValue<info::value::OptionalValue>( current_value_ = context_manager_.AddValue<info::value::OptionalValue>(
info::value::OptionalValue(), info::value::OptionalValue(context_manager_.GetValueManager()),
utils::ValueType::Tmp); utils::ValueType::Tmp);
} }
@ -407,21 +457,27 @@ void ExecuteVisitor::Visit(ReturnExpression* node) {
return_value_ = current_value_; return_value_ = current_value_;
} }
// TODO
void ExecuteVisitor::Visit(TypeConstructorParameter* node) {
if (node->name.has_value()) {
// Visit(&node->name.value());
}
Visitor::Visit(node->value);
}
// TODO void ExecuteVisitor::Visit(TypeConstructorParameter* node) {} // handled in TypeConstructor
void ExecuteVisitor::Visit(TypeConstructor* node) { void ExecuteVisitor::Visit(TypeConstructor* node) {
// TODO: not only tuples // TODO: support for non-tuples
Visit(node->constructor.get()); std::vector<std::pair<std::optional<std::string>, utils::IdType>> fields;
// Visit(node->constructor.get()); // use parameters from type expression ??
fields.reserve(node->parameters.size());
for (auto& parameter : node->parameters) { for (auto& parameter : node->parameters) {
Visit(&parameter); Visitor::Visit(parameter.value);
// TODO: copy/move parameters
fields.push_back(
{ parameter.name.has_value() ? std::optional<std::string>(parameter.name.value().name) : std::nullopt,
current_value_ });
} }
current_value_ = context_manager_.AddValue<info::value::TupleValue>(
info::value::TupleValue(std::move(fields), context_manager_.GetValueManager()),
utils::ValueType::Tmp);
} }
// TODO // TODO
@ -440,7 +496,7 @@ void ExecuteVisitor::Visit(ArrayExpression* node) {
} }
current_value_ = context_manager_.AddValue<info::value::ArrayValue>( current_value_ = context_manager_.AddValue<info::value::ArrayValue>(
info::value::ArrayValue(std::move(elements), true), // maybe size not fixed?? info::value::ArrayValue(std::move(elements), true, context_manager_.GetValueManager()), // maybe size not fixed??
utils::ValueType::Tmp); utils::ValueType::Tmp);
} }
@ -513,6 +569,7 @@ void ExecuteVisitor::Visit(TupleName* node) { // TODO: check
} }
// TODO // TODO
// TODO: make variant of TupleValue
void ExecuteVisitor::Visit(VariantName* node) { void ExecuteVisitor::Visit(VariantName* node) {
utils::IdType value = current_value_; utils::IdType value = current_value_;
@ -522,6 +579,20 @@ void ExecuteVisitor::Visit(VariantName* node) {
error_handling::HandleRuntimeError("Mismatched value types in variant variable definition", node->base); error_handling::HandleRuntimeError("Mismatched value types in variant variable definition", node->base);
} }
for (size_t i = 0; i < node->names.size(); ++i) {
if (i == maybe_variant_value.value()->current_constructor) {
// TODO if (fields_count.empty()) ... else ...
current_value_ = context_manager_.AddValue(
info::value::OptionalValue(maybe_variant_value.value()->value, context_manager_.GetValueManager()),
utils::IsConstModifierToValueType(is_const_definition_.value())); // TODO ??
} else {
current_value_ = context_manager_.AddValue(
info::value::OptionalValue(context_manager_.GetValueManager()),
utils::IsConstModifierToValueType(is_const_definition_.value()));
}
Visitor::Visit(node->names[i]);
}
// TODO: find out, which constructor used // TODO: find out, which constructor used
// set value to that constructor and None (empty OptionalValue) to others // set value to that constructor and None (empty OptionalValue) to others
@ -633,6 +704,34 @@ void ExecuteVisitor::CollectTypeContext(const ParametrizedType& type) {
if (type.parameters[i]->type_id_.has_value()) { if (type.parameters[i]->type_id_.has_value()) {
context_manager_.DefineLocalType(type_info.parameters[i].type, context_manager_.DefineLocalType(type_info.parameters[i].type,
type.parameters[i]->type_id_.value()); type.parameters[i]->type_id_.value());
}
}
}
// TODO
void ExecuteVisitor::CheckPattern(Pattern& node, const BaseNode& base_node) {
utils::IdType value = current_value_;
switch (node.index()) {
case 0:
value = context_manager_.ToModifiedValue(value, utils::ValueType::Const); // ??
if (!context_manager_.DefineVariable(std::get<std::unique_ptr<ExtendedName>>(node)->name,
value)) {
error_handling::HandleRuntimeError("Can't redifine variable", base_node);
}
break;
case 1:
Visitor::Visit(*std::get<std::unique_ptr<Literal>>(node));
if (!context_manager_.EqualValues(current_value_, value)) { // TODO
case_matched_ = false;
}
break;
case 2:
Visit(std::get<std::unique_ptr<TypeConstructorPattern>>(node).get());
break;
default:
// error
break;
} }
} }

View file

@ -364,16 +364,15 @@ void TypeCheckVisitor::Visit(MatchCase* node) {
error_handling::HandleTypecheckError("Match case condition is not bool expression", node->base); error_handling::HandleTypecheckError("Match case condition is not bool expression", node->base);
} }
if (node->statement.has_value()) { // IMPORTANT: statement visited in Match
Visitor::Visit(node->statement.value());
}
// current_type_ from statement is current_type_ for MatchCase
node->base.type_ = current_type_; node->base.type_ = current_type_;
} }
void TypeCheckVisitor::Visit(Match* node) { // TODO: move value to match void TypeCheckVisitor::Visit(Match* node) { // TODO: move value to match
// TODO: types can be different in block statement // TODO: types can be different in block statement
context_manager_.EnterContext();
utils::IdType type; utils::IdType type;
bool is_type_found = false; bool is_type_found = false;
@ -381,17 +380,26 @@ void TypeCheckVisitor::Visit(Match* node) { // TODO: move value to match
Visitor::Visit(node->value); Visitor::Visit(node->value);
utils::IdType value_type = current_type_; utils::IdType value_type = current_type_;
for (size_t i = 0; i < node->matches.size(); ++i) { // TODO: several matches with one statement typecheck <- check proposed solution
std::optional<Expression*> nearest_statement;
for (ssize_t i = (ssize_t)node->matches.size() - 1; i >= 0; --i) { // TODO: internal contexts ??
current_type_ = value_type; current_type_ = value_type;
context_manager_.EnterContext(); context_manager_.EnterContext();
Visit(&node->matches[i]); Visit(&node->matches[i]);
context_manager_.ExitContext();
if (!node->matches[i].statement.has_value()) { if (node->matches[i].statement.has_value()) {
nearest_statement = &node->matches[i].statement.value();
}
if (!nearest_statement.has_value()) {
continue; continue;
} }
Visitor::Visit(*nearest_statement.value());
context_manager_.ExitContext();
if (!is_type_found) { if (!is_type_found) {
type = current_type_; type = current_type_;
is_type_found = true; is_type_found = true;
@ -408,10 +416,18 @@ void TypeCheckVisitor::Visit(Match* node) { // TODO: move value to match
current_type_ = type; current_type_ = type;
current_type_ = context_manager_.AddValue(
info::type::OptionalType(current_type_, context_manager_.GetValueManager()),
utils::ValueType::Tmp);
context_manager_.ExitContext();
node->base.type_ = current_type_; node->base.type_ = current_type_;
} }
void TypeCheckVisitor::Visit(Condition* node) { void TypeCheckVisitor::Visit(Condition* node) {
context_manager_.EnterContext();
// TODO: types can be different in statement // TODO: types can be different in statement
utils::IdType type; utils::IdType type;
@ -421,9 +437,8 @@ void TypeCheckVisitor::Visit(Condition* node) {
error_handling::HandleTypecheckError("Condition statement condition is not bool expression", node->base); error_handling::HandleTypecheckError("Condition statement condition is not bool expression", node->base);
} }
context_manager_.EnterContext();
Visitor::Visit(node->statements[i]); Visitor::Visit(node->statements[i]);
context_manager_.ExitContext();
if (i == 0) { if (i == 0) {
type = current_type_; type = current_type_;
} else { } else {
@ -434,9 +449,8 @@ void TypeCheckVisitor::Visit(Condition* node) {
} }
if (node->statements.size() > node->conditions.size()) { if (node->statements.size() > node->conditions.size()) {
context_manager_.EnterContext();
Visitor::Visit(node->statements[node->conditions.size()]); Visitor::Visit(node->statements[node->conditions.size()]);
context_manager_.ExitContext();
if (!context_manager_.EqualValues(type, current_type_)) { if (!context_manager_.EqualValues(type, current_type_)) {
error_handling::HandleTypecheckError("Condition statement else have different type from other cases", node->base); error_handling::HandleTypecheckError("Condition statement else have different type from other cases", node->base);
} }
@ -447,42 +461,52 @@ void TypeCheckVisitor::Visit(Condition* node) {
utils::ValueType::Tmp); // ?? utils::ValueType::Tmp); // ??
} }
context_manager_.ExitContext();
node->base.type_ = current_type_; node->base.type_ = current_type_;
} }
void TypeCheckVisitor::Visit(DoWhileLoop* node) { void TypeCheckVisitor::Visit(DoWhileLoop* node) {
context_manager_.EnterContext();
Visitor::Visit(node->condition); Visitor::Visit(node->condition);
if (!context_manager_.EqualValues(context_manager_.AddValue(info::type::InternalType::Bool, utils::ValueType::Tmp), current_type_)) { if (!context_manager_.EqualValues(context_manager_.AddValue(info::type::InternalType::Bool, utils::ValueType::Tmp), current_type_)) {
error_handling::HandleTypecheckError("Do while loop statement condition is not bool expression", node->base); error_handling::HandleTypecheckError("Do while loop statement condition is not bool expression", node->base);
} }
context_manager_.EnterContext();
Visitor::Visit(node->statement); Visitor::Visit(node->statement);
context_manager_.ExitContext();
current_type_ = context_manager_.AddValue( current_type_ = context_manager_.AddValue(
info::type::ArrayType(0, current_type_, context_manager_.GetValueManager()), info::type::ArrayType(0, current_type_, context_manager_.GetValueManager()),
utils::ValueType::Tmp); utils::ValueType::Tmp);
context_manager_.ExitContext();
node->base.type_ = current_type_;
} }
void TypeCheckVisitor::Visit(WhileLoop* node) { void TypeCheckVisitor::Visit(WhileLoop* node) {
context_manager_.EnterContext();
Visitor::Visit(node->condition); Visitor::Visit(node->condition);
if (!context_manager_.EqualValues(context_manager_.AddValue(info::type::InternalType::Bool, utils::ValueType::Tmp), current_type_)) { if (!context_manager_.EqualValues(context_manager_.AddValue(info::type::InternalType::Bool, utils::ValueType::Tmp), current_type_)) {
error_handling::HandleTypecheckError("While loop statement condition is not bool expression", node->base); error_handling::HandleTypecheckError("While loop statement condition is not bool expression", node->base);
} }
context_manager_.EnterContext();
Visitor::Visit(node->statement); Visitor::Visit(node->statement);
context_manager_.ExitContext();
current_type_ = context_manager_.AddValue( current_type_ = context_manager_.AddValue(
info::type::ArrayType(0, current_type_, context_manager_.GetValueManager()), info::type::ArrayType(0, current_type_, context_manager_.GetValueManager()),
utils::ValueType::Tmp); utils::ValueType::Tmp);
context_manager_.ExitContext();
node->base.type_ = current_type_; node->base.type_ = current_type_;
} }
void TypeCheckVisitor::Visit(ForLoop* node) { void TypeCheckVisitor::Visit(ForLoop* node) {
context_manager_.EnterContext();
Visitor::Visit(node->interval); Visitor::Visit(node->interval);
std::optional<info::type::ArrayType*> maybe_interval_type = context_manager_.GetValue<info::type::ArrayType>(current_type_); std::optional<info::type::ArrayType*> maybe_interval_type = context_manager_.GetValue<info::type::ArrayType>(current_type_);
@ -490,8 +514,6 @@ void TypeCheckVisitor::Visit(ForLoop* node) {
error_handling::HandleTypecheckError("For loop interval type mismatch", node->base); error_handling::HandleTypecheckError("For loop interval type mismatch", node->base);
} }
context_manager_.EnterContext();
current_type_ = context_manager_.ToModifiedValue(maybe_interval_type.value()->GetElementsType(), current_type_ = context_manager_.ToModifiedValue(maybe_interval_type.value()->GetElementsType(),
utils::IsConstModifierToValueType(node->variable_modifier)); utils::IsConstModifierToValueType(node->variable_modifier));
@ -501,22 +523,26 @@ void TypeCheckVisitor::Visit(ForLoop* node) {
Visitor::Visit(node->statement); Visitor::Visit(node->statement);
context_manager_.ExitContext();
current_type_ = context_manager_.AddValue( current_type_ = context_manager_.AddValue(
info::type::ArrayType(0, current_type_, context_manager_.GetValueManager()), info::type::ArrayType(0, current_type_, context_manager_.GetValueManager()),
utils::ValueType::Tmp); utils::ValueType::Tmp);
context_manager_.ExitContext();
node->base.type_ = current_type_;
} }
void TypeCheckVisitor::Visit(LoopLoop* node) { void TypeCheckVisitor::Visit(LoopLoop* node) {
context_manager_.EnterContext(); context_manager_.EnterContext();
Visitor::Visit(node->statement); Visitor::Visit(node->statement);
context_manager_.ExitContext();
current_type_ = context_manager_.AddValue( current_type_ = context_manager_.AddValue(
info::type::ArrayType(0, current_type_, context_manager_.GetValueManager()), info::type::ArrayType(0, current_type_, context_manager_.GetValueManager()),
utils::ValueType::Tmp); utils::ValueType::Tmp);
context_manager_.ExitContext();
node->base.type_ = current_type_; node->base.type_ = current_type_;
} }
@ -897,9 +923,9 @@ void TypeCheckVisitor::Visit(VariantExpression* node) {
std::nullopt), std::nullopt),
utils::ValueType::Tmp); utils::ValueType::Tmp);
current_type_ = context_manager_.AddValue(info::type::OptionalType(current_type_, current_type_ = context_manager_.AddValue(
context_manager_.GetValueManager()), info::type::OptionalType(current_type_, context_manager_.GetValueManager()),
utils::ValueType::Tmp); utils::ValueType::Tmp);
node->base.type_ = current_type_; node->base.type_ = current_type_;
} }
@ -1134,7 +1160,9 @@ void TypeCheckVisitor::Visit(VariantName* node) {
for (size_t i = 0; i < node->names.size(); ++i) { for (size_t i = 0; i < node->names.size(); ++i) {
if (maybe_type_value.value()->GetConstructors()[i].GetFields().empty()) { if (maybe_type_value.value()->GetConstructors()[i].GetFields().empty()) {
current_type_ = context_manager_.AddValue( current_type_ = context_manager_.AddValue(
info::type::OptionalType(context_manager_.AddValue(info::type::InternalType::Unit, utils::ValueType::Tmp), context_manager_.GetValueManager()), info::type::OptionalType(
context_manager_.AddValue(info::type::InternalType::Unit, utils::ValueType::Tmp),
context_manager_.GetValueManager()),
utils::IsConstModifierToValueType(is_const_definition_.value())); // TODO ?? utils::IsConstModifierToValueType(is_const_definition_.value())); // TODO ??
} else { } else {
info::type::TupleType constructor_type_value = maybe_type_value.value()->GetConstructors()[i]; info::type::TupleType constructor_type_value = maybe_type_value.value()->GetConstructors()[i];
@ -1408,12 +1436,15 @@ void TypeCheckVisitor::CheckPattern(Pattern& node, const BaseNode& base_node) {
switch (node.index()) { switch (node.index()) {
case 0: case 0:
context_manager_.DefineVariable(std::get<std::unique_ptr<ExtendedName>>(node)->name, value_type = context_manager_.ToModifiedValue(value_type, utils::ValueType::Const); // ??
value_type); if (!context_manager_.DefineVariable(std::get<std::unique_ptr<ExtendedName>>(node)->name,
value_type)) {
error_handling::HandleTypecheckError("Can't redifine variable", base_node);
}
break; break;
case 1: case 1:
Visitor::Visit(*std::get<std::unique_ptr<Literal>>(node)); Visitor::Visit(*std::get<std::unique_ptr<Literal>>(node));
if (context_manager_.EqualValues(current_type_, value_type)) { // TODO: better solution ?? if (!context_manager_.EqualValues(current_type_, value_type)) { // TODO: better solution ??
error_handling::HandleTypecheckError("Literal and value have different types", base_node); error_handling::HandleTypecheckError("Literal and value have different types", base_node);
} }
break; break;

View file

@ -1,6 +1,5 @@
// for clangd // for clangd
#include "../include/types.hpp" #include "../include/types.hpp"
#include <cstddef>
namespace info::type { namespace info::type {

79
src/values.cpp Normal file
View file

@ -0,0 +1,79 @@
// for clangd
#include "../include/values.hpp"
namespace info::value {
std::optional<utils::IdType> InternalValue::GetFieldValue(const std::string& name) {
return std::nullopt;
}
//
std::optional<utils::IdType> TupleValue::GetFieldValue(const std::string& name) {
for (size_t i = 0; i < fields.size(); ++i) { // TODO: optimize??
if (fields[i].first.has_value() && fields[i].first.value() == name) {
return fields[i].second;
}
}
return std::nullopt;
}
//
std::optional<utils::IdType> VariantValue::GetFieldValue(const std::string& name) {
return value_manager_->GetAnyValue(value)->GetFieldValue(name); // TODO: TupleType ??
}
//
std::optional<utils::IdType> ReferenceToValue::GetFieldValue(const std::string& name) {
return value_manager_->GetAnyValue(value)->GetFieldValue(name);
}
//
std::optional<utils::IdType> FunctionValue::GetFieldValue(const std::string& name) {
return std::nullopt;
}
//
std::optional<utils::IdType> ArrayValue::GetFieldValue(const std::string& name) {
return std::nullopt;
}
//
std::optional<utils::IdType> OptionalValue::GetFieldValue(const std::string& name) {
return std::nullopt;
}
//
std::optional<utils::IdType> Value::GetFieldValue(const std::string& name) {
size_t index = value.index();
switch (index) {
case 0:
return std::get<InternalValue>(value).GetFieldValue(name);
case 1:
return std::get<TupleValue>(value).GetFieldValue(name);
case 2:
return std::get<VariantValue>(value).GetFieldValue(name);
case 3:
return std::get<ReferenceToValue>(value).GetFieldValue(name);
case 4:
return std::get<FunctionValue>(value).GetFieldValue(name);
case 5:
return std::get<ArrayValue>(value).GetFieldValue(name);
case 6:
return std::get<OptionalValue>(value).GetFieldValue(name);
default:
// error
break;
}
return std::nullopt;
}
}; // namespace info::value