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_;
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_;
bool case_matched_;
};

View file

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

View file

@ -178,6 +178,7 @@ private:
std::unordered_set<utils::IdType> type_namespaces_;
utils::IdType current_type_;
std::optional<utils::IdType> returned_type_;
std::optional<utils::IdType> brought_type_;
std::optional<utils::IsConstModifier> is_const_definition_;
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_;
node->is_consuming_value = (parse_node.NthChild(1).GetValue() == "<-");
current_node_ = parse_node.ChildByFieldName("value");
Visit(node->value);
@ -924,6 +926,8 @@ void BuildVisitor::Visit(ReferenceExpression* node) {
node->references[i] = utils::ReferenceModifier::Reference;
} else if (reference == "~") {
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_;
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");
Visit(node->expression);
@ -1077,6 +1083,8 @@ void BuildVisitor::Visit(TypeConstructor* node) {
auto parse_node = current_node_;
node->is_allocated_on_heap = (parse_node.NthChild(1).GetValue() == "@");
current_node_ = parse_node.ChildByFieldName("constructor");
node->constructor = std::make_unique<TypeExpression>();
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
// Visit(node->definition.get());
context_manager_.EnterContext();
returned_value_ = std::nullopt;
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();
}
@ -308,20 +317,27 @@ void ExecuteVisitor::Visit(Block* node) {
context_manager_.EnterContext();
for (auto& statement : node->statements) {
returned_value_ = std::nullopt;
brought_value_ = std::nullopt;
Visitor::Visit(statement);
if (returned_value_.has_value()) {
current_value_ = returned_value_.value();
returned_value_ = std::nullopt; // TODO: ?? ("return" exits only from one block)
return;
brought_value_ = std::nullopt;
break;
}
if (brought_value_.has_value()) {
break;
}
}
context_manager_.ExitContext();
current_value_ = context_manager_.AddValue(
info::value::InternalValue(info::value::Unit()),
utils::ValueType::Tmp);
if (brought_value_.has_value()) {
current_value_ = brought_value_.value();
brought_value_ = std::nullopt;
} else {
current_value_ = context_manager_.AddValue(
info::value::InternalValue(info::value::Unit()),
utils::ValueType::Tmp);
}
}
void ExecuteVisitor::Visit(ScopedStatement* node) {
@ -332,7 +348,7 @@ void ExecuteVisitor::Visit(LoopControlExpression& node) {
active_loop_control_expression_ = node;
current_value_ = context_manager_.AddValue(info::value::InternalValue(info::value::Unit()),
utils::ValueType::Tmp); // ??
utils::ValueType::Tmp);
}
// Operators
@ -563,7 +579,15 @@ void ExecuteVisitor::Visit(VariantExpression* node) {
void ExecuteVisitor::Visit(ReturnExpression* node) {
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) {
out_ << "[Match] (";
out_ << "[Match";
if (node->is_consuming_value) {
out_ << " <- ";
}
out_ << "] (";
Visitor::Visit(node->value);
out_ << ") [with] (\n";
for (auto& match_case : node->matches) {
@ -476,7 +480,12 @@ void PrintVisitor::Visit(VariantExpression* node) {
}
void PrintVisitor::Visit(ReturnExpression* node) {
out_ << "[Return] (";
if (node->is_from_definition) {
out_ << "[Return] (";
} else {
out_ << "[Bring] (";
}
Visitor::Visit(node->expression);
out_ << ")\n";
}

View file

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

View file

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

View file

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

View file

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

View file

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