constructors on heap, consuming match, move modifier in reference expression, .bring. keyword to return from block, some fixes

This commit is contained in:
ProgramSnail 2023-05-20 20:18:49 +03:00
parent 2556efcaba
commit 8a84cfff70
12 changed files with 128 additions and 34 deletions

View file

@ -174,7 +174,8 @@ private:
utils::IdType current_value_; utils::IdType current_value_;
std::optional<LoopControlExpression> active_loop_control_expression_; std::optional<LoopControlExpression> active_loop_control_expression_;
std::optional<utils::IdType> returned_value_; // TODO: work outside block ?? std::optional<utils::IdType> returned_value_;
std::optional<utils::IdType> brought_value_;
std::optional<utils::IsConstModifier> is_const_definition_; std::optional<utils::IsConstModifier> is_const_definition_;
bool case_matched_; bool case_matched_;
}; };

View file

@ -420,6 +420,8 @@ struct Match {
Expression value; Expression value;
std::vector<MatchCase> matches; std::vector<MatchCase> matches;
bool is_consuming_value = false;
}; };
struct Condition { struct Condition {
@ -545,6 +547,8 @@ struct ReturnExpression {
BaseNode base; BaseNode base;
Expression expression; Expression expression;
bool is_from_definition = false; // from definition or from current block
}; };
struct TypeConstructorParameter { struct TypeConstructorParameter {
@ -560,6 +564,8 @@ struct TypeConstructor {
std::unique_ptr<TypeExpression> constructor; std::unique_ptr<TypeExpression> constructor;
std::vector<TypeConstructorParameter> parameters; std::vector<TypeConstructorParameter> parameters;
bool is_allocated_on_heap = false;
}; };
struct LambdaFunction { struct LambdaFunction {

View file

@ -178,6 +178,7 @@ private:
std::unordered_set<utils::IdType> type_namespaces_; std::unordered_set<utils::IdType> type_namespaces_;
utils::IdType current_type_; utils::IdType current_type_;
std::optional<utils::IdType> returned_type_; std::optional<utils::IdType> returned_type_;
std::optional<utils::IdType> brought_type_;
std::optional<utils::IsConstModifier> is_const_definition_; std::optional<utils::IsConstModifier> is_const_definition_;
bool is_in_statement_ = false; bool is_in_statement_ = false;

@ -1 +1 @@
Subproject commit 630eced5368dca21af5eb2b6bea7f90651ce5e30 Subproject commit ed339526706e0e9289a112fa2cec6ecfdcb362ab

View file

@ -551,6 +551,8 @@ void BuildVisitor::Visit(Match* node) {
auto parse_node = current_node_; auto parse_node = current_node_;
node->is_consuming_value = (parse_node.NthChild(1).GetValue() == "<-");
current_node_ = parse_node.ChildByFieldName("value"); current_node_ = parse_node.ChildByFieldName("value");
Visit(node->value); Visit(node->value);
@ -924,6 +926,8 @@ void BuildVisitor::Visit(ReferenceExpression* node) {
node->references[i] = utils::ReferenceModifier::Reference; node->references[i] = utils::ReferenceModifier::Reference;
} else if (reference == "~") { } else if (reference == "~") {
node->references[i] = utils::ReferenceModifier::Dereference; node->references[i] = utils::ReferenceModifier::Dereference;
} else if (reference == "@") {
node->references[i] = utils::ReferenceModifier::UniqueReference; // TODO: rename to move ??
} }
} }
} }
@ -1042,6 +1046,8 @@ void BuildVisitor::Visit(ReturnExpression* node) {
auto parse_node = current_node_; auto parse_node = current_node_;
node->is_from_definition = (parse_node.NthChild(0).GetValue() == "return"); // "return" to return from definition and "bring" to return from block
current_node_ = parse_node.ChildByFieldName("expression"); current_node_ = parse_node.ChildByFieldName("expression");
Visit(node->expression); Visit(node->expression);
@ -1077,6 +1083,8 @@ void BuildVisitor::Visit(TypeConstructor* node) {
auto parse_node = current_node_; auto parse_node = current_node_;
node->is_allocated_on_heap = (parse_node.NthChild(1).GetValue() == "@");
current_node_ = parse_node.ChildByFieldName("constructor"); current_node_ = parse_node.ChildByFieldName("constructor");
node->constructor = std::make_unique<TypeExpression>(); node->constructor = std::make_unique<TypeExpression>();
Visit(node->constructor.get()); Visit(node->constructor.get());

View file

@ -49,7 +49,16 @@ void ExecuteVisitor::Visit(FunctionDeclaration*) {} // no value
void ExecuteVisitor::Visit(FunctionDefinitionStatement* node) { // visited on function call void ExecuteVisitor::Visit(FunctionDefinitionStatement* node) { // visited on function call
// Visit(node->definition.get()); // Visit(node->definition.get());
context_manager_.EnterContext(); context_manager_.EnterContext();
returned_value_ = std::nullopt;
Visitor::Visit(node->value); Visitor::Visit(node->value);
if (returned_value_.has_value()) {
current_value_ = returned_value_.value();
} // else returned type = current_type_
returned_value_ = std::nullopt;
context_manager_.ExitContext(); context_manager_.ExitContext();
} }
@ -308,20 +317,27 @@ void ExecuteVisitor::Visit(Block* node) {
context_manager_.EnterContext(); context_manager_.EnterContext();
for (auto& statement : node->statements) { for (auto& statement : node->statements) {
returned_value_ = std::nullopt; brought_value_ = std::nullopt;
Visitor::Visit(statement); Visitor::Visit(statement);
if (returned_value_.has_value()) { if (returned_value_.has_value()) {
current_value_ = returned_value_.value(); brought_value_ = std::nullopt;
returned_value_ = std::nullopt; // TODO: ?? ("return" exits only from one block) break;
return; }
if (brought_value_.has_value()) {
break;
} }
} }
context_manager_.ExitContext(); context_manager_.ExitContext();
current_value_ = context_manager_.AddValue( if (brought_value_.has_value()) {
info::value::InternalValue(info::value::Unit()), current_value_ = brought_value_.value();
utils::ValueType::Tmp); brought_value_ = std::nullopt;
} else {
current_value_ = context_manager_.AddValue(
info::value::InternalValue(info::value::Unit()),
utils::ValueType::Tmp);
}
} }
void ExecuteVisitor::Visit(ScopedStatement* node) { void ExecuteVisitor::Visit(ScopedStatement* node) {
@ -332,7 +348,7 @@ void ExecuteVisitor::Visit(LoopControlExpression& node) {
active_loop_control_expression_ = node; active_loop_control_expression_ = node;
current_value_ = context_manager_.AddValue(info::value::InternalValue(info::value::Unit()), current_value_ = context_manager_.AddValue(info::value::InternalValue(info::value::Unit()),
utils::ValueType::Tmp); // ?? utils::ValueType::Tmp);
} }
// Operators // Operators
@ -563,7 +579,15 @@ void ExecuteVisitor::Visit(VariantExpression* node) {
void ExecuteVisitor::Visit(ReturnExpression* node) { void ExecuteVisitor::Visit(ReturnExpression* node) {
Visitor::Visit(node->expression); Visitor::Visit(node->expression);
returned_value_ = current_value_; if (node->is_from_definition) {
returned_value_ = current_value_;
} else {
brought_value_ = current_value_;
}
current_value_ = context_manager_.AddValue(
info::value::InternalValue(info::value::Unit()),
utils::ValueType::Tmp);
} }

View file

@ -282,7 +282,11 @@ void PrintVisitor::Visit(MatchCase* node) {
} }
void PrintVisitor::Visit(Match* node) { void PrintVisitor::Visit(Match* node) {
out_ << "[Match] ("; out_ << "[Match";
if (node->is_consuming_value) {
out_ << " <- ";
}
out_ << "] (";
Visitor::Visit(node->value); Visitor::Visit(node->value);
out_ << ") [with] (\n"; out_ << ") [with] (\n";
for (auto& match_case : node->matches) { for (auto& match_case : node->matches) {
@ -476,7 +480,12 @@ void PrintVisitor::Visit(VariantExpression* node) {
} }
void PrintVisitor::Visit(ReturnExpression* node) { void PrintVisitor::Visit(ReturnExpression* node) {
out_ << "[Return] ("; if (node->is_from_definition) {
out_ << "[Return] (";
} else {
out_ << "[Bring] (";
}
Visitor::Visit(node->expression); Visitor::Visit(node->expression);
out_ << ")\n"; out_ << ")\n";
} }

View file

@ -1,6 +1,7 @@
#include <asm-generic/errno.h> #include <asm-generic/errno.h>
#include <cstdarg> #include <cstdarg>
#include <memory> #include <memory>
#include <optional>
#include <unordered_map> #include <unordered_map>
#include <variant> #include <variant>
@ -254,12 +255,18 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) {
} }
Visitor::Visit(declaration->type->types.back()); Visitor::Visit(declaration->type->types.back());
utils::IdType return_type = current_type_; utils::IdType returned_type = current_type_;
returned_type_ = std::nullopt;
Visitor::Visit(node->value); Visitor::Visit(node->value);
if (!context_manager_.EqualValues(return_type, current_type_)) {
if (!returned_type_.has_value()) {
returned_type_ = current_type_;
}
if (!context_manager_.EqualValues(returned_type, returned_type_.value())) {
error_handling::HandleTypecheckError("Wrong function return type", node->base); error_handling::HandleTypecheckError("Wrong function return type", node->base);
} }
returned_type_ = std::nullopt;
context_manager_.ExitContext(); context_manager_.ExitContext();
@ -639,35 +646,57 @@ void TypeCheckVisitor::Visit(LoopLoop* node) {
// Statements, expressions, blocks, etc. ----------------- // Statements, expressions, blocks, etc. -----------------
// TODO: check, that last statement in function definition has return type
void TypeCheckVisitor::Visit(Block* node) { void TypeCheckVisitor::Visit(Block* node) {
// TODO: types can be different in statement // TODO: types can be different in statement
utils::IdType type; std::optional<utils::IdType> brought_type;
std::optional<utils::IdType> returned_type = returned_type_;
bool is_type_found = false;
context_manager_.EnterContext(); context_manager_.EnterContext();
for (auto& statement : node->statements) { for (auto& statement : node->statements) {
brought_type_ = std::nullopt;
returned_type_ = std::nullopt; returned_type_ = std::nullopt;
Visitor::Visit(statement); Visitor::Visit(statement);
if (returned_type_.has_value()) {
if (!is_type_found) { if (brought_type_.has_value()) {
type = returned_type_.value(); if (!brought_type.has_value()) {
is_type_found = true; brought_type = brought_type_.value();
} else { } else {
if (!context_manager_.EqualValues(type, returned_type_.value())) { if (!context_manager_.EqualValues(brought_type.value(), brought_type_.value())) {
error_handling::HandleTypecheckError("Different return types in block", node->base); error_handling::HandleTypecheckError("Different brought types in block", node->base);
}
}
}
if (returned_type_.has_value()) {
if (!returned_type.has_value()) {
returned_type = returned_type_.value();
} else {
if (!context_manager_.EqualValues(returned_type.value(), returned_type_.value())) {
error_handling::HandleTypecheckError("Different returned types in block", node->base);
} }
} }
// returned_type_ = std::nullopt; // not needed
} }
} }
context_manager_.EnterContext(); context_manager_.EnterContext();
if (!is_type_found) { if (brought_type.has_value()
type = context_manager_.AddValue(info::type::InternalType::Unit, utils::ValueType::Tmp); && !context_manager_.EqualValues(brought_type.value(),
context_manager_.AddValue(info::type::InternalType::Unit,
utils::ValueType::Tmp))
&& !brought_type_.has_value()) {
error_handling::HandleTypecheckError("Different brought types in block (no return at end)", node->base);
} }
current_type_ = type; if (brought_type.has_value()) {
current_type_ = brought_type.value();
} else {
current_type_ = context_manager_.AddValue(info::type::InternalType::Unit, utils::ValueType::Tmp);
}
returned_type_ = returned_type;
brought_type_ = std::nullopt;
node->base.type_ = current_type_; node->base.type_ = current_type_;
} }
@ -864,7 +893,11 @@ void TypeCheckVisitor::Visit(VariantExpression* node) {
void TypeCheckVisitor::Visit(ReturnExpression* node) { void TypeCheckVisitor::Visit(ReturnExpression* node) {
Visitor::Visit(node->expression); Visitor::Visit(node->expression);
returned_type_ = current_type_; if (node->is_from_definition) {
returned_type_ = current_type_;
} else {
brought_type_ = current_type_;
}
current_type_ = context_manager_.AddValue(info::type::InternalType::Unit, utils::ValueType::Tmp); current_type_ = context_manager_.AddValue(info::type::InternalType::Unit, utils::ValueType::Tmp);

View file

@ -385,7 +385,13 @@ void TypedPrintVisitor::Visit(MatchCase* node) {
} }
void TypedPrintVisitor::Visit(Match* node) { void TypedPrintVisitor::Visit(Match* node) {
out_ << "[Match : "; out_ << "[Match";
if (node->is_consuming_value) {
out_ << " <-";
}
out_ << " : ";
if (node->base.type_.has_value()) { if (node->base.type_.has_value()) {
out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName();
@ -657,7 +663,11 @@ void TypedPrintVisitor::Visit(VariantExpression* node) {
} }
void TypedPrintVisitor::Visit(ReturnExpression* node) { void TypedPrintVisitor::Visit(ReturnExpression* node) {
out_ << "[Return : "; if (node->is_from_definition) {
out_ << "[Return : ";
} else {
out_ << "[Bring : ";
}
if (node->base.type_.has_value()) { if (node->base.type_.has_value()) {
out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName(); out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName();

View file

@ -1,8 +1,9 @@
namespace Employee { namespace Employee {
decl gen_employee : Unit -> Employee decl gen_employee : Unit -> Employee
def gen_employee = { def gen_employee = {
var x = $@Complex & 11.3 & 15.87 // construct on heap
return return
$Employee $Employee // construct on stack
& name = "John" & name = "John"
& role = & role =
($Manager ($Manager

View file

@ -1,6 +1,7 @@
decl fruit_cost : Fruit -> Int decl fruit_cost : Fruit -> Int
def fruit_cost : fruit = { def fruit_cost : fruit = {
return (match fruit with var fruit_copy = fruit
return (match <- fruit_copy with // consuming match
| $Banana -> 11 | $Banana -> 11
| $Apple | $Orange -> 7) | $Apple | $Orange -> 7)
} }

View file

@ -142,5 +142,5 @@ def func : s = {
exec main { exec main {
for i in (,0 ,1 ,2 ,3) do func: "abacaba" for i in (,0 ,1 ,2 ,3) do func: "abacaba"
; print: ({ return read: }) ; print: ({ bring read: })
} }