From 3106a6494979971d369fb727184ebaae6540dd48 Mon Sep 17 00:00:00 2001 From: ProgramSnail Date: Sat, 3 Jun 2023 19:01:03 +0300 Subject: [PATCH] changes for new grammar, fixes --- include/definitions.hpp | 2 +- include/interpreter_tree.hpp | 19 ++- include/parse_token_types.hpp | 1 + include/types.hpp | 42 ++--- include/utils.hpp | 2 + lang-parser | 2 +- src/build_visitor.cpp | 95 ++++++++---- src/find_symbols_visitor.cpp | 2 +- src/global_info.cpp | 25 +-- src/link_symbols_visitor.cpp | 8 + src/main.cpp | 8 +- src/print_visitor.cpp | 27 ++-- src/type_check_visitor.cpp | 37 ++--- src/typed_print_visitor.cpp | 23 +-- src/types.cpp | 26 +++- src/utils.cpp | 23 +++ src/visitor.cpp | 13 +- tests/arrays.lang | 16 +- tests/classes.lang | 96 ++++++------ tests/default_constructors.lang | 42 +---- tests/flow_control.lang | 20 +-- tests/functions.lang | 58 +++---- tests/import.lang | 6 +- tests/lambdas.lang | 14 +- tests/match.lang | 22 +-- tests/memory.lang | 12 +- tests/namespaces.lang | 20 +-- tests/partitions.lang | 8 +- tests/stdlib.lang | 159 +++++++++---------- tests/test_code.lang | 261 ++++++++++++++++---------------- tests/tuples.lang | 8 +- tests/type_casting.lang | 8 +- tests/typeclasses.lang | 32 ++-- tests/types.lang | 10 +- tests/variants.lang | 8 +- 35 files changed, 605 insertions(+), 550 deletions(-) diff --git a/include/definitions.hpp b/include/definitions.hpp index 6a09d8c..067c276 100644 --- a/include/definitions.hpp +++ b/include/definitions.hpp @@ -65,7 +65,7 @@ struct Constructor { struct FunctionDeclaration { std::vector parameters; - std::vector argument_types; + std::vector argument_types; interpreter::tokens::FunctionDeclaration* node = nullptr; }; diff --git a/include/interpreter_tree.hpp b/include/interpreter_tree.hpp index 4f1baf8..ff1f42c 100644 --- a/include/interpreter_tree.hpp +++ b/include/interpreter_tree.hpp @@ -212,13 +212,14 @@ struct FunctionType; struct TupleType; struct VariantType; struct TypeExpression; -struct TypeExpression; + +using WrappedTypeExpression = TypeExpression; using Constructor = std::string; // // ScopedAnyType <-> AnyType using AnyType = std::variant< - std::unique_ptr, + std::unique_ptr, std::unique_ptr, std::unique_ptr, std::unique_ptr>; @@ -272,6 +273,8 @@ struct Namespace { TypeIdentifier type; NamespaceSources scope; + bool is_type_namespace = false; // TODO: use + std::optional link_type_id_; std::optional link_typeclass_id_; }; @@ -292,7 +295,7 @@ struct AliasDefinitionStatement { utils::AliasModifier modifier; TypeIdentifier type; std::vector parameters; - std::unique_ptr value; + std::unique_ptr value; utils::IdType type_id_ = 0; }; @@ -516,7 +519,7 @@ struct FunctionCallExpression { BaseNode base; std::optional, - std::unique_ptr>> prefix; + std::unique_ptr>> prefix; NameOrOperatorIdentifier name; std::vector> parameters; std::vector arguments; @@ -621,21 +624,21 @@ struct AnnotatedName { struct FunctionType { BaseNode base; - std::vector types; + std::vector> types; }; struct TupleType { BaseNode base; - std::optional type; + std::optional type; std::vector, std::unique_ptr>> entities; }; struct VariantType { BaseNode base; - std::optional type; - std::vector>> constructors; + std::optional type; + std::vector, std::optional>>> constructors; }; struct ParametrizedType { diff --git a/include/parse_token_types.hpp b/include/parse_token_types.hpp index 540118d..ea07c1a 100644 --- a/include/parse_token_types.hpp +++ b/include/parse_token_types.hpp @@ -98,6 +98,7 @@ const std::string FunctionType = "function_type"; const std::string TupleType = "tuple_type"; const std::string VariantType = "variant_type"; const std::string TypeExpression = "type_expression"; +const std::string WrappedTypeExpression = "wrapped_type_expression"; const std::string Constructor = "constructor"; const std::string AnyType = "any_type"; const std::string ScopedAnyType = "scoped_any_type"; diff --git a/include/types.hpp b/include/types.hpp index 8628ac0..3c315c9 100644 --- a/include/types.hpp +++ b/include/types.hpp @@ -105,23 +105,23 @@ inline std::optional ToInternalType(const std::string& type) { } switch (type[0]) { - case 'F': - if (type == "Float") { return InternalType::Float; } + case 'f': + if (type == "float") { return InternalType::Float; } break; - case 'I': - if (type == "Int") { return InternalType::Int; } + case 'i': + if (type == "int") { return InternalType::Int; } break; - case 'S': - if (type == "String") { return InternalType::String; } + case 's': + if (type == "string") { return InternalType::String; } break; - case 'C': - if (type == "Char") { return InternalType::Char; } + case 'c': + if (type == "char") { return InternalType::Char; } break; - case 'B': - if (type == "Bool") { return InternalType::Bool; } + case 'b': + if (type == "bool") { return InternalType::Bool; } break; - case 'U': - if (type == "Unit") { return InternalType::Unit; } + case 'u': + if (type == "unit") { return InternalType::Unit; } break; default: break; @@ -135,22 +135,22 @@ inline std::string ToString(InternalType type) { switch (type) { case InternalType::Float: - result = "Float"; + result = "float"; break; case InternalType::Int: - result = "Int"; + result = "int"; break; case InternalType::String: - result = "String"; + result = "string"; break; case InternalType::Char: - result = "Char"; + result = "char"; break; case InternalType::Bool: - result = "Bool"; + result = "bool"; break; case InternalType::Unit: - result = "Unit"; + result = "unit"; break; } return result; @@ -187,7 +187,7 @@ class VariantType { public: VariantType() = default; VariantType(const std::optional& name, - const std::vector& constructors, + const std::vector>>& constructors, std::optional current_constructor) : name_(name), constructors_(constructors), current_constructor_(current_constructor) {} @@ -199,7 +199,7 @@ public: std::optional GetFieldType(const std::string& name, const std::unordered_set& type_namespaces) const; - const std::vector& GetConstructors() const { + const std::vector>>& GetConstructors() const { return constructors_; } @@ -210,7 +210,7 @@ public: std::string ToString() const; private: std::optional name_; - std::vector constructors_; + std::vector>> constructors_; std::optional current_constructor_; }; diff --git a/include/utils.hpp b/include/utils.hpp index 175f7ec..efca7ff 100644 --- a/include/utils.hpp +++ b/include/utils.hpp @@ -35,6 +35,8 @@ ValueType IsConstModifierToValueType(IsConstModifier modifier); ValueType ClassInternalsModifierToValueType(ClassInternalsModifier modifier); +std::optional ToEscapeSymbol(char symbol); + bool IsBuiltinFunction(const std::string& name); template diff --git a/lang-parser b/lang-parser index e469601..24bcf6e 160000 --- a/lang-parser +++ b/lang-parser @@ -1 +1 @@ -Subproject commit e4696019cf4ec08e4d2c707297887ed9bc359499 +Subproject commit 24bcf6e960957daf5662b764480f1d56637b1712 diff --git a/src/build_visitor.cpp b/src/build_visitor.cpp index 44190e1..180ec1b 100644 --- a/src/build_visitor.cpp +++ b/src/build_visitor.cpp @@ -62,7 +62,9 @@ void BuildVisitor::Visit(Namespace* node) { node->modifier = utils::ClassInternalsModifier::Static; } - node->type = parse_node.ChildByFieldName("type").GetValue(); + current_node_ = parse_node.ChildByFieldName("type"); + node->type = current_node_.GetValue(); + node->is_type_namespace = (current_node_.PreviousSibling().GetValue() == "\\"); current_node_ = parse_node.ChildByFieldName("scope"); Visit(&node->scope); @@ -130,7 +132,7 @@ void BuildVisitor::Visit(AliasDefinitionStatement* node) { } current_node_ = parse_node.ChildByFieldName("value"); - node->value = std::make_unique(); + node->value = std::make_unique(); Visit(node->value.get()); current_node_ = parse_node; @@ -961,9 +963,9 @@ void BuildVisitor::Visit(FunctionCallExpression* node) { node->prefix = std::make_unique(); Visit(*std::get>(node->prefix.value())); ++excluded_child_count; - } else if (current_node_type == parser::tokens::TypeExpression) { - node->prefix = std::make_unique(); - Visit(std::get>(node->prefix.value()).get()); + } else if (current_node_type == parser::tokens::WrappedTypeExpression) { + node->prefix = std::make_unique(); + Visit(std::get>(node->prefix.value()).get()); ++excluded_child_count; } else { // no prefix @@ -1282,7 +1284,8 @@ void BuildVisitor::Visit(FunctionType* node) { for (size_t i = 0; i < types_count; ++i) { current_node_ = parse_node.NthNamedChild(i); - Visit(node->types[i]); + node->types[i] = std::make_unique(); + Visit(node->types[i].get()); } current_node_ = parse_node; @@ -1340,19 +1343,28 @@ void BuildVisitor::Visit(VariantType* node) { } - node->constructors.resize(child_count - excluded_child_count); - for (size_t i = 0; i < node->constructors.size(); ++i) { - current_node_ = parse_node.NthNamedChild(i + excluded_child_count); + if (child_count > excluded_child_count) { + node->constructors.reserve(child_count - excluded_child_count); + for (size_t i = 0; i < child_count - excluded_child_count; ++i) { + current_node_ = parse_node.NthNamedChild(i + excluded_child_count); - std::string current_node_type = current_node_.GetType(); + std::string current_node_type = current_node_.GetType(); - if (current_node_type == parser::tokens::Constructor) { - node->constructors[i] = current_node_.GetValue(); - } else if (current_node_type == parser::tokens::TupleType) { - node->constructors[i] = std::make_unique(); - Visit(std::get>(node->constructors[i]).get()); - } else { - // error + if (current_node_type == parser::tokens::Constructor) { + std::string constructor_name = current_node_.GetValue(); + constructor_name = constructor_name.substr(1, constructor_name.size() - 1); + node->constructors.push_back({constructor_name, std::nullopt}); + } else if (current_node_type == parser::tokens::TupleType) { + if (!node->constructors.empty() && !node->constructors.back().second.has_value()) { + node->constructors.back().second = std::make_unique(); + Visit(node->constructors.back().second.value().get()); + } else { + node->constructors.push_back({std::nullopt, std::make_unique()}); + Visit(node->constructors.back().second.value().get()); + } + } else { + // error + } } } @@ -1389,11 +1401,11 @@ void BuildVisitor::Visit(TypeExpression* node) { node->is_optional = true; } else { - if (suffix_node1.GetValue() == "_" && suffix_node2.GetValue() == "!") { + if (suffix_node1.GetValue() == "`" && suffix_node2.GetValue() == "?") { node->array_size = 0; node->is_optional = true; - } else if (suffix_node1.GetValue() == "_") { + } else if (suffix_node1.GetValue() == "`") { current_node_ = suffix_node2; NumberLiteral literal; @@ -1407,9 +1419,9 @@ void BuildVisitor::Visit(TypeExpression* node) { } } } else { - if (suffix_node1.GetValue() == "_") { + if (suffix_node1.GetValue() == "`") { node->array_size = 0; - } else if (suffix_node1.GetValue() == "!") { + } else if (suffix_node1.GetValue() == "?") { node->is_optional = true; } else { error_handling::HandleInternalError("Undefined suffix (1 element)", @@ -1438,9 +1450,9 @@ void BuildVisitor::Visit(AnyType& node) { std::string current_node_type = current_node_.GetType(); - if (current_node_type == parser::tokens::TypeExpression) { - node = std::make_unique(); - Visit(std::get>(node).get()); + if (current_node_type == parser::tokens::WrappedTypeExpression) { + node = std::make_unique(); + Visit(std::get>(node).get()); } else if (current_node_type == parser::tokens::TupleType) { node = std::make_unique(); Visit(std::get>(node).get()); @@ -1550,18 +1562,47 @@ void BuildVisitor::Visit(NumberLiteral* node) { node->value = std::stoll(current_node_.GetValue()); } -void BuildVisitor::Visit(StringLiteral* node) { // TODO: special symbols, etc. +void BuildVisitor::Visit(StringLiteral* node) { // TODO: other special symbols, etc. SetPosition(node->base, current_node_); std::string literal = current_node_.GetValue(); - node->value = literal.substr(1, literal.size() - 2); + literal = literal.substr(1, literal.size() - 2); + node->value.reserve(literal.size()); + + bool is_escape_symbol = false; + for (size_t i = 0; i < literal.size(); ++i) { + if (literal[i] == '\\' && !is_escape_symbol) { + is_escape_symbol = true; + } else { + if (is_escape_symbol) { + auto maybe_escape_symbol = utils::ToEscapeSymbol(literal[i]); + if (maybe_escape_symbol.has_value()) { + node->value += maybe_escape_symbol.value(); + } else { + node->value += literal[i]; + } + } else { + node->value += literal[i]; + } + } + } } void BuildVisitor::Visit(CharLiteral* node) { SetPosition(node->base, current_node_); std::string literal = current_node_.GetValue(); - node->value = literal.substr(1, literal.size() - 2).back(); // TODO: special symbols, etc. + literal = literal.substr(2, literal.size() - 2); // TODO: other special symbols, etc. + if (literal[0] == '\\') { + auto maybe_escape_symbol = utils::ToEscapeSymbol(literal.back()); + if (maybe_escape_symbol.has_value()) { + node->value = maybe_escape_symbol.value(); + } else { + node->value = literal.back(); + } + } else { + node->value = literal.back(); + } } void BuildVisitor::Visit(UnitLiteral* node) { diff --git a/src/find_symbols_visitor.cpp b/src/find_symbols_visitor.cpp index ba5417c..8529b81 100644 --- a/src/find_symbols_visitor.cpp +++ b/src/find_symbols_visitor.cpp @@ -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]; + info.argument_types[i] = node->type->types[i].get(); } info.node = node; diff --git a/src/global_info.cpp b/src/global_info.cpp index ec1481e..52a5323 100644 --- a/src/global_info.cpp +++ b/src/global_info.cpp @@ -179,35 +179,18 @@ utils::IdType GlobalInfo::NamespaceVisitor::AddType(const std::string& type, if (std::holds_alternative>(any_type_info.node->value)) { interpreter::tokens::VariantType& variant_type_info = *std::get>(any_type_info.node->value); for (size_t i = 0; i < variant_type_info.constructors.size(); ++i) { - std::string constructor_name; definition::Constructor constructor_info; constructor_info.type_id = id; constructor_info.order = i; - if (std::holds_alternative(variant_type_info.constructors[i])) { - constructor_name = std::get(variant_type_info.constructors[i]); - } else if (std::holds_alternative< - std::unique_ptr>(variant_type_info.constructors[i])) { - constructor_info.constructor_tuple_node = - std::get>(variant_type_info.constructors[i]).get(); - - auto maybe_constructor_name = constructor_info.constructor_tuple_node.value()->type; - - if (maybe_constructor_name.has_value()) { - constructor_name = maybe_constructor_name.value(); - } else { - constructor_name = type; - } + if (variant_type_info.constructors[i].first.has_value()) { + constructor_info.name = variant_type_info.constructors[i].first.value(); } else { - error_handling::HandleInternalError("Unexprected VariantType constructor node type", - "GlobalInfo.NamespaceVisitor.AddType", - &base_node); + constructor_info.name = any_type_info.type.type; } - constructor_info.name = constructor_name; - - AddConstructor(constructor_name, std::move(constructor_info), base_node); + AddConstructor(constructor_info.name, std::move(constructor_info), base_node); } } else if (std::holds_alternative>(any_type_info.node->value)) { definition::Constructor constructor_info; diff --git a/src/link_symbols_visitor.cpp b/src/link_symbols_visitor.cpp index 46fe1e6..6e7e720 100644 --- a/src/link_symbols_visitor.cpp +++ b/src/link_symbols_visitor.cpp @@ -20,6 +20,14 @@ void LinkSymbolsVisitor::Visit(Namespace* node) { maybe_typeclass = namespace_visitor_.FindTypeclassId(node->type); } + if (!node->is_type_namespace && (maybe_type.has_value() || maybe_typeclass.has_value())) { + error_handling::HandleNamesError("Not type / typeclass namespace has associated type / typeclass", node->base); + } + + if (node->is_type_namespace && !maybe_type.has_value() && !maybe_typeclass.has_value()) { + error_handling::HandleNamesError("Type / typeclass namespace has no associated type / typeclass", node->base); + } + if (maybe_type.has_value() && maybe_typeclass.has_value()) { error_handling::HandleNamesError("Ambigious namespace name (typeclass or type)", node->base); } diff --git a/src/main.cpp b/src/main.cpp index 0ba8571..63d259b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -48,7 +48,7 @@ int main(int argc, char** argv) { // TODO, only test version info::ContextManager context_manager; interpreter::BuildVisitor build_visitor(parse_tree); - // interpreter::PrintVisitor print_visitor(std::cout); + interpreter::PrintVisitor print_visitor(std::cout); interpreter::FindSymbolsVisitor find_symbols_visitor(global_info); interpreter::LinkSymbolsVisitor link_symbols_visitor(global_info); interpreter::TypeCheckVisitor type_check_visitor(global_info, type_context_manager); @@ -56,8 +56,8 @@ int main(int argc, char** argv) { // TODO, only test version build_visitor.VisitSourceFile(source_file.get()); - // std::cout << "\n---------------------------------- Untyped -------------------------------------\n\n"; - // print_visitor.VisitSourceFile(source_file.get()); + std::cout << "\n---------------------------------- Untyped -------------------------------------\n\n"; + print_visitor.VisitSourceFile(source_file.get()); try { find_symbols_visitor.VisitSourceFile(source_file.get()); @@ -69,7 +69,7 @@ int main(int argc, char** argv) { // TODO, only test version try { type_check_visitor.VisitSourceFile(source_file.get()); - } catch (bool) { error_handling::HandleInternalError("type_check_visitor exception", "main", std::nullopt); } + } catch (...) { error_handling::HandleInternalError("type_check_visitor exception", "main", std::nullopt); } std::optional maybe_main_partition_id = global_info.FindPartition({"main"}); diff --git a/src/print_visitor.cpp b/src/print_visitor.cpp index b4df798..ddf8fb0 100644 --- a/src/print_visitor.cpp +++ b/src/print_visitor.cpp @@ -271,7 +271,7 @@ void PrintVisitor::Visit(MatchCase* node) { out_ << "[MatchCase | "; Visitor::Visit(node->value); if (node->condition.has_value()) { - out_ << " ? "; + out_ << " ?? "; Visitor::Visit(node->condition.value()); } if (node->statement.has_value()) { @@ -428,7 +428,7 @@ void PrintVisitor::Visit(FunctionCallExpression* node) { } else { // error } - out_ << ")."; + out_ << ").."; } Visit(&node->name); @@ -554,7 +554,7 @@ void PrintVisitor::Visit(PartitionName* node) { for (size_t i = 0; i < node->path.size(); ++i) { Visit(&node->path[i]); if (i + 1 < node->path.size()) { - out_ << "::"; + out_ << '.'; } } out_ << ')'; @@ -565,7 +565,7 @@ void PrintVisitor::Visit(NameExpression* node) { for (size_t i = 0; i < node->names.size(); ++i) { Visit(&node->names[i]); if (i + 1 < node->names.size()) { - out_ << "::"; + out_ << '.'; } } out_ << ')'; @@ -612,7 +612,7 @@ void PrintVisitor::Visit(FunctionType* node) { out_ << " -> "; } is_first = false; - Visitor::Visit(type); + Visit(type.get()); } out_ << ')'; } @@ -641,13 +641,14 @@ void PrintVisitor::Visit(VariantType* node) { } out_ << "] ("; for (auto& constructor : node->constructors) { - out_ << "| "; - if (std::holds_alternative(constructor)) { - Visit(&std::get(constructor)); - } else if (std::holds_alternative>(constructor)) { - Visit(std::get>(constructor).get()); - } else { - // error + out_ << "|"; + if (constructor.first.has_value()) { + out_ << " "; + Visit(&constructor.first.value()); + } + if (constructor.second.has_value()) { + out_ << " "; + Visit(constructor.second.value().get()); } } out_ << ')'; @@ -667,7 +668,7 @@ void PrintVisitor::Visit(TypeExpression* node) { out_ << "] ("; for (auto& type : node->path) { Visit(&type); - out_ << "::"; + out_ << '.'; } Visit(&node->type); out_ << ')'; diff --git a/src/type_check_visitor.cpp b/src/type_check_visitor.cpp index 8e5a556..5665a91 100644 --- a/src/type_check_visitor.cpp +++ b/src/type_check_visitor.cpp @@ -224,14 +224,14 @@ void TypeCheckVisitor::Visit(FunctionDefinitionStatement* node) { } for (size_t i = 0; i < node->definition->arguments.size(); ++i) { - Visitor::Visit(declaration->type->types[i]); + Visit(declaration->type->types[i].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); } } - Visitor::Visit(declaration->type->types.back()); + Visit(declaration->type->types.back().get()); utils::IdType returned_type = current_type_; returned_type_ = std::nullopt; @@ -812,7 +812,7 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) { } for (size_t i = index_shift; i < node->arguments.size(); ++i) { - Visitor::Visit(function_declaration->type->types[i - index_shift]); + Visit(function_declaration->type->types[i - index_shift].get()); utils::IdType argument_type = TypeInContext(current_type_, context); Visitor::Visit(node->arguments[i]); @@ -847,7 +847,7 @@ void TypeCheckVisitor::Visit(FunctionCallExpression* node) { } } - Visitor::Visit(function_declaration->type->types.back()); + Visit(function_declaration->type->types.back().get()); current_type_ = TypeInContext(current_type_, context); context_manager_.ExitContext(); @@ -871,14 +871,14 @@ void TypeCheckVisitor::Visit(TupleExpression* node) { } void TypeCheckVisitor::Visit(VariantExpression* node) { - std::vector constructors; + std::vector>> constructors; for (auto& expression : node->expressions) { Visitor::Visit(expression); // TODO: deal with expression tuple types, etc, ?? std::vector, utils::IdType>> constructor_fields {{std::nullopt, current_type_}}; - constructors.push_back(info::type::TupleType(std::nullopt, constructor_fields, context_manager_.GetValueManager())); + constructors.push_back({"", info::type::TupleType(std::nullopt, constructor_fields, context_manager_.GetValueManager())}); } @@ -1170,14 +1170,14 @@ void TypeCheckVisitor::Visit(VariantName* node) { } for (size_t i = 0; i < node->names.size(); ++i) { - if (type_value->GetConstructors()[i].GetFields().empty()) { + if (!type_value->GetConstructors()[i].second.has_value()) { current_type_ = context_manager_.AddValue( info::type::OptionalType( internal_to_abstract_type_.at(info::type::InternalType::Unit), context_manager_.GetValueManager()), utils::IsConstModifierToValueType(is_const_definition_.value())); // TODO ?? } else { - info::type::TupleType constructor_type_value = type_value->GetConstructors()[i]; + info::type::TupleType constructor_type_value = type_value->GetConstructors()[i].second.value(); utils::IdType constructor_type = context_manager_.AddValue(std::move(constructor_type_value), @@ -1227,7 +1227,7 @@ void TypeCheckVisitor::Visit(FunctionType* node) { std::vector argument_types(node->types.size()); for (auto& argument_type : node->types) { - Visitor::Visit(argument_type); + Visit(argument_type.get()); argument_types.push_back(current_type_); } @@ -1262,24 +1262,25 @@ void TypeCheckVisitor::Visit(TupleType* node) { } void TypeCheckVisitor::Visit(VariantType* node) { - std::vector constructors; + std::vector>> constructors; constructors.reserve(node->constructors.size()); for (auto& constructor : node->constructors) { - if (std::holds_alternative(constructor)) { - std::vector, utils::IdType>> constructor_fields; - constructors.push_back(info::type::TupleType(std::get(constructor), constructor_fields, context_manager_.GetValueManager())); - } else if (std::holds_alternative>(constructor)) { - Visit(std::get>(constructor).get()); + if (!constructor.first.has_value() && !node->type.has_value()) { + error_handling::HandleTypecheckError("Constructor type not recognized", node->base); + } // TODO: decide + + constructors.push_back({constructor.first.has_value() ? constructor.first.value() : node->type.value(), std::nullopt}); // TODO: real constructor name, instead of variant name (names in namespaces, etc) + + if (constructor.second.has_value()) { + Visit(constructor.second.value().get()); std::optional maybe_constructor = context_manager_.GetValue(current_type_); if (!maybe_constructor.has_value()) { error_handling::HandleInternalError("Entity of VariantType is not TupleType", "TypeCheckVisitor.VariantType", &node->base); } - constructors.push_back(*maybe_constructor.value()); - } else { - // error + constructors.back().second = *maybe_constructor.value(); } } diff --git a/src/typed_print_visitor.cpp b/src/typed_print_visitor.cpp index 29d7c84..ef3e27b 100644 --- a/src/typed_print_visitor.cpp +++ b/src/typed_print_visitor.cpp @@ -599,7 +599,7 @@ void TypedPrintVisitor::Visit(FunctionCallExpression* node) { } else { // error } - out_ << ")."; + out_ << ").."; } Visit(&node->name); @@ -772,7 +772,7 @@ void TypedPrintVisitor::Visit(PartitionName* node) { for (size_t i = 0; i < node->path.size(); ++i) { Visit(&node->path[i]); if (i + 1 < node->path.size()) { - out_ << "::"; + out_ << '.'; } } out_ << ')'; @@ -789,7 +789,7 @@ void TypedPrintVisitor::Visit(NameExpression* node) { for (size_t i = 0; i < node->names.size(); ++i) { Visit(&node->names[i]); if (i + 1 < node->names.size()) { - out_ << "::"; + out_ << '.'; } } out_ << ')'; @@ -860,7 +860,7 @@ void TypedPrintVisitor::Visit(FunctionType* node) { out_ << " -> "; } is_first = false; - Visitor::Visit(type); + Visit(type.get()); } out_ << ')'; } @@ -902,12 +902,13 @@ void TypedPrintVisitor::Visit(VariantType* node) { out_ << "] ("; for (auto& constructor : node->constructors) { out_ << "| "; - if (std::holds_alternative(constructor)) { - Visit(&std::get(constructor)); - } else if (std::holds_alternative>(constructor)) { - Visit(std::get>(constructor).get()); - } else { - // error + if (constructor.first.has_value()) { + out_ << " "; + Visit(&constructor.first.value()); + } + if (constructor.second.has_value()) { + out_ << " "; + Visit(constructor.second.value().get()); } } out_ << ')'; @@ -932,7 +933,7 @@ void TypedPrintVisitor::Visit(TypeExpression* node) { out_ << "] ("; for (auto& type : node->path) { Visit(&type); - out_ << "::"; + out_ << '.'; } Visit(&node->type); out_ << ')'; diff --git a/src/types.cpp b/src/types.cpp index 0410f3c..061bfac 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -144,7 +144,9 @@ std::string TupleType::ToString() const { std::optional VariantType::InContext(const std::unordered_map& context) { for (size_t i = 0; i < constructors_.size(); ++i) { - constructors_[i].InContext(context); + if (constructors_[i].second.has_value()) { + constructors_[i].second.value().InContext(context); + } } return std::nullopt; @@ -156,9 +158,20 @@ bool VariantType::Same(const VariantType& type) const { } for (size_t i = 0; i < constructors_.size(); ++i) { - if (!constructors_[i].Same(constructors_[i])) { + + if (constructors_[i].first != type.constructors_[i].first) { // TODO: decide return false; } + + if (constructors_[i].second.has_value() != type.constructors_[i].second.has_value()) { + return false; + } + + if (constructors_[i].second.has_value()) { + if (!constructors_[i].second.value().Same(type.constructors_[i].second.value())) { + return false; + } + } } return true; @@ -184,8 +197,8 @@ bool VariantType::operator>(const VariantType& type) const { std::optional VariantType::GetFieldType(const std::string& name, const std::unordered_set& type_namespaces) const { - if (current_constructor_.has_value()) { - return constructors_.at(current_constructor_.value()).GetFieldType(name, type_namespaces); + if (current_constructor_.has_value() && constructors_.at(current_constructor_.value()).second.has_value()) { + return constructors_[current_constructor_.value()].second.value().GetFieldType(name, type_namespaces); } return std::nullopt; } @@ -197,7 +210,10 @@ std::string VariantType::ToString() const { for (auto& constructor : constructors_) { result += "& "; - result += constructor.ToString(); + result += constructor.first; + if (constructor.second.has_value()) { + result += " " + constructor.second.value().ToString(); + } } result += ")"; diff --git a/src/utils.cpp b/src/utils.cpp index f21266e..5c9fad4 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -38,6 +38,29 @@ ValueType ClassInternalsModifierToValueType(ClassInternalsModifier modifier) { exit(1); // unreachable } +std::optional ToEscapeSymbol(char symbol) { + switch (symbol) { + case 'a': + return '\a'; + case 'b': + return '\b'; + case 'e': + return '\e'; + case 'f': + return '\f'; + case 'n': + return '\n'; + case 'r': + return '\r'; + case 't': + return '\t'; + case 'v': + return '\v'; + default: + return std::nullopt; + } +} + bool IsBuiltinFunction(const std::string& name) { // optimize ?? std::unordered_set builtin_functions; diff --git a/src/visitor.cpp b/src/visitor.cpp index ce268ef..fb45600 100644 --- a/src/visitor.cpp +++ b/src/visitor.cpp @@ -583,7 +583,7 @@ void Visitor::Visit(AnnotatedName* node) { void Visitor::Visit(FunctionType* node) { for (auto& type : node->types) { - Visit(type); + Visit(type.get()); } } @@ -604,12 +604,11 @@ void Visitor::Visit(VariantType* node) { Visit(&node->type.value()); } for (auto& constructor : node->constructors) { - if (std::holds_alternative(constructor)) { - Visit(&std::get(constructor)); - } else if (std::holds_alternative>(constructor)) { - Visit(std::get>(constructor).get()); - } else { - // error + if (constructor.first.has_value()) { + Visit(&constructor.first.value()); + } + if (constructor.second.has_value()) { + Visit(constructor.second.value().get()); } } } diff --git a/tests/arrays.lang b/tests/arrays.lang index 734d713..12003af 100644 --- a/tests/arrays.lang +++ b/tests/arrays.lang @@ -1,14 +1,14 @@ -decl test_arrays : -> Unit -def test_arrays = { +decl test-arrays : -> \unit +def test-arrays = { var arr1 = ,1 ,2 ,3 - const arr2 = Int._array: 32 - var arr3 = String._array: 11 - const arr4 = 'a'--'z' + const arr2 = \int..array: 32 + var arr3 = \string..array: 11 + const arr4 = ''a--''z const n = 100 - var arr5 <- Int._new_array: 10 + var arr5 <- \int..new-array: 10 - var arr6 <- String._new_array: 10 - var arr6_reference = ^arr6 + var arr6 <- \string..new-array: 10 + var arr6-reference = ^arr6 const elem1 = arr1`0 var elem2 = arr1`2 diff --git a/tests/classes.lang b/tests/classes.lang index f3487b1..ab991e5 100644 --- a/tests/classes.lang +++ b/tests/classes.lang @@ -1,59 +1,59 @@ -struct Fruit = - | Apple - | Orange - | Banana +struct \fruit = + | $apple + | $orange + | $banana -struct Optional 'A = - | Some & 'A - | None +struct \optional 'a = + | $some & 'a + | $none -struct (Result : #Move) 'A 'B = - | & 'A - | Error & 'B +struct \result[#move] 'a 'b = + | & 'a + | $error & 'b -struct (Complex : #Value) = - & Float - & Float +struct \complex[#value] = + & \float + & \float -struct Task = - & name : String - & duration : Float! +struct \task = + & name : \string + & duration : \float? -class Employee = - & name : String +class \employee = + & name : \string & role : - ( | Director - & importance : Float - & share : Float - | Manager + ( | $director + & importance : \float + & share : \float + | $manager & productivity : - ( Productivity - | .Low - | .Average - | .High - & duration : Float - & sleep_on_work : - (SleepOnWork - | ..Yes - | ..No + ( \productivity + | $.low + | $.average + | $.high + & duration : \float + & sleep-on-work : + ( \sleep-on-work + | $..yes + | $..no )) - & salary : Int - | Programmer - & skills : Float - & current_task : (Optional Task) - & salary : Int) + & salary : \int + | $programmer + & skills : \float + & current-task : \optional[task] + & salary : \int) -class Bag = +class \bag = & - ( | Apple - | Orange - | Banana) - & bag_type : - ( | Small - | Medium - & weight_kg : Int - & weight_g : Int - & weight_g : Int - | Big) - & other_things : (Array Something) + ( | $apple + | $orange + | $banana) + & bag-type : + ( | $small + | $medium + & weight-kg : \int + & weight-g : \int + & weight-mg : \int + | $big) + & other-things : \array[something] diff --git a/tests/default_constructors.lang b/tests/default_constructors.lang index bfed145..ef6f5b5 100644 --- a/tests/default_constructors.lang +++ b/tests/default_constructors.lang @@ -1,44 +1,18 @@ -namespace Employee { - decl gen_employee : Unit -> Employee - def gen_employee = { - var x = $@Complex & 11.3 & 15.87 // construct on heap +namespace \employee { + decl gen-employee : \unit -> \employee + def gen-employee = { + var x = $@complex & 11.3 & 15.87 // construct on heap return - $Employee // construct on stack + $employee // construct on stack & name = "John" & role = - ($Manager + ($manager & "John" & productivity = - ($Productivity::High + ($productivity.high & duration = 10.3 - & sleep_on_work = ($Productivity::SleepOnWork::No)) + & sleep-on-work = ($productivity.sleep-on-work.no)) & salary = 123) } } - -/* -class Employee = - & name : String - & role : - ( | Director - & importance : Float - & share : Float - | Manager - & productivity : - ( Productivity - | .Low - | .Average - | .High - & duration : Float - & sleep_on_work : - (SleepOnWork - | ..Yes - | ..No - )) - & salary : Int - | Programmer - & skills : Float - & current_task : Optional Task - & salary : Int) -*/ diff --git a/tests/flow_control.lang b/tests/flow_control.lang index aaea061..76e0993 100644 --- a/tests/flow_control.lang +++ b/tests/flow_control.lang @@ -1,28 +1,28 @@ -decl flow_control_test : -> Unit -def flow_control_test = { - if (a < b ||. a == b) && (b < c) then IO.print: x +decl flow-control-test : -> \unit +def flow-control-test = { + if (a < b ||. a == b) && (b < c) then \io..print: x elif x < 0 then { ; x += 1 - ; IO.print: y + ; \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: + ; array..pop: } while x < 10 do x +=. x + 3 for i in 0--y do { - ; IO.print: i + ; \io..print: i } for & i & j in (& 0--y & 0--k) do { // ?? - ; IO.print: 1 - ; IO.print: 2 - ; IO.print: 128 + ; \io..print: 1 + ; \io..print: 2 + ; \io..print: 128 } loop { diff --git a/tests/functions.lang b/tests/functions.lang index 080f30e..e530d4d 100644 --- a/tests/functions.lang +++ b/tests/functions.lang @@ -1,62 +1,62 @@ -decl sum ('A : #Add) : 'A -> 'A -> 'A +decl sum 'a[#add] : 'a -> 'a -> 'a def sum : a b = a + b -decl fib : Int -> Int +decl fib : \int -> \int def fib : n = match n with | 0 | 1 -> 1 - | n ? n > 1 -> fib: (n - 1) + fib: n + | n ?? n > 1 -> fib: (n - 1) + fib: n | _ -> error: "n must be positive" -decl fact : Int -> Int +decl fact : \int -> \int def fact : n = match n with | 0 -> 1 - | n ? n > 0 -> n * fact: (n - 1) + | n ?? n > 0 -> n * fact: (n - 1) | _ -> error: "n must be positive" -decl find_prefix_hashes ('H : (#AccHash Char)) : String -> (Array 'H) -def find_prefix_hashes : str = { - var hashes = (Array 'H).new: (str.size: + 1) +decl find-prefix-hashes 'h[#acc-hash[char]] : \string -> \array['h] +def find-prefix-hashes : str = { + var hashes = \array['h]..new: (str..size: + 1) - ; hashes`0 = 'H.of: str`0 - for i in 1--hashes.size: do { + ; hashes`0 = 'h..of: str`0 + for i in 1--hashes..size: do { ; hashes`i = hashes`(i - 1) - ; hashes`i.append: str`i + ; hashes`i..append: str`i } return hashes } -alias Hash = (AccHash Char) +alias \hash = \acc-hash[char] -decl find_substring : String -> String -> (Array Index) -def find_substring : str substr = { - var result = (Array Index).empty: +decl find-substring : \string -> \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 + const str-hashes = find-prefix-hashes:[hash] str + const 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 + for i in 0--(str-hashes..size: - substr..size:) do { + const part-hash = hash..diff: str-hashes`(i + substr..size:) str-hashes`i - if part_hash == substr_hash then { - ; result.push: i + if part-hash == substr-hash then { + ; result..push: i } } return result } -decl is_empty : -> Bool -def is_empty = 0 +decl is-empty : -> \bool +def is-empty = 0 -decl do_something : -> Unit -def do_something = - IO.print: "Hello World!" +decl do-something : -> \unit +def do-something = + \io..print: "Hello World!" -decl mul : Int -> Int -> Int +decl mul : \int -> \int -> \int def mul : x y = x * y -decl mul_10 : Int -> Int -def mul_10 = mul: 10 +decl mul-10 : \int -> \int +def mul-10 = mul: 10 diff --git a/tests/import.lang b/tests/import.lang index d3c2533..c7894ec 100644 --- a/tests/import.lang +++ b/tests/import.lang @@ -1,15 +1,15 @@ import "module" import "module" : func import "module" : - Type1 + \type1 func1 func2 func3 func4 -use ModuleNamespace = import "module" +use module-namespace = import "module" -use PartOfModuleNamespace = +use part-of-module-namespace = import "module" : func1 func2 diff --git a/tests/lambdas.lang b/tests/lambdas.lang index 3a9998f..f5f01d0 100644 --- a/tests/lambdas.lang +++ b/tests/lambdas.lang @@ -1,11 +1,11 @@ -decl test_lambdas : -> Unit -def test_lambdas = { - const lambda1 = \x -> x * x - const lambda2 = \x -> x.hash: - const lambda3 = \x y -> x + y +decl test-lambdas : -> \unit +def test-lambdas = { + const lambda1 = \\x -> x * x + const lambda2 = \\x -> x..hash: + const lambda3 = \\x y -> x + y - const lambda4 = \x -> { - ; IO.print: x + const lambda4 = \\x -> { + ; \io..print: x const y = x + x return y } diff --git a/tests/match.lang b/tests/match.lang index 0541c72..d5ed074 100644 --- a/tests/match.lang +++ b/tests/match.lang @@ -1,18 +1,18 @@ -decl fruit_cost : Fruit -> Int -def fruit_cost : fruit = { - var fruit_copy = fruit - return (match <- fruit_copy with // consuming match - | $Banana -> 11 - | $Apple | $Orange -> 7) +decl fruit-cost : \fruit -> \int +def fruit-cost : fruit = { + var fruit-copy = fruit + return (match <- fruit-copy with // consuming match + | $banana -> 11 + | $apple | $orange -> 7) } -decl amount_to_string : Int -> Bool -> String -def amount_to_string : x is_zero_separated = { +decl amount-to-string : \int -> \bool -> \string +def amount-to-string : x is-zero-separated = { const ans = match x with - | 0 ? is_zero_separated -> "Zero" + | 0 ?? is-zero-separated -> "Zero" | 0 | 1 | 2 | 3 | 4 -> "Few" - | x ? (5--9).contains: x -> "Several" - | x ? (10--19).contains: x -> "Pack" + | x ?? (5--9)..contains: x -> "Several" + | x ?? (10--19)..contains: x -> "Pack" | _ -> "Lots" return ans } diff --git a/tests/memory.lang b/tests/memory.lang index 0092566..c6a07f2 100644 --- a/tests/memory.lang +++ b/tests/memory.lang @@ -1,8 +1,8 @@ -struct StructWithRef = - & @Int_0 +struct \struct-with-ref = + & @\int`0 -decl test_memory : -> Unit -def test_memory = { - const unique_ref1 <- Int._new: 5 - var unique_ref2 <- Array.of: 1 2 3 +decl test-memory : -> \unit +def test-memory = { + const unique-ref1 <- \int..new: 5 + var unique-ref2 <- \array..of: 1 2 3 } diff --git a/tests/namespaces.lang b/tests/namespaces.lang index 57f3580..1232fce 100644 --- a/tests/namespaces.lang +++ b/tests/namespaces.lang @@ -1,19 +1,19 @@ -namespace Namespace { - decl something : -> Unit +namespace some-namespace { + decl something : -> \unit } -namespace Array { - decl something : -> Unit +namespace \array { + decl something : -> \unit } -namespace Array { - decl something : -> Unit +namespace \array { + decl something : -> \unit } -namespace var Array { - decl something : -> Unit +namespace var \array { + decl something : -> \unit } -namespace const Array { - decl something : -> Unit +namespace const \array { + decl something : -> \unit } diff --git a/tests/partitions.lang b/tests/partitions.lang index 9ec0b99..5c2b1a4 100644 --- a/tests/partitions.lang +++ b/tests/partitions.lang @@ -1,10 +1,10 @@ -test All::Dev::Syntax::testing { +test all.dev.syntax.testing { const a = 31 - ; do_something: a + ; do-something: a } -exec App::exe { +exec app.exe { const b = true const c = false - ; do_something_different: b b c + ; do-something-different: b b c } diff --git a/tests/stdlib.lang b/tests/stdlib.lang index 2950e11..46c451a 100644 --- a/tests/stdlib.lang +++ b/tests/stdlib.lang @@ -1,19 +1,19 @@ -basic (Float : #Ord #Div #Str) -basic (Int : #Ord #IDiv #Str) -basic (String : #Ord #Str #CharContainer #Copy) -basic (Char : #Ord #Str #Copy) -basic (Bool : #Ord #Str #Copy) -basic (Unit : #Str #Copy) +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 +decl not : \bool -> \bool def not : x = (match x with | true -> false | false -> true) -decl ( && ) : Bool -> Bool -> Bool +decl ( && ) : \bool -> \bool -> \bool def ( && ) : x y = match x with | true -> ( @@ -23,7 +23,7 @@ def ( && ) : x y = ) | false -> false -decl ( || ) : Bool -> Bool -> Bool +decl ( || ) : \bool -> \bool -> \bool def ( || ) : x y = match x with | true -> true @@ -35,28 +35,28 @@ def ( || ) : x y = // -typeclass CharContainer = - & var size : -> Int - & var at : Int -> Char +typeclass \char-container = + & var size : -> \int + & var at : \int -> \char // -typeclass Move = // TODO - & var ( <- ) : Move -> Unit +typeclass \move = // TODO + & var ( <- ) : \move -> \unit -typeclass Copy = - & var ( = ) : Copy -> Unit +typeclass \copy = + & var ( = ) : \copy -> \unit // -typeclass (Sum : #Copy) = - & var ( += ) : Sum -> Unit - & var ( -= ) : Sum -> Unit - & var ( + ) : Sum -> Sum - & var ( - ) : Sum -> Sum - & zero : -> Sum +typeclass \sum[#copy] = + & var ( += ) : \sum -> \unit + & var ( -= ) : \sum -> \unit + & var ( + ) : \sum -> \sum + & var ( - ) : \sum -> \sum + & zero : -> \sum -namespace var Sum { +namespace var \sum { def ( + ) : x = { var ans = self ; ans += x @@ -70,11 +70,11 @@ namespace var Sum { } } -typeclass (Mult : #Sum) = - & var ( *= ) : Mult -> Unit - & var ( * ) : Mult -> Mult +typeclass \mult[#sum] = + & var ( *= ) : \mult -> \unit + & var ( * ) : \mult -> \mult -namespace var Mult { +namespace var \mult { def ( * ) : x = { var ans = self ; ans *= x @@ -82,19 +82,19 @@ namespace var Mult { } } -typeclass (IDiv : #Mult) = - & var div : IDiv -> IDiv - & var mod : IDiv -> IDiv +typeclass \idiv[#mult] = + & var div : \idiv -> \idiv + & var mod : \idiv -> \idiv -namespace var IDiv { - def mod : x = self -. x * self.div: x +namespace var \idiv { + def mod : x = self -. x * self..div: x } -typeclass (Div : #Mult) = - & var ( /= ) : Div -> Unit - & var ( / ) : Div -> Div +typeclass \div[#mult] = + & var ( /= ) : \div -> \unit + & var ( / ) : \div -> \div -namespace var Div { +namespace var \div { def ( / ) : x = { var ans = self ; ans /= x @@ -104,39 +104,39 @@ namespace var Div { // -typeclass Eq = - & var ( == ) : Eq -> Bool - & var ( != ) : Eq -> Bool +typeclass \eq = + & var ( == ) : \eq -> \bool + & var ( != ) : \eq -> \bool -namespace var Eq { +namespace var \eq { def ( != ) : x = not: (self == x) } // -struct Order = - | EQ - | LT - | GT +struct \order = + | $eq + | $lt + | $gt -typeclass (Ord : #Eq) = - & var compare : Ord -> Order - & var ( < ) : Ord -> Bool - & var ( >= ) : Ord -> Bool - & var ( > ) : Ord -> Bool - & var ( <= ) : Ord -> Bool +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 +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 +decl max 'a[#ord] : 'a -> 'a -> 'a def max : x y = if x < y then y else x -namespace var Ord { +namespace var \ord { def compare : x = - if self == x then $EQ - elif self < x then $LT - else $GT + if self == x then $eq + elif self < x then $lt + else $gt def ( >= ) : x = not: (self < x) def ( > ) : x = x < self @@ -145,44 +145,45 @@ namespace var Ord { // -typeclass Show = - & var show : -> String +typeclass \show = + & var show : -> \string -typeclass Read = - & read : String -> Read +typeclass \read = + & read : \string -> \read -typeclass (Str : #Show #Read) +typeclass \str[#show #read] -// typeclass DebugShow = // TODO -// & debug_show : -> String +// typeclass debug-show = // TODO +// & debugdshow : -> \string // -typeclass Default = - & default : -> Default +typeclass \default = + & default : -> \default // -typeclass Bounded = - & min_bound : -> Bounded - & max_bound : -> Bounded - & var is_max_bound : -> Bool - & var is_min_bound : -> Bool +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 +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 +namespace io { + decl print : \string -> \unit + decl scan : -> \string } +decl random : -> \int // TODO + // diff --git a/tests/test_code.lang b/tests/test_code.lang index 5207e46..971738b 100644 --- a/tests/test_code.lang +++ b/tests/test_code.lang @@ -1,19 +1,19 @@ -basic (Float : #Ord #Div #Str) -basic (Int : #Ord #IDiv #Str) -basic (String : #Ord #Str #CharContainer #Copy) -basic (Char : #Ord #Str #Copy) -basic (Bool : #Ord #Str #Copy) -basic (Unit : #Str #Copy) +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 +decl not : \bool -> \bool def not : x = (match x with | true -> false | false -> true) -decl ( && ) : Bool -> Bool -> Bool +decl ( && ) : \bool -> \bool -> \bool def ( && ) : x y = match x with | true -> ( @@ -23,7 +23,7 @@ def ( && ) : x y = ) | false -> false -decl ( || ) : Bool -> Bool -> Bool +decl ( || ) : \bool -> \bool -> \bool def ( || ) : x y = match x with | true -> true @@ -35,28 +35,28 @@ def ( || ) : x y = // -typeclass CharContainer = - & var size : -> Int - & var at : Int -> Char +typeclass \char-container = + & var size : -> \int + & var at : \int -> \char // -typeclass Move = // TODO - & var ( <- ) : Move -> Unit +typeclass \move = // TODO + & var ( <- ) : \move -> \unit -typeclass Copy = - & var ( = ) : Copy -> Unit +typeclass \copy = + & var ( = ) : \copy -> \unit // -typeclass (Sum : #Copy) = - & var ( += ) : Sum -> Unit - & var ( -= ) : Sum -> Unit - & var ( + ) : Sum -> Sum - & var ( - ) : Sum -> Sum - & zero : -> Sum +typeclass \sum[#copy] = + & var ( += ) : \sum -> \unit + & var ( -= ) : \sum -> \unit + & var ( + ) : \sum -> \sum + & var ( - ) : \sum -> \sum + & zero : -> \sum -namespace var Sum { +namespace var \sum { def ( + ) : x = { var ans = self ; ans += x @@ -70,11 +70,11 @@ namespace var Sum { } } -typeclass (Mult : #Sum) = - & var ( *= ) : Mult -> Unit - & var ( * ) : Mult -> Mult +typeclass \mult[#sum] = + & var ( *= ) : \mult -> \unit + & var ( * ) : \mult -> \mult -namespace var Mult { +namespace var \mult { def ( * ) : x = { var ans = self ; ans *= x @@ -82,19 +82,19 @@ namespace var Mult { } } -typeclass (IDiv : #Mult) = - & var div : IDiv -> IDiv - & var mod : IDiv -> IDiv +typeclass \idiv[#mult] = + & var div : \idiv -> \idiv + & var mod : \idiv -> \idiv -namespace var IDiv { - def mod : x = self -. x * self.div: x +namespace var \idiv { + def mod : x = self -. x * self..div: x } -typeclass (Div : #Mult) = - & var ( /= ) : Div -> Unit - & var ( / ) : Div -> Div +typeclass \div[#mult] = + & var ( /= ) : \div -> \unit + & var ( / ) : \div -> \div -namespace var Div { +namespace var \div { def ( / ) : x = { var ans = self ; ans /= x @@ -104,39 +104,39 @@ namespace var Div { // -typeclass Eq = - & var ( == ) : Eq -> Bool - & var ( != ) : Eq -> Bool +typeclass \eq = + & var ( == ) : \eq -> \bool + & var ( != ) : \eq -> \bool -namespace var Eq { +namespace var \eq { def ( != ) : x = not: (self == x) } // -struct Order = - | EQ - | LT - | GT +struct \order = + | $eq + | $lt + | $gt -typeclass (Ord : #Eq) = - & var compare : Ord -> Order - & var ( < ) : Ord -> Bool - & var ( >= ) : Ord -> Bool - & var ( > ) : Ord -> Bool - & var ( <= ) : Ord -> Bool +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 +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 +decl max 'a[#ord] : 'a -> 'a -> 'a def max : x y = if x < y then y else x -namespace var Ord { +namespace var \ord { def compare : x = - if self == x then $EQ - elif self < x then $LT - else $GT + if self == x then $eq + elif self < x then $lt + else $gt def ( >= ) : x = not: (self < x) def ( > ) : x = x < self @@ -145,63 +145,64 @@ namespace var Ord { // -typeclass Show = - & var show : -> String +typeclass \show = + & var show : -> \string -typeclass Read = - & read : String -> Read +typeclass \read = + & read : \string -> \read -typeclass (Str : #Show #Read) +typeclass \str[#show #read] -// typeclass DebugShow = // TODO -// & debug_show : -> String +// typeclass debug-show = // TODO +// & debugdshow : -> \string // -typeclass Default = - & default : -> Default +typeclass \default = + & default : -> \default // -typeclass Bounded = - & min_bound : -> Bounded - & max_bound : -> Bounded - & var is_max_bound : -> Bool - & var is_min_bound : -> Bool +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 +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 +namespace io { + decl print : \string -> \unit + decl scan : -> \string } -// - -// // bad -// typeclass Functor 'A = -// & fmap 'B ('F : (#Functor 'B)) : ('A -> 'B) -> Functor -> 'F - -// typeclass (Iterator : #Eq) = -// & next : -> Unit -// & prev : -> Unit -// -// typeclass Iterable ('Iter : #Iterable) = -// & begin : -> 'Iter -// & end : -> 'Iter +decl random : -> \int // TODO // -decl ( -- ) : Int -> Int -> Int_0 +// // // bad +// // typeclass \functor 'a = +// // & fmap 'b ('f[#functor['b]]) : ('a -> 'b) -> \functor -> 'f +// +// // typeclass \iterator[#eq] = +// // & next : -> \unit +// // & prev : -> \unit +// +// // typeclass \iterable 'iter[#iterable] = +// // & begin : -> 'iter +// // & end : -> 'iter + +// + +decl ( -- ) : \int -> \int -> \int`0 def ( -- ) : begin end = { var current = begin return (while current < end do { @@ -210,11 +211,11 @@ def ( -- ) : begin end = { }) } -// decl func : String -> Int -> Int +// decl func : \string -> \int -> \int // def func : s i = { // ; print: s // var x = s -// ; print: (i.show:) +// ; print: (i..show:) // return 5 // } // @@ -227,60 +228,60 @@ def ( -- ) : begin end = { // }) // } -decl scan_int : -> Int -def scan_int = Int.read: (IO.scan:) +decl scan-int : -> \int +def scan-int = \int..read: (\io..scan:) -decl print_int : Int -> Unit -def print_int : x = IO.print: (x.show:) +decl print-int : \int -> \unit +def print-int : x = \io..print: (x..show:) -decl scan_anything ('A : #Read) : -> 'A -def scan_anything = 'A.read: (IO.scan:) +decl scan-anything 'a[#read] : -> 'a +def scan-anything = 'a..read: (\io..scan:) -decl print_anything ('A : #Show) : 'A -> Unit -def print_anything : x = IO.print: (x.show:) +decl print-anything 'a[#show] : 'a -> \unit +def print-anything : x = \io..print: (x..show:) -// decl sorted ('A : #Ord #Copy): 'A_0 -> Int -> 'A_0 +// decl sorted 'a[#ord #copy]: 'a`0 -> \int -> 'a`0 // def sorted : a sz = { -// var a_copy = a +// var a-copy = a // if sz == 2 then { -// if a_copy`0 > a_copy`1 then { -// var x = a_copy`0 -// a_copy`0 = a_copy`1 -// a_copy`1 = x +// if a-copy`0 > a-copy`1 then { +// var x = a-copy`0 +// a-copy`0 = a-copy`1 +// a-copy`1 = x // } -// return a_copy +// return a-copy // } // -// var center = sz.div: 2 +// var center = sz..div: 2 // -// var a_left = for i in 0--center do a`i -// var a_right = for i in center-sz do a`i +// var a-left = for i in 0--center do a`i +// var a-right = for i in center-sz do a`i // -// return a_copy +// return a-copy // } -struct Array 'A = & 'A // 'A_0 +// struct \array 'a = & 'a // 'a`0 -// namespace Array { -// decl of : 'A_0 -> (Array 'A) -// def of : x = $(Array 'A) & data = x +// namespace \array { +// decl of : 'a`0 -> \array['a] +// def of : x = $array['a] & data = x // } -struct ThreeTuple = & String & String & String +struct \three-tuple = & \string & \string & \string -decl scan_three_t : -> ThreeTuple -def scan_three_t = $ThreeTuple & IO.scan: & IO.scan: & IO.scan: +decl scan-three-t : -> \three-tuple +def scan-three-t = $three-tuple & \io..scan: & \io..scan: & \io..scan: -decl scan_three : -> (& String & String & String) -def scan_three = & IO.scan: & IO.scan: & IO.scan: +decl scan-three : -> (& \string & \string & \string) +def scan-three = & \io..scan: & \io..scan: & \io..scan: exec main { - var n = scan_anything Int: - var x = $(Array Int) & 0 // (for _ in 0--n do scan_int:) - ; print_anything Int: n + var n = scan-anything:[int] + var x = (for _ in 0--n do scan-int:) // $array[int] & 0 + ; print-anything:[int] n - var & a & b & c = scan_three_t: - ; IO.print: b - var & d & e & f = scan_three: - ; IO.print: e + var & a & b & c = scan-three-t: + ; \io..print: b + var & d & e & f = scan-three: + ; \io..print: e } diff --git a/tests/tuples.lang b/tests/tuples.lang index 73692e8..765cfa0 100644 --- a/tests/tuples.lang +++ b/tests/tuples.lang @@ -1,8 +1,8 @@ -decl test_tuples : -> Unit -def test_tuples = { - var tuple1 = & "a" & 2 & "hello" +decl test-tuples : -> \unit +def test-tuples = { + var tuple1 = & ''a & 2 & "hello" const & t1 & t2 & t3 = f: x - ; tuple1`0 = "b" + ; tuple1`0 = ''b } diff --git a/tests/type_casting.lang b/tests/type_casting.lang index 9d9c255..b2884b8 100644 --- a/tests/type_casting.lang +++ b/tests/type_casting.lang @@ -1,5 +1,5 @@ -decl test_type_casting : -> Unit -def test_type_casting = { - var x = y.as Int: - var k = (f: y x).as Float: +decl test-type-casting : -> \unit +def test-type-casting = { + var x = y..as:[int] + var k = (f: y x)..as:[float] } diff --git a/tests/typeclasses.lang b/tests/typeclasses.lang index 4b32064..2cf4ec5 100644 --- a/tests/typeclasses.lang +++ b/tests/typeclasses.lang @@ -1,29 +1,29 @@ -typeclass Default = - & default : -> Copy +typeclass \default = + & default : -> \default -typeclass (Ord : #Eq) = - & var is_less_then : Ord -> Bool +typeclass \ord[#eq] = + & var is-less-then : \ord -> \bool -typeclass (D : #A #B #C) 'A 'B = - & var do_something : -> (& 'A & 'B) +typeclass \d[#a #b #c] 'a 'b = + & var do-something : -> (& 'a & 'b) -typeclass E 'A = - & var do_something : -> 'A +typeclass \e 'a = + & var do-something : -> 'a -decl ( == ) ('A : #Ord) : 'A -> 'A -> Bool -def ( == ) : a b = a.is_equal_to: b +decl ( == ) 'a[#ord] : 'a -> 'a -> \bool +def ( == ) : a b = a..is-equal-to: b -decl ( != ) ('A : #Ord) : 'A -> 'A -> Bool +decl ( != ) 'a[#ord] : 'a -> 'a -> \bool def ( != ) : a b = not: (a == b) -decl ( < ) ('A : #Ord) : 'A -> 'A -> Bool -def ( < ) : a b = a.is_less_then: b +decl ( < ) 'a[#ord] : 'a -> 'a -> \bool +def ( < ) : a b = a..is-less-then: b -decl ( > ) ('A : #Ord) : 'A -> 'A -> Bool +decl ( > ) 'a[#ord] : 'a -> 'a -> \bool def ( > ) : a b = not: (a <= b) -decl ( <= ) ('A : #Ord) : 'A -> 'A -> Bool +decl ( <= ) 'a[#ord] : 'a -> 'a -> \bool def ( <= ) : a b = a < b ||. a == b -decl ( >= ) ('A : #Ord) : 'A -> 'A -> Bool +decl ( >= ) 'a[#ord] : 'a -> 'a -> \bool def ( >= ) : a b = not: (a < b) diff --git a/tests/types.lang b/tests/types.lang index f6ce429..445bb8d 100644 --- a/tests/types.lang +++ b/tests/types.lang @@ -1,8 +1,8 @@ -alias T1 = Int +alias \t1 = \int -abstract (T2 : #A #B #C) +abstract \t2[#a #b #c] // Used to pre-compile module for some types -let T2 = Int -let T2 = Float -let T2 = Complex +let \t2 = \int +let \t2 = \float +let \t2 = \complex diff --git a/tests/variants.lang b/tests/variants.lang index 9b747b7..49b9019 100644 --- a/tests/variants.lang +++ b/tests/variants.lang @@ -1,6 +1,6 @@ -decl test_variants : -> Unit -def test_variants = { - var variant1 = | 'a' | 2 | "hello" +decl test-variants : -> \unit +def test-variants = { + var variant1 = | ''a | 2 | "hello" var | val | err = f: x ; val -?> "something" // open variant as value in expr @@ -8,7 +8,7 @@ def test_variants = { ; val -!> "nothing" // open variant as None in expr match variant1 with - | 'a' -> "something" + | ''a -> "something" | 2 -> "nothing" | "hello" -> "nothing" | 11 -> "nothing"