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

@ -91,6 +91,8 @@ private:
void Visit(TypeConstructorParameter* node) override;
void Visit(TypeConstructor* node) override;
void Visit(LambdaFunction* node) override;
void Visit(AndExpression* node) override;
void Visit(OrExpression* node) override;
void Visit(ArrayExpression* node) override;
void Visit(LoopControlExpression& node) override; // enum

View file

@ -22,4 +22,12 @@ inline T Read() {
return value;
}
template<typename T>
inline void Error(const T& value) { // only for strings ??
std::cout << "\x1b[1;33mError:\x1b[0m ";
std::cout << value;
std::cout << '\n';
exit(1);
}
} // namespace info

View file

@ -100,6 +100,8 @@ private:
void Visit(TypeConstructorParameter* node) override;
void Visit(TypeConstructor* node) override;
void Visit(LambdaFunction* node) override;
void Visit(AndExpression* node) override;
void Visit(OrExpression* node) override;
void Visit(ArrayExpression* node) override;
void Visit(LoopControlExpression& node) override; // enum

View file

@ -76,6 +76,8 @@ private:
// // void Visit(TypeConstructorParameter* node) override;
// // void Visit(TypeConstructor* node) override;
// // void Visit(LambdaFunction* node) override;
// // void Visit(AndExpression* node) override;
// // void Visit(OrExpression* node) override;
// // void Visit(ArrayExpression* node) override;
// // void Visit(LoopControlExpression& node) override; // enum

View file

@ -131,7 +131,6 @@ using SubExpressionToken = std::variant<
std::unique_ptr<ReferenceExpression>>;
//
struct FunctionCallExpression;
struct ArrayExpression;
using SubExpression = std::variant< // BiaryOperatorExpression is FunctionCallExpression
std::unique_ptr<FunctionCallExpression>,
std::unique_ptr<SubExpressionToken>>;
@ -149,11 +148,17 @@ using PrefixedExpression = std::variant<
//
struct LambdaFunction;
struct TypeConstructor;
struct AndExpression;
struct OrExpression;
struct ArrayExpression;
using Expression = std::variant<
std::unique_ptr<LambdaFunction>,
std::unique_ptr<TypeConstructor>,
std::unique_ptr<PrefixedExpression>,
std::unique_ptr<SubExpression>>;
std::unique_ptr<SubExpression>,
std::unique_ptr<AndExpression>,
std::unique_ptr<OrExpression>,
std::unique_ptr<ArrayExpression>>;
//
struct TupleExpression;
struct VariantExpression;
@ -161,7 +166,6 @@ using SuperExpression = std::variant<
std::unique_ptr<FlowControl>,
std::unique_ptr<TupleExpression>,
std::unique_ptr<VariantExpression>,
std::unique_ptr<ArrayExpression>,
std::unique_ptr<Expression>>;
//
@ -181,6 +185,8 @@ struct ReturnExpression;
struct TypeConstructorParameter;
struct TypeConstructor;
struct LambdaFunction;
struct AndExpression;
struct OrExpression;
struct ArrayExpression;
// Name
@ -525,7 +531,7 @@ struct FunctionCallExpression {
std::unique_ptr<WrappedTypeExpression>>> prefix;
NameOrOperatorIdentifier name;
std::vector<std::unique_ptr<TypeExpression>> parameters;
std::vector<SubExpression> arguments;
std::vector<std::pair<std::optional<NameIdentifier>, SubExpression>> arguments;
std::optional<size_t> precedence; // for operators
bool is_binary_operator_expression = false; // for operators
@ -587,6 +593,18 @@ struct LambdaFunction {
utils::IdType return_type_graph_id_ = 0;
};
struct AndExpression {
BaseNode base;
std::vector<SubExpression> expressions;
};
struct OrExpression {
BaseNode base;
std::vector<SubExpression> expressions;
};
struct ArrayExpression {
BaseNode base;
@ -632,7 +650,7 @@ struct Name {
struct FunctionType {
BaseNode base;
std::vector<std::unique_ptr<ExtendedScopedAnyType>> types;
std::vector<std::pair<std::optional<NameIdentifier>, std::unique_ptr<ExtendedScopedAnyType>>> types;
};
struct TupleType {

View file

@ -85,6 +85,8 @@ private:
// // void Visit(TypeConstructorParameter* node) override;
// // void Visit(TypeConstructor* node) override;
// // void Visit(LambdaFunction* node) override;
// // void Visit(AndExpression* node) override;
// // void Visit(OrExpression* node) override;
// // void Visit(ArrayExpression* node) override;
// // void Visit(LoopControlExpression& node) override; // enum

View file

@ -77,6 +77,8 @@ const std::string ReturnExpression = "return_expression";
const std::string TypeConstructorParameter = "type_constructor_parameter";
const std::string TypeConstructor = "type_constructor";
const std::string LambdaFunction = "lambda_function";
const std::string AndExpression = "and_expression";
const std::string OrExpression = "or_expression";
const std::string ArrayExpression = "array_expression";
const std::string LoopControlExpression = "loop_control_expression";

View file

@ -74,6 +74,8 @@ private:
void Visit(TypeConstructorParameter* node) override;
void Visit(TypeConstructor* node) override;
void Visit(LambdaFunction* node) override;
void Visit(AndExpression* node) override;
void Visit(OrExpression* node) override;
void Visit(ArrayExpression* node) override;
void Visit(LoopControlExpression& node) override; // enum

View file

@ -95,6 +95,8 @@ private:
void Visit(TypeConstructorParameter* node) override;
void Visit(TypeConstructor* node) override;
void Visit(LambdaFunction* node) override;
void Visit(AndExpression* node) override;
void Visit(OrExpression* node) override;
void Visit(ArrayExpression* node) override;
void Visit(LoopControlExpression& node) override; // enum

View file

@ -76,6 +76,8 @@ private:
void Visit(TypeConstructorParameter* node) override;
void Visit(TypeConstructor* node) override;
void Visit(LambdaFunction* node) override;
void Visit(AndExpression* node) override;
void Visit(OrExpression* node) override;
void Visit(ArrayExpression* node) override;
void Visit(LoopControlExpression& node) override; // enum

View file

@ -27,7 +27,7 @@ enum class ClassModifier { Struct = 0, Class = 1 };
enum class AssignmentModifier { Assign = 0, Move = 1 };
enum class AliasModifier { Alias = 0, Type = 1, Let = 2 };
enum class AbstractTypeModifier { Basic = 0, Abstract = 1 };
enum class PartitionModifier { Exec = 0, Test = 1 };
enum class PartitionModifier { Exec = 0, Test = 1, Example = 2 };
enum class ValueType { Const = 0, Var = 1, Tmp = 2 };

View file

@ -88,6 +88,8 @@ protected:
virtual void Visit(TypeConstructorParameter* node);
virtual void Visit(TypeConstructor* node);
virtual void Visit(LambdaFunction* node);
virtual void Visit(AndExpression* node);
virtual void Visit(OrExpression* node);
virtual void Visit(ArrayExpression* node);
virtual void Visit(LoopControlExpression& node); // enum

@ -1 +1 @@
Subproject commit 25f8750ab2a99222f61b4702419f8b4533ed8cf4
Subproject commit 8e69e96520290fab76a98e620d58a4478e9d0861

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());
}
}

View file

@ -1,18 +1,18 @@
decl test-arrays : -> \unit
def test-arrays = {
var arr1 = ,1 ,2 ,3
const arr2 = \int..array: 32
let arr2 = \int..array: 32
var arr3 = \string..array: 11
const arr4 = ''a--''z
const n = 100
let arr4 = ''a--''z
let n = 100
var arr5 <- \int..new-array: 10
var arr6 <- \string..new-array: 10
var arr6-reference = ^arr6
const elem1 = arr1`0
let elem1 = arr1`0
var elem2 = arr1`2
const ref1 = ^arr1`1
let ref1 = ^arr1`1
var ref2 = ^arr1`3
; arr1`1 = 123

View file

@ -1,14 +1,20 @@
decl flow-control-test : -> \unit
def flow-control-test = {
if (a < b ||. a == b) && (b < c) then \io..print: x
elif x < 0 then {
if && ( || a < b
|| a == b )
&& b < c
then \io..print: x
elif x < 0
then {
; x += 1
; \io..print: y
} else {
return {}
}
while (a > 0) && not: (array..is-empty:) do {
while && a > 0
&& not: (array..is-empty:)
do {
; a -= 1
; array..pop:
}

View file

@ -30,15 +30,15 @@ def find-prefix-hashes : str = {
alias \hash = \acc-hash[char]
decl find-substring : \string -> \string -> \array[index]
decl find-substring : ::str \string -> ::substr \string -> \array[index]
def find-substring : str substr = {
var result = \array[index]..empty:
const str-hashes = find-prefix-hashes:[hash] str
const substr-hash = \hash..of: substr
let str-hashes = find-prefix-hashes:[hash] str
let substr-hash = \hash..of: substr
for i in 0--(str-hashes..size: - substr..size:) do {
const part-hash = hash..diff: str-hashes`(i + substr..size:) str-hashes`i
let part-hash = hash..diff: str-hashes`(i + substr..size:) str-hashes`i
if part-hash == substr-hash then {
; result..push: i
@ -60,3 +60,9 @@ def mul : x y = x * y
decl mul-10 : \int -> \int
def mul-10 = mul: 10
exec main {
; find-substring:
::str "abacaba"
::substr "bac"
}

View file

@ -1,12 +1,12 @@
decl test-lambdas : -> \unit
def test-lambdas = {
const lambda1 = \\x -> x * x
const lambda2 = \\x -> x..hash:
const lambda3 = \\x y -> x + y
let lambda1 = \\x -> x * x
let lambda2 = \\x -> x..hash:
let lambda3 = \\x y -> x + y
const lambda4 = \\x -> {
let lambda4 = \\x -> {
; \io..print: x
const y = x + x
let y = x + x
return y
}
}

View file

@ -8,7 +8,7 @@ def fruit-cost : fruit = {
decl amount-to-string : \int -> \bool -> \string
def amount-to-string : x is-zero-separated = {
const ans = match x with
let ans = match x with
| 0 ?? is-zero-separated -> "Zero"
| 0 | 1 | 2 | 3 | 4 -> "Few"
| x ?? (5--9)..contains: x -> "Several"

View file

@ -3,6 +3,6 @@ struct \struct-with-ref =
decl test-memory : -> \unit
def test-memory = {
const unique-ref1 <- \int..new: 5
let unique-ref1 <- \int..new: 5
var unique-ref2 <- \array..of: 1 2 3
}

View file

@ -14,6 +14,6 @@ namespace var \array {
decl something : -> \unit
}
namespace const \array {
namespace let \array {
decl something : -> \unit
}

View file

@ -1,10 +1,14 @@
test all.dev.syntax.testing {
const a = 31
let a = 31
; do-something: a
}
exec app.exe {
const b = true
const c = false
let b = true
let c = false
; do-something-different: b b c
}
example func.basic-example {
; func: a b c // func executed
}

View file

@ -1,189 +0,0 @@
basic \float[#ord #div #str]
basic \int[#ord #idiv #str]
basic \string[#ord #str #char-container #copy]
basic \char[#ord #str #copy]
basic \bool[#ord #str #copy]
basic \unit[#str #copy]
//
decl not : \bool -> \bool
def not : x =
(match x with
| true -> false
| false -> true)
decl ( && ) : \bool -> \bool -> \bool
def ( && ) : x y =
match x with
| true -> (
match y with
| true -> true
| false -> false
)
| false -> false
decl ( || ) : \bool -> \bool -> \bool
def ( || ) : x y =
match x with
| true -> true
| false -> (
match y with
| true -> true
| false -> false
)
//
typeclass \char-container =
& var size : -> \int
& var at : \int -> \char
//
typeclass \move = // TODO
& var ( <- ) : \move -> \unit
typeclass \copy =
& var ( = ) : \copy -> \unit
//
typeclass \sum[#copy] =
& var ( += ) : \sum -> \unit
& var ( -= ) : \sum -> \unit
& var ( + ) : \sum -> \sum
& var ( - ) : \sum -> \sum
& zero : -> \sum
namespace var \sum {
def ( + ) : x = {
var ans = self
; ans += x
return ans
}
def ( - ) : x = {
var ans = self
; ans -= x
return ans
}
}
typeclass \mult[#sum] =
& var ( *= ) : \mult -> \unit
& var ( * ) : \mult -> \mult
namespace var \mult {
def ( * ) : x = {
var ans = self
; ans *= x
return ans
}
}
typeclass \idiv[#mult] =
& var div : \idiv -> \idiv
& var mod : \idiv -> \idiv
namespace var \idiv {
def mod : x = self -. x * self..div: x
}
typeclass \div[#mult] =
& var ( /= ) : \div -> \unit
& var ( / ) : \div -> \div
namespace var \div {
def ( / ) : x = {
var ans = self
; ans /= x
return ans
}
}
//
typeclass \eq =
& var ( == ) : \eq -> \bool
& var ( != ) : \eq -> \bool
namespace var \eq {
def ( != ) : x = not: (self == x)
}
//
struct \order =
| $eq
| $lt
| $gt
typeclass \ord[#eq] =
& var compare : \ord -> \order
& var ( < ) : \ord -> \bool
& var ( >= ) : \ord -> \bool
& var ( > ) : \ord -> \bool
& var ( <= ) : \ord -> \bool
decl min 'a[#ord] : 'a -> 'a -> 'a
def min : x y = if x < y then x else y
decl max 'a[#ord] : 'a -> 'a -> 'a
def max : x y = if x < y then y else x
namespace var \ord {
def compare : x =
if self == x then $eq
elif self < x then $lt
else $gt
def ( >= ) : x = not: (self < x)
def ( > ) : x = x < self
def ( <= ) : x = not: (x < self)
}
//
typeclass \show =
& var show : -> \string
typeclass \read =
& read : \string -> \read
typeclass \str[#show #read]
// typeclass debug-show = // TODO
// & debugdshow : -> \string
//
typeclass \default =
& default : -> \default
//
typeclass \bounded =
& min-bound : -> \bounded
& max-bound : -> \bounded
& var is-max-bound : -> \bool
& var is-min-bound : -> \bool
//
typeclass \enum =
& var succ : -> \optional[enum]
& var pred : -> \optional[enum]
& to-enum : \int -> \enum
& var from-enum : -> \int
//
namespace io {
decl print : \string -> \unit
decl scan : -> \string
}
decl random : -> \int // TODO
//

View file

@ -7,32 +7,23 @@ basic \unit[#str #copy]
//
namespace io {
decl print : \string -> \unit
decl scan : -> \string
}
decl random : -> \int // TODO
decl error : \string -> \unit
//
decl not : \bool -> \bool
def not : x =
(match x with
| true -> false
| false -> true)
decl ( && ) : \bool -> \bool -> \bool
def ( && ) : x y =
match x with
| true -> (
match y with
| true -> true
| false -> false
)
| false -> false
decl ( || ) : \bool -> \bool -> \bool
def ( || ) : x y =
match x with
| true -> true
| false -> (
match y with
| true -> true
| false -> false
)
//
typeclass \char-container =
@ -179,15 +170,6 @@ typeclass \enum =
//
namespace io {
decl print : \string -> \unit
decl scan : -> \string
}
decl random : -> \int // TODO
//
// // // bad
// // typeclass \functor 'a =
// // & fmap 'b ('f[#functor['b]]) : ('a -> 'b) -> \functor -> 'f
@ -231,7 +213,7 @@ def ( -- ) : begin end = {
decl scan-int : -> \int
def scan-int = \int..read: (\io..scan:)
decl print-int : \int -> \unit
decl print-int : ::x \int -> \unit
def print-int : x = \io..print: (x..show:)
decl scan-anything 'a[#read] : -> 'a
@ -277,6 +259,11 @@ def scan-three = & \io..scan: & \io..scan: & \io..scan:
exec main {
var n = scan-anything:[int]
; print-anything:[bool] (n < 2) // TODO: fix exception (arguments not present ??)
if n > 1 then print-anything:[string] "aaa" // not work ??
var x = (for _ in 0--n do scan-int:) // $array[int] & 0
var k? = if n < 2 then n * 2 +. 3 in
@ -285,6 +272,8 @@ exec main {
; print-anything:[int] n
; print-int: ::x 123
var & a & b & c = scan-three-t:
; \io..print: b
var & d & e & f = scan-three:

View file

@ -1,7 +1,7 @@
decl test-tuples : -> \unit
def test-tuples = {
var tuple1 = & ''a & 2 & "hello"
const & t1 & t2 & t3 = f: x
let & t1 & t2 & t3 = f: x
; tuple1`0 = ''b

View file

@ -13,3 +13,4 @@ def test-variants = {
| "hello" -> "nothing"
| 11 -> "nothing"
}