const -> let

This commit is contained in:
ProgramSnail 2023-07-03 19:05:50 +03:00
parent 3ae6ed079d
commit 189306df26
33 changed files with 406 additions and 285 deletions

View file

@ -315,6 +315,8 @@ void BuildVisitor::Visit(PartitionStatement* node) {
node->modifier = utils::PartitionModifier::Exec;
} else if (partition_modifier == "test") {
node->modifier = utils::PartitionModifier::Test;
} else if (partition_modifier == "example") {
node->modifier = utils::PartitionModifier::Example;
} else {
// error
}
@ -826,6 +828,15 @@ void BuildVisitor::Visit(Expression& node) {
} else if (current_node_type == parser::tokens::SubExpression) {
node = std::make_unique<SubExpression>();
Visit(*std::get<std::unique_ptr<SubExpression>>(node));
} else if (current_node_type == parser::tokens::AndExpression) {
node = std::make_unique<AndExpression>();
Visit(std::get<std::unique_ptr<AndExpression>>(node).get());
} else if (current_node_type == parser::tokens::OrExpression) {
node = std::make_unique<OrExpression>();
Visit(std::get<std::unique_ptr<OrExpression>>(node).get());
} else if (current_node_type == parser::tokens::ArrayExpression) {
node = std::make_unique<ArrayExpression>();
Visit(std::get<std::unique_ptr<ArrayExpression>>(node).get());
} else {
// error
}
@ -849,9 +860,6 @@ void BuildVisitor::Visit(SuperExpression& node) {
} else if (current_node_type == parser::tokens::VariantExpression) {
node = std::make_unique<VariantExpression>();
Visit(std::get<std::unique_ptr<VariantExpression>>(node).get());
} else if (current_node_type == parser::tokens::ArrayExpression) {
node = std::make_unique<ArrayExpression>();
Visit(std::get<std::unique_ptr<ArrayExpression>>(node).get());
} else if (current_node_type == parser::tokens::Expression) {
node = std::make_unique<Expression>();
Visit(*std::get<std::unique_ptr<Expression>>(node));
@ -884,7 +892,7 @@ void BuildVisitor::VisitBinaryOperatorExpression(FunctionCallExpression* node) {
node->arguments.resize(2);
current_node_ = parse_node.ChildByFieldName("left_expression");
Visit(node->arguments[0]);
Visit(node->arguments[0].second);
node->name = parse_node.ChildByFieldName("operator_name").GetValue();
@ -896,15 +904,16 @@ void BuildVisitor::VisitBinaryOperatorExpression(FunctionCallExpression* node) {
}
current_node_ = parse_node.ChildByFieldName("right_expression");
Visit(node->arguments[1]);
Visit(node->arguments[1].second);
// ??
for (size_t i = 0; i < node->arguments.size(); ++i) {
if (std::holds_alternative<std::unique_ptr<FunctionCallExpression>>(node->arguments[i])) {
FunctionCallExpression* argument_node = std::get<std::unique_ptr<FunctionCallExpression>>(node->arguments[i]).get();
if (std::holds_alternative<std::unique_ptr<FunctionCallExpression>>(node->arguments[i].second)) {
FunctionCallExpression* argument_node = std::get<std::unique_ptr<FunctionCallExpression>>(node->arguments[i].second).get();
if (argument_node->is_binary_operator_expression
&& argument_node->precedence.has_value()
&& argument_node->precedence.value() == node->precedence.value()) {
&& argument_node->precedence.value() == node->precedence.value()
&& node->name != argument_node->name) { // same operators can be chained
error_handling::HandleParsingError("Operators can't be chained (left argument)", node->base.start_position, node->base.end_position);
}
}
@ -986,6 +995,7 @@ void BuildVisitor::Visit(FunctionCallExpression* node) {
if (child_count > excluded_child_count) {
bool parameters_ended = false;
bool last_child_is_annotation = false;
for (size_t i = 0; i + excluded_child_count < child_count; ++i) {
current_node_ = parse_node.NthNamedChild(i + excluded_child_count);
@ -998,10 +1008,26 @@ void BuildVisitor::Visit(FunctionCallExpression* node) {
node->parameters.push_back(std::make_unique<TypeExpression>());
Visit(node->parameters.back().get());
} else {
node->arguments.push_back(std::make_unique<SubExpressionToken>());
Visit(*std::get<std::unique_ptr<SubExpressionToken>>(node->arguments.back()));
if (!current_node_.PreviousSibling().IsNull() && current_node_.PreviousSibling().GetValue() == "::") { // annotation
node->arguments.push_back({current_node_.GetValue(), SubExpression()});
last_child_is_annotation = true;
} else if (last_child_is_annotation) { // argument after annotation
node->arguments.back().second = std::make_unique<SubExpressionToken>();
Visit(*std::get<std::unique_ptr<SubExpressionToken>>(node->arguments.back().second));
last_child_is_annotation = false;
} else { // argument without annotation
node->arguments.push_back({std::nullopt, std::make_unique<SubExpressionToken>()});
Visit(*std::get<std::unique_ptr<SubExpressionToken>>(node->arguments.back().second));
last_child_is_annotation = false;
}
}
}
if (last_child_is_annotation) {
error_handling::HandleInternalError("Last child is annotation",
"BuildVisitor.FunctionCallExpression",
&node->base);
}
}
current_node_ = parse_node;
@ -1137,6 +1163,40 @@ void BuildVisitor::Visit(LambdaFunction* node) {
current_node_ = parse_node;
}
void BuildVisitor::Visit(AndExpression* node) {
SetPosition(node->base, current_node_);
auto parse_node = current_node_;
size_t expressions_count = parse_node.NamedChildCount();
node->expressions.resize(expressions_count);
for (size_t i = 0; i < expressions_count; ++i) {
current_node_ = parse_node.NthNamedChild(i);
Visit(node->expressions[i]);
}
current_node_ = parse_node;
}
void BuildVisitor::Visit(OrExpression* node) {
SetPosition(node->base, current_node_);
auto parse_node = current_node_;
size_t expressions_count = parse_node.NamedChildCount();
node->expressions.resize(expressions_count);
for (size_t i = 0; i < expressions_count; ++i) {
current_node_ = parse_node.NthNamedChild(i);
Visit(node->expressions[i]);
}
current_node_ = parse_node;
}
void BuildVisitor::Visit(ArrayExpression* node) {
SetPosition(node->base, current_node_);
@ -1296,12 +1356,31 @@ void BuildVisitor::Visit(FunctionType* node) {
size_t types_count = parse_node.NamedChildCount();
node->types.resize(types_count);
node->types.reserve(types_count);
bool last_child_is_annotation = false;
for (size_t i = 0; i < types_count; ++i) {
current_node_ = parse_node.NthNamedChild(i);
node->types[i] = std::make_unique<ExtendedScopedAnyType>();
Visit(node->types[i].get());
if (!current_node_.PreviousSibling().IsNull() && current_node_.PreviousSibling().GetValue() == "::") { // annotation
node->types.push_back({current_node_.GetValue(), nullptr});
last_child_is_annotation = true;
} else if (last_child_is_annotation) { // argument after annotation
node->types.back().second = std::make_unique<ExtendedScopedAnyType>();
Visit(node->types.back().second.get());
last_child_is_annotation = false;
} else { // argument without annotation
node->types.push_back({std::nullopt, std::make_unique<ExtendedScopedAnyType>()});
Visit(node->types.back().second.get());
last_child_is_annotation = false;
}
}
if (last_child_is_annotation) {
error_handling::HandleInternalError("Last child is annotation",
"BuildVisitor.FunctionType",
&node->base);
}
current_node_ = parse_node;

View file

@ -477,7 +477,7 @@ void ExecuteVisitor::Visit(FunctionCallExpression* node) {
}
} else {
if (node->is_method_of_first_argument_) {
Visitor::Visit(node->arguments[0]);
Visitor::Visit(node->arguments[0].second);
if (context_manager_.GetValueType(current_value_) == utils::ValueType::Tmp) {
// temporary value can't be modified inside
@ -598,7 +598,7 @@ void ExecuteVisitor::Visit(FunctionCallExpression* node) {
// handle arguments
for (size_t i = index_shift; i < node->arguments.size(); ++i) {
Visitor::Visit(node->arguments[i]);
Visitor::Visit(node->arguments[i].second);
// function arguments can't be changed inside function
current_value_ = context_manager_.ToModifiedValue(current_value_, utils::ValueType::Const);
@ -711,6 +711,38 @@ void ExecuteVisitor::Visit(LambdaFunction* node) {
&node->base);
}
void ExecuteVisitor::Visit(AndExpression* node) {
bool result = true;
for (auto& expression : node->expressions) {
Visitor::Visit(expression);
if (!*ExtractInternalValue<bool>(current_value_, node->base)) {
result = false;
break;
}
}
current_value_ = context_manager_.AddValue(
info::value::InternalValue(result),
utils::ValueType::Tmp);
}
void ExecuteVisitor::Visit(OrExpression* node) {
bool result = false;
for (auto& expression : node->expressions) {
Visitor::Visit(expression);
if (*ExtractInternalValue<bool>(current_value_, node->base)) {
result = true;
break;
}
}
current_value_ = context_manager_.AddValue(
info::value::InternalValue(result),
utils::ValueType::Tmp);
}
void ExecuteVisitor::Visit(ArrayExpression* node) {
std::vector<utils::IdType> elements;
@ -1014,7 +1046,7 @@ void ExecuteVisitor::CheckPattern(Pattern& node, const BaseNode& base_node) {
bool ExecuteVisitor::HandleBuiltinFunctionCall(FunctionCallExpression* node) {
if (node->name == "print") {
Visitor::Visit(node->arguments[0]);
Visitor::Visit(node->arguments[0].second);
info::builtin::Print(*ExtractInternalValue<std::string>(current_value_, node->base));
current_value_ = context_manager_.AddValue(info::value::InternalValue(info::value::Unit()),
@ -1025,6 +1057,13 @@ bool ExecuteVisitor::HandleBuiltinFunctionCall(FunctionCallExpression* node) {
} else if (node->name == "random") { // TODO: different types, better random, seed, etc.
current_value_ = context_manager_.AddValue(info::value::InternalValue(rand()),
utils::ValueType::Tmp);
} else if (node->name == "error") {
Visitor::Visit(node->arguments[0].second);
info::builtin::Error(*ExtractInternalValue<std::string>(current_value_, node->base));
error_handling::HandleInternalError("Error function finished",
"ExecuteVisitor.HandleBuiltinFunctionCall",
&node->base);
} else {
return false;
}
@ -1046,7 +1085,7 @@ bool ExecuteVisitor::HandleBuiltinTypeFunctionCall(FunctionCallExpression* node,
}
for (auto& argument : node->arguments) {
Visitor::Visit(argument);
Visitor::Visit(argument.second);
arguments.push_back(ExtractValue<info::value::InternalValue>(current_value_, node->base));
}

View file

@ -65,7 +65,7 @@ void FindSymbolsVisitor::Visit(FunctionDeclaration* node) {
info.argument_types.resize(node->type->types.size());
for (size_t i = 0; i < node->type->types.size(); ++i) {
info.argument_types[i] = node->type->types[i].get();
info.argument_types[i] = node->type->types[i].second.get();
}
info.node = node;
@ -179,6 +179,7 @@ void FindSymbolsVisitor::Visit(TypeclassDefinitionStatement* node) {
}
void FindSymbolsVisitor::Visit(PartitionStatement* node) {
// TODO: difference between partitions ??
node->executable_id_ = namespace_visitor_.AddPartition(node->name.path, node, node->base);
Visitor::Visit(node->value); // to visit all tree

View file

@ -193,6 +193,9 @@ void PrintVisitor::Visit(PartitionStatement* node) {
case utils::PartitionModifier::Test:
out_ << "test ";
break;
case utils::PartitionModifier::Example:
out_ << "example ";
break;
}
Visit(&node->name);
out_ << "] = (";
@ -460,7 +463,13 @@ void PrintVisitor::Visit(FunctionCallExpression* node) {
}
is_first = false;
Visitor::Visit(argument);
if (argument.first.has_value()) {
out_ << "::";
Visit(&argument.first.value());
out_ << ' ';
}
Visitor::Visit(argument.second);
}
out_ << ")";
}
@ -544,6 +553,24 @@ void PrintVisitor::Visit(LambdaFunction* node) {
out_ << ")\n";
}
void PrintVisitor::Visit(AndExpression* node) {
out_ << "[AndExpression] (";
for (auto& expression : node->expressions) {
out_ << "&&";
Visitor::Visit(expression);
}
out_ << ")";
}
void PrintVisitor::Visit(OrExpression* node) {
out_ << "[OrExpression] (";
for (auto& expression : node->expressions) {
out_ << "||";
Visitor::Visit(expression);
}
out_ << ")";
}
void PrintVisitor::Visit(ArrayExpression* node) {
out_ << "[ArrayExpression] ( ,";
for (auto& element : node->elements) {
@ -619,7 +646,14 @@ void PrintVisitor::Visit(FunctionType* node) {
out_ << " -> ";
}
is_first = false;
Visit(type.get());
if (type.first.has_value()) {
out_ << "::";
Visit(&type.first.value());
out_ << ' ';
}
Visit(type.second.get());
}
out_ << ')';
}

View file

@ -239,14 +239,14 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) {
}
for (size_t i = 0; i < node->definition->arguments.size(); ++i) {
Visit(declaration->type->types[i].get());
Visit(declaration->type->types[i].second.get());
current_type_ = context_manager_.ToModifiedValue(current_type_, utils::ValueType::Const);
if (!context_manager_.DefineVariable(node->definition->arguments[i], current_type_)) {
error_handling::HandleTypecheckError("Can't define function argument variable: name redefinition", node->base);
}
}
Visit(declaration->type->types.back().get());
Visit(declaration->type->types.back().second.get());
utils::IdType returned_type = current_type_;
returned_type_ = std::nullopt;
@ -828,10 +828,18 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) {
}
for (size_t i = index_shift; i < node->arguments.size(); ++i) {
Visit(function_declaration->type->types[i - index_shift].get());
Visit(function_declaration->type->types[i - index_shift].second.get());
utils::IdType argument_type = TypeInContext(current_type_, context);
Visitor::Visit(node->arguments[i]);
if (node->arguments[i].first.has_value()) {
if (!function_declaration->type->types[i - index_shift].first.has_value()) {
error_handling::HandleTypecheckError("Declared argument has no annotation (argument " + std::to_string(i - index_shift + 1) + ")", node->base);
} else if (node->arguments[i].first.value() != function_declaration->type->types[i - index_shift].first.value()) {
error_handling::HandleTypecheckError("Wrong argument annotation (argument " + std::to_string(i - index_shift + 1) + ")", node->base);
}
}
Visitor::Visit(node->arguments[i].second);
if (!context_manager_.AddValueRequirement(current_type_, argument_type)) {
error_handling::HandleTypecheckError("Wrong argument type (argument " + std::to_string(i - index_shift + 1) + ")", node->base);
}
@ -863,7 +871,7 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) {
}
}
Visit(function_declaration->type->types.back().get());
Visit(function_declaration->type->types.back().second.get());
current_type_ = TypeInContext(current_type_, context);
context_manager_.ExitContext();
@ -1052,6 +1060,32 @@ void TypeCheckVisitor::Visit(LambdaFunction* node) {
node->base.type_ = current_type_;
}
void TypeCheckVisitor::Visit(AndExpression* node) {
for (auto& expression : node->expressions) {
Visitor::Visit(expression);
if (!context_manager_.EqualValues(internal_to_abstract_type_.at(info::type::InternalType::Bool), current_type_)) {
error_handling::HandleTypecheckError("And expression element is not bool expression", node->base);
}
}
current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Bool);
node->base.type_ = current_type_;
}
void TypeCheckVisitor::Visit(OrExpression* node) {
for (auto& expression : node->expressions) {
Visitor::Visit(expression);
if (!context_manager_.EqualValues(internal_to_abstract_type_.at(info::type::InternalType::Bool), current_type_)) {
error_handling::HandleTypecheckError("Or expression element is not bool expression", node->base);
}
}
current_type_ = internal_to_abstract_type_.at(info::type::InternalType::Bool);
node->base.type_ = current_type_;
}
void TypeCheckVisitor::Visit(ArrayExpression* node) {
utils::IdType elements_type = 0;
@ -1282,7 +1316,7 @@ void TypeCheckVisitor::Visit(FunctionType* node) {
std::vector<utils::IdType> argument_types(node->types.size());
for (auto& argument_type : node->types) {
Visit(argument_type.get());
Visit(argument_type.second.get());
argument_types.push_back(current_type_);
}
@ -1677,8 +1711,8 @@ std::optional<FunctionDeclaration*> TypeCheckVisitor::FindFunctionAndUpdate(Func
}
}
if (!maybe_function_declaration.has_value() && node->is_binary_operator_expression && node->arguments.size() > 0) {
Visitor::Visit(node->arguments[0]);
if (!maybe_function_declaration.has_value() && node->is_binary_operator_expression && node->arguments.size() > 0 && !node->arguments[0].first.has_value()) { // ... , no annotation
Visitor::Visit(node->arguments[0].second);
maybe_function_declaration = FindExpressionMethodAndUpdate(node, current_type_);
if (maybe_function_declaration.has_value()) {
node->is_method_of_first_argument_ = true;

View file

@ -260,6 +260,9 @@ void TypedPrintVisitor::Visit(PartitionStatement* node) {
case utils::PartitionModifier::Test:
out_ << "test ";
break;
case utils::PartitionModifier::Example:
out_ << "example ";
break;
}
Visit(&node->name);
out_ << "] = (";
@ -631,7 +634,13 @@ void TypedPrintVisitor::Visit(FunctionCallExpression* node) {
}
is_first = false;
Visitor::Visit(argument);
if (argument.first.has_value()) {
out_ << "::";
Visit(&argument.first.value());
out_ << ' ';
}
Visitor::Visit(argument.second);
}
out_ << ")";
}
@ -750,6 +759,36 @@ void TypedPrintVisitor::Visit(LambdaFunction* node) {
out_ << ")\n";
}
void TypedPrintVisitor::Visit(AndExpression* node) {
out_ << "[AndExpression : ";
if (node->base.type_.has_value()) {
out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName();
}
out_ << "] (";
for (auto& expression : node->expressions) {
out_ << "&&";
Visitor::Visit(expression);
}
out_ << ")";
}
void TypedPrintVisitor::Visit(OrExpression* node) {
out_ << "[OrExpression : ";
if (node->base.type_.has_value()) {
out_ << context_manager_.GetAnyValue(node->base.type_.value())->GetTypeName();
}
out_ << "] (";
for (auto& expression : node->expressions) {
out_ << "||";
Visitor::Visit(expression);
}
out_ << ")";
}
void TypedPrintVisitor::Visit(ArrayExpression* node) {
out_ << "[ArrayExpression : ";
@ -873,7 +912,14 @@ void TypedPrintVisitor::Visit(FunctionType* node) {
out_ << " -> ";
}
is_first = false;
Visit(type.get());
if (type.first.has_value()) {
out_ << "::";
Visit(&type.first.value());
out_ << ' ';
}
Visit(type.second.get());
}
out_ << ')';
}

View file

@ -56,6 +56,8 @@ std::optional<char> ToEscapeSymbol(char symbol) {
return '\t';
case 'v':
return '\v';
case 's':
return ' ';
default:
return std::nullopt;
}
@ -82,6 +84,7 @@ bool IsBuiltinFunction(const std::string& name) { // optimize ??
builtin_functions.insert("one");
builtin_functions.insert("show");
builtin_functions.insert("read");
builtin_functions.insert("error");
// builtin_functions.insert("debug_show"); // TODO
return builtin_functions.count(name) != 0;

View file

@ -188,6 +188,15 @@ void Visitor::Visit(Expression& node) {
case 3:
Visit(*std::get<std::unique_ptr<SubExpression>>(node));
break;
case 4:
Visit(std::get<std::unique_ptr<AndExpression>>(node).get());
break;
case 5:
Visit(std::get<std::unique_ptr<OrExpression>>(node).get());
break;
case 6:
Visit(std::get<std::unique_ptr<ArrayExpression>>(node).get());
break;
default:
// error
break;
@ -206,9 +215,6 @@ void Visitor::Visit(SuperExpression& node) {
Visit(std::get<std::unique_ptr<VariantExpression>>(node).get());
break;
case 3:
Visit(std::get<std::unique_ptr<ArrayExpression>>(node).get());
break;
case 4:
Visit(*std::get<std::unique_ptr<Expression>>(node));
break;
default:
@ -500,7 +506,10 @@ void Visitor::Visit(FunctionCallExpression* node) {
}
for (auto& argument : node->arguments) {
Visit(argument);
if (argument.first.has_value()) {
Visit(&argument.first.value());
}
Visit(argument.second);
}
}
@ -544,6 +553,18 @@ void Visitor::Visit(LambdaFunction* node) {
Visit(node->expression);
}
void Visitor::Visit(AndExpression* node) {
for (auto& expression : node->expressions) {
Visit(expression);
}
}
void Visitor::Visit(OrExpression* node) {
for (auto& expression : node->expressions) {
Visit(expression);
}
}
void Visitor::Visit(ArrayExpression* node) {
for (auto& element : node->elements) {
Visit(element);
@ -590,7 +611,10 @@ void Visitor::Visit(Name* node) {
void Visitor::Visit(FunctionType* node) {
for (auto& type : node->types) {
Visit(type.get());
if (type.first.has_value()) {
Visit(&type.first.value());
}
Visit(type.second.get());
}
}