mirror of
https://codeberg.org/ProgramSnail/lang_2023.git
synced 2025-12-06 06:58:45 +00:00
constructors on heap, consuming match, move modifier in reference expression, .bring. keyword to return from block, some fixes
This commit is contained in:
parent
2556efcaba
commit
8a84cfff70
12 changed files with 128 additions and 34 deletions
|
|
@ -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_;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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());
|
||||||
|
|
|
||||||
|
|
@ -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,21 +317,28 @@ 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();
|
||||||
|
|
||||||
|
if (brought_value_.has_value()) {
|
||||||
|
current_value_ = brought_value_.value();
|
||||||
|
brought_value_ = std::nullopt;
|
||||||
|
} else {
|
||||||
current_value_ = context_manager_.AddValue(
|
current_value_ = context_manager_.AddValue(
|
||||||
info::value::InternalValue(info::value::Unit()),
|
info::value::InternalValue(info::value::Unit()),
|
||||||
utils::ValueType::Tmp);
|
utils::ValueType::Tmp);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ExecuteVisitor::Visit(ScopedStatement* node) {
|
void ExecuteVisitor::Visit(ScopedStatement* node) {
|
||||||
Visitor::Visit(node->statement); // current_value_ passed from statement
|
Visitor::Visit(node->statement); // current_value_ passed from statement
|
||||||
|
|
@ -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);
|
||||||
|
if (node->is_from_definition) {
|
||||||
returned_value_ = current_value_;
|
returned_value_ = current_value_;
|
||||||
|
} else {
|
||||||
|
brought_value_ = current_value_;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_value_ = context_manager_.AddValue(
|
||||||
|
info::value::InternalValue(info::value::Unit()),
|
||||||
|
utils::ValueType::Tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
if (node->is_from_definition) {
|
||||||
out_ << "[Return] (";
|
out_ << "[Return] (";
|
||||||
|
} else {
|
||||||
|
out_ << "[Bring] (";
|
||||||
|
}
|
||||||
|
|
||||||
Visitor::Visit(node->expression);
|
Visitor::Visit(node->expression);
|
||||||
out_ << ")\n";
|
out_ << ")\n";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
if (node->is_from_definition) {
|
||||||
returned_type_ = current_type_;
|
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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
if (node->is_from_definition) {
|
||||||
out_ << "[Return : ";
|
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();
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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: })
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue