From d15cbbf7b33df0f78a575cff9679d84c36ea3ab1 Mon Sep 17 00:00:00 2001 From: Cai Bingjun <1945458160@qq.com> Date: Sun, 4 Sep 2022 07:20:19 +0800 Subject: [PATCH 01/42] Improve the English translation of doc and increase the simplified Chinese translation of doc --- doc/EN/API/consts.md | 13 + doc/EN/API/funcs.md | 121 +++ doc/EN/API/index.md | 0 doc/EN/API/modules/external/alstruct.md | 57 ++ doc/EN/API/modules/repl.md | 24 + doc/EN/API/modules/status.md | 6 + doc/EN/API/modules/unit.md | 73 ++ doc/EN/API/modules/unsound.md | 24 + doc/EN/API/operators.md | 64 ++ doc/EN/API/procs.md | 39 + doc/EN/API/special.md | 175 ++++ doc/EN/API/types.md | 262 ++++++ doc/EN/API/types/classes/Array!(T).md | 4 + doc/EN/API/types/classes/Array(T).md | 3 + doc/EN/API/types/classes/ArrayWithLen(T,N).md | 34 + .../types/classes/ArrayWithMutLength!(T,N).md | 34 + doc/EN/API/types/classes/Class.md | 0 doc/EN/API/types/classes/Complex.md | 14 + doc/EN/API/types/classes/Dict!.md | 7 + doc/EN/API/types/classes/Either.md | 12 + doc/EN/API/types/classes/Float.md | 21 + doc/EN/API/types/classes/Function(N).md | 9 + doc/EN/API/types/classes/Inf.md | 7 + doc/EN/API/types/classes/Int.md | 10 + doc/EN/API/types/classes/IntRange.md | 19 + doc/EN/API/types/classes/Interval.md | 18 + doc/EN/API/types/classes/Iterator.md | 0 doc/EN/API/types/classes/Kind(N).md | 5 + doc/EN/API/types/classes/Matrix.md | 7 + doc/EN/API/types/classes/Module.md | 3 + doc/EN/API/types/classes/Nat.md | 18 + doc/EN/API/types/classes/Neg.md | 8 + doc/EN/API/types/classes/Never.md | 13 + doc/EN/API/types/classes/NonZero.md | 30 + doc/EN/API/types/classes/Object.md | 7 + doc/EN/API/types/classes/Operator.md | 7 + doc/EN/API/types/classes/Option.md | 21 + doc/EN/API/types/classes/Pos.md | 8 + doc/EN/API/types/classes/Ratio.md | 5 + doc/EN/API/types/classes/Record.md | 14 + doc/EN/API/types/classes/Result.md | 7 + doc/EN/API/types/classes/Str!.md | 3 + doc/EN/API/types/classes/Str.md | 9 + doc/EN/API/types/classes/StrWithLen.md | 0 doc/EN/API/types/classes/Subroutine.md | 19 + doc/EN/API/types/classes/Tensor.md | 24 + doc/EN/API/types/classes/TransCell(T).md | 12 + doc/EN/API/types/classes/Tuple.md | 27 + doc/EN/API/types/classes/Type.md | 0 doc/EN/API/types/classes/Vector.md | 3 + doc/EN/API/types/patches/BinOp.md | 7 + doc/EN/API/types/patches/UnaryOp.md | 7 + doc/EN/API/types/traits/Add(R,O).md | 34 + doc/EN/API/types/traits/Div(R,O).md | 9 + doc/EN/API/types/traits/Eq.md | 0 doc/EN/API/types/traits/Into.md | 11 + doc/EN/API/types/traits/Iterable.md | 0 doc/EN/API/types/traits/Num.md | 16 + doc/EN/API/types/traits/Ord.md | 0 doc/EN/API/types/traits/SafeDiv(R,O).md | 8 + doc/EN/API/types/traits/Sample.md | 31 + doc/EN/API/types/traits/Seq.md | 0 doc/EN/API/types/traits/Show.md | 0 doc/EN/API/types/traits/Unpack.md | 13 + doc/EN/compiler/TODO_hint.md | 4 + doc/EN/compiler/TODO_recov_suggest.md | 11 + doc/EN/compiler/TODO_warn.md | 5 + doc/EN/compiler/abandoned.md | 10 + doc/EN/compiler/hir.md | 148 ++++ doc/EN/compiler/index.md | 0 doc/EN/compiler/inference.md | 438 +++++++++ doc/EN/compiler/overview.md | 28 +- doc/EN/compiler/refinement_subtyping.md | 149 ++++ doc/EN/compiler/trait_method_resolving.md | 95 ++ doc/EN/compiler/transpile.md | 90 ++ doc/EN/compiler/type_var_normalization.md | 39 + doc/EN/dev_guide/branches.md | 2 + doc/EN/dev_guide/build_features.md | 6 +- doc/EN/dev_guide/directories.md | 44 +- doc/EN/dev_guide/doc_guideline.md | 8 +- doc/EN/dev_guide/env.md | 16 +- doc/EN/dev_guide/faq_syntax.md | 110 +-- doc/EN/dev_guide/i18n_messages.md | 47 +- doc/EN/dev_guide/rust_code_guideline.md | 26 +- doc/EN/dev_guide/terms.md | 618 ++++++++++++- doc/EN/dev_guide/unify_terms.md | 88 ++ doc/EN/migration_from_py.md | 17 +- doc/EN/python/bytecode_instructions.md | 63 +- doc/EN/syntax/14_set.md | 29 +- doc/EN/syntax/15_type.md | 2 +- doc/EN/syntax/18_ownership.md | 108 +-- doc/EN/syntax/19_visibility.md | 112 +-- doc/EN/syntax/20_naming_rule.md | 30 +- doc/EN/syntax/21_lambda.md | 81 +- doc/EN/syntax/23_closure.md | 58 +- doc/EN/syntax/24_module.md | 2 +- doc/EN/syntax/25_object_system.md | 60 +- doc/EN/syntax/26_pattern_matching.md | 118 +-- doc/EN/syntax/27_comprehension.md | 55 +- doc/EN/syntax/28_spread_syntax.md | 30 +- doc/EN/syntax/29_decorator.md | 93 +- doc/EN/syntax/30_error_handling.md | 75 +- doc/EN/syntax/31_pipeline.md | 17 +- doc/EN/syntax/container_ownership.md | 42 + doc/EN/syntax/grammar.txt | 2 +- doc/EN/syntax/indexes.md | 380 ++++++-- doc/EN/syntax/quick_tour.md | 266 ++++++ doc/EN/syntax/type/14_dependent.md | 68 +- doc/EN/syntax/type/18_mut.md | 148 ++-- doc/EN/syntax/type/19_bound.md | 16 +- doc/EN/syntax/type/advanced.md | 3 +- doc/EN/syntax/type/advanced/GADTs.md | 34 +- doc/EN/syntax/type/advanced/_rank2type.md | 142 +++ doc/EN/syntax/type/advanced/default_param.md | 18 +- doc/EN/syntax/type/advanced/keyword_param.md | 16 +- doc/EN/syntax/type/advanced/kind.md | 34 +- doc/EN/syntax/type/advanced/marker_trait.md | 20 +- doc/EN/syntax/type/advanced/special.md | 28 +- doc/EN/syntax/type/advanced/typeof.md | 65 ++ doc/EN/syntax/type/advanced/variance.md | 143 +++ doc/EN/syntax/type/advanced/widening.md | 92 ++ doc/EN/tools/build.md | 14 + doc/EN/tools/env.md | 7 + doc/EN/tools/fmt.md | 6 + doc/EN/tools/index.md | 0 doc/EN/tools/install.md | 10 + doc/EN/tools/pack.md | 100 +++ doc/EN/tools/repl.md | 15 + doc/EN/tools/test.md | 45 + doc/JA/compiler/architecture.md | 56 +- doc/JA/compiler/parsing.md | 2 +- doc/JA/syntax/type/04_class.md | 10 +- doc/zh_CN/API/consts.md | 13 + doc/zh_CN/API/funcs.md | 121 +++ doc/zh_CN/API/index.md | 0 doc/zh_CN/API/modules/external/alstruct.md | 57 ++ doc/zh_CN/API/modules/repl.md | 24 + doc/zh_CN/API/modules/status.md | 6 + doc/zh_CN/API/modules/unit.md | 73 ++ doc/zh_CN/API/modules/unsound.md | 24 + doc/zh_CN/API/operators.md | 64 ++ doc/zh_CN/API/procs.md | 39 + doc/zh_CN/API/special.md | 175 ++++ doc/zh_CN/API/types.md | 262 ++++++ doc/zh_CN/API/types/classes/Array!(T).md | 3 + doc/zh_CN/API/types/classes/Array(T).md | 3 + .../API/types/classes/ArrayWithLen(T,N).md | 34 + .../types/classes/ArrayWithMutLength!(T,N).md | 26 + doc/zh_CN/API/types/classes/Class.md | 0 doc/zh_CN/API/types/classes/Complex.md | 14 + doc/zh_CN/API/types/classes/Dict!.md | 7 + doc/zh_CN/API/types/classes/Either.md | 12 + doc/zh_CN/API/types/classes/Float.md | 21 + doc/zh_CN/API/types/classes/Function(N).md | 9 + doc/zh_CN/API/types/classes/Inf.md | 7 + doc/zh_CN/API/types/classes/Int.md | 10 + doc/zh_CN/API/types/classes/IntRange.md | 19 + doc/zh_CN/API/types/classes/Interval.md | 18 + doc/zh_CN/API/types/classes/Iterator.md | 0 doc/zh_CN/API/types/classes/Kind(N).md | 5 + doc/zh_CN/API/types/classes/Matrix.md | 7 + doc/zh_CN/API/types/classes/Module.md | 3 + doc/zh_CN/API/types/classes/Nat.md | 18 + doc/zh_CN/API/types/classes/Neg.md | 8 + doc/zh_CN/API/types/classes/Never.md | 13 + doc/zh_CN/API/types/classes/NonZero.md | 30 + doc/zh_CN/API/types/classes/Object.md | 7 + doc/zh_CN/API/types/classes/Operator.md | 7 + doc/zh_CN/API/types/classes/Option.md | 21 + doc/zh_CN/API/types/classes/Pos.md | 8 + doc/zh_CN/API/types/classes/Ratio.md | 5 + doc/zh_CN/API/types/classes/Record.md | 14 + doc/zh_CN/API/types/classes/Result.md | 7 + doc/zh_CN/API/types/classes/Str!.md | 3 + doc/zh_CN/API/types/classes/Str.md | 9 + doc/zh_CN/API/types/classes/StrWithLen.md | 0 doc/zh_CN/API/types/classes/Subroutine.md | 19 + doc/zh_CN/API/types/classes/Tensor.md | 24 + doc/zh_CN/API/types/classes/TransCell(T).md | 12 + doc/zh_CN/API/types/classes/Tuple.md | 27 + doc/zh_CN/API/types/classes/Type.md | 0 doc/zh_CN/API/types/classes/Vector.md | 3 + doc/zh_CN/API/types/patches/BinOp.md | 7 + doc/zh_CN/API/types/patches/UnaryOp.md | 7 + doc/zh_CN/API/types/traits/Add(R,O).md | 34 + doc/zh_CN/API/types/traits/Div(R,O).md | 9 + doc/zh_CN/API/types/traits/Eq.md | 0 doc/zh_CN/API/types/traits/Into.md | 11 + doc/zh_CN/API/types/traits/Iterable.md | 0 doc/zh_CN/API/types/traits/Num.md | 16 + doc/zh_CN/API/types/traits/Ord.md | 0 doc/zh_CN/API/types/traits/SafeDiv(R,O).md | 8 + doc/zh_CN/API/types/traits/Sample.md | 31 + doc/zh_CN/API/types/traits/Seq.md | 0 doc/zh_CN/API/types/traits/Show.md | 0 doc/zh_CN/API/types/traits/Unpack.md | 13 + doc/zh_CN/compiler/TODO_hint.md | 4 + doc/zh_CN/compiler/TODO_recov_suggest.md | 11 + doc/zh_CN/compiler/TODO_warn.md | 5 + doc/zh_CN/compiler/abandoned.md | 10 + doc/zh_CN/compiler/architecture.md | 42 + doc/zh_CN/compiler/errors.md | 131 +++ doc/zh_CN/compiler/hir.md | 148 ++++ doc/zh_CN/compiler/index.md | 0 doc/zh_CN/compiler/inference.md | 436 +++++++++ doc/zh_CN/compiler/overview.md | 36 + doc/zh_CN/compiler/parsing.md | 31 + doc/zh_CN/compiler/refinement_subtyping.md | 155 ++++ doc/zh_CN/compiler/trait_method_resolving.md | 86 ++ doc/zh_CN/compiler/transpile.md | 91 ++ doc/zh_CN/compiler/type_var_normalization.md | 35 + doc/zh_CN/dev_guide/branches.md | 31 + doc/zh_CN/dev_guide/build_features.md | 17 + doc/zh_CN/dev_guide/directories.md | 25 + doc/zh_CN/dev_guide/doc_guideline.md | 13 + doc/zh_CN/dev_guide/env.md | 19 + doc/zh_CN/dev_guide/faq_syntax.md | 108 +++ doc/zh_CN/dev_guide/i18n_messages.md | 55 ++ doc/zh_CN/dev_guide/index.md | 0 doc/zh_CN/dev_guide/rust_code_guideline.md | 23 + doc/zh_CN/dev_guide/terms.md | 831 ++++++++++++++++++ doc/zh_CN/dev_guide/unify_terms.md | 80 ++ doc/zh_CN/faq_general.md | 27 + doc/zh_CN/faq_technical.md | 25 + doc/zh_CN/improved_points.md | 46 + doc/zh_CN/index.md | 25 + doc/zh_CN/migration_from_py.md | 28 + doc/zh_CN/python/bytecode_instructions.md | 106 +++ doc/zh_CN/python/bytecode_specification.md | 70 ++ doc/zh_CN/python/class_system.md | 95 ++ doc/zh_CN/python/index.md | 0 doc/zh_CN/syntax/00_basic.md | 121 +++ doc/zh_CN/syntax/01_literal.md | 165 ++++ doc/zh_CN/syntax/02_name.md | 169 ++++ doc/zh_CN/syntax/03_declaration.md | 48 + doc/zh_CN/syntax/04_function.md | 306 +++++++ doc/zh_CN/syntax/05_builtin_funcs.md | 52 ++ doc/zh_CN/syntax/06_operator.md | 30 + doc/zh_CN/syntax/07_side_effect.md | 123 +++ doc/zh_CN/syntax/08_procedure.md | 12 + doc/zh_CN/syntax/09_builtin_procs.md | 13 + doc/zh_CN/syntax/10_array.md | 56 ++ doc/zh_CN/syntax/11_tuple.md | 125 +++ doc/zh_CN/syntax/12_dict.md | 71 ++ doc/zh_CN/syntax/13_record.md | 198 +++++ doc/zh_CN/syntax/14_set.md | 50 ++ doc/zh_CN/syntax/15_type.md | 7 + doc/zh_CN/syntax/16_iterator.md | 91 ++ doc/zh_CN/syntax/17_mutability.md | 92 ++ doc/zh_CN/syntax/18_ownership.md | 103 +++ doc/zh_CN/syntax/19_visibility.md | 199 +++++ doc/zh_CN/syntax/20_naming_rule.md | 52 ++ doc/zh_CN/syntax/21_lambda.md | 102 +++ doc/zh_CN/syntax/22_subroutine.md | 65 ++ doc/zh_CN/syntax/23_closure.md | 99 +++ doc/zh_CN/syntax/24_module.md | 47 + doc/zh_CN/syntax/25_object_system.md | 77 ++ doc/zh_CN/syntax/26_pattern_matching.md | 203 +++++ doc/zh_CN/syntax/27_comprehension.md | 65 ++ doc/zh_CN/syntax/28_spread_syntax.md | 45 + doc/zh_CN/syntax/29_decorator.md | 124 +++ doc/zh_CN/syntax/30_error_handling.md | 106 +++ doc/zh_CN/syntax/31_pipeline.md | 32 + .../syntax/32_integration_with_Python.md | 87 ++ doc/zh_CN/syntax/33_package_system.md | 83 ++ doc/zh_CN/syntax/34_generator.md | 37 + doc/zh_CN/syntax/SUMMARY.md | 69 ++ doc/zh_CN/syntax/container_ownership.md | 42 + doc/zh_CN/syntax/grammar.txt | 88 ++ doc/zh_CN/syntax/indexes.md | 452 ++++++++++ doc/zh_CN/syntax/quick_tour.md | 287 ++++++ doc/zh_CN/syntax/type/01_type_system.md | 225 +++++ doc/zh_CN/syntax/type/02_basic.md | 170 ++++ doc/zh_CN/syntax/type/03_trait.md | 193 ++++ doc/zh_CN/syntax/type/04_class.md | 285 ++++++ doc/zh_CN/syntax/type/05_inheritance.md | 248 ++++++ doc/zh_CN/syntax/type/06_nst_vs_sst.md | 43 + doc/zh_CN/syntax/type/07_patch.md | 223 +++++ doc/zh_CN/syntax/type/08_value.md | 38 + doc/zh_CN/syntax/type/09_attributive.md | 7 + doc/zh_CN/syntax/type/10_interval.md | 39 + doc/zh_CN/syntax/type/11_enum.md | 86 ++ doc/zh_CN/syntax/type/12_refinement.md | 75 ++ doc/zh_CN/syntax/type/13_algebraic.md | 82 ++ doc/zh_CN/syntax/type/14_dependent.md | 76 ++ doc/zh_CN/syntax/type/15_quantified.md | 288 ++++++ doc/zh_CN/syntax/type/16_subtyping.md | 80 ++ doc/zh_CN/syntax/type/17_type_casting.md | 74 ++ doc/zh_CN/syntax/type/18_mut.md | 168 ++++ doc/zh_CN/syntax/type/19_bound.md | 16 + doc/zh_CN/syntax/type/advanced.md | 1 + doc/zh_CN/syntax/type/advanced/GADTs.md | 68 ++ doc/zh_CN/syntax/type/advanced/_rank2type.md | 142 +++ .../syntax/type/advanced/default_param.md | 28 + doc/zh_CN/syntax/type/advanced/erasure.md | 45 + doc/zh_CN/syntax/type/advanced/existential.md | 39 + .../syntax/type/advanced/keyword_param.md | 26 + doc/zh_CN/syntax/type/advanced/kind.md | 157 ++++ .../syntax/type/advanced/marker_trait.md | 33 + doc/zh_CN/syntax/type/advanced/mut_struct.md | 40 + doc/zh_CN/syntax/type/advanced/newtype.md | 31 + doc/zh_CN/syntax/type/advanced/overloading.md | 91 ++ doc/zh_CN/syntax/type/advanced/phantom.md | 58 ++ doc/zh_CN/syntax/type/advanced/projection.md | 25 + .../type/advanced/quantified_dependent.md | 30 + doc/zh_CN/syntax/type/advanced/shared.md | 72 ++ doc/zh_CN/syntax/type/advanced/special.md | 54 ++ doc/zh_CN/syntax/type/advanced/typeof.md | 61 ++ doc/zh_CN/syntax/type/advanced/variance.md | 128 +++ doc/zh_CN/syntax/type/advanced/widening.md | 93 ++ doc/zh_CN/tips.md | 142 +++ doc/zh_CN/tools/build.md | 13 + doc/zh_CN/tools/env.md | 3 + doc/zh_CN/tools/fmt.md | 5 + doc/zh_CN/tools/index.md | 0 doc/zh_CN/tools/install.md | 9 + doc/zh_CN/tools/pack.md | 82 ++ doc/zh_CN/tools/repl.md | 15 + doc/zh_CN/tools/test.md | 43 + 319 files changed, 17672 insertions(+), 893 deletions(-) create mode 100644 doc/EN/API/consts.md create mode 100644 doc/EN/API/funcs.md create mode 100644 doc/EN/API/index.md create mode 100644 doc/EN/API/modules/external/alstruct.md create mode 100644 doc/EN/API/modules/repl.md create mode 100644 doc/EN/API/modules/status.md create mode 100644 doc/EN/API/modules/unit.md create mode 100644 doc/EN/API/modules/unsound.md create mode 100644 doc/EN/API/operators.md create mode 100644 doc/EN/API/procs.md create mode 100644 doc/EN/API/special.md create mode 100644 doc/EN/API/types.md create mode 100644 doc/EN/API/types/classes/Array!(T).md create mode 100644 doc/EN/API/types/classes/Array(T).md create mode 100644 doc/EN/API/types/classes/ArrayWithLen(T,N).md create mode 100644 doc/EN/API/types/classes/ArrayWithMutLength!(T,N).md create mode 100644 doc/EN/API/types/classes/Class.md create mode 100644 doc/EN/API/types/classes/Complex.md create mode 100644 doc/EN/API/types/classes/Dict!.md create mode 100644 doc/EN/API/types/classes/Either.md create mode 100644 doc/EN/API/types/classes/Float.md create mode 100644 doc/EN/API/types/classes/Function(N).md create mode 100644 doc/EN/API/types/classes/Inf.md create mode 100644 doc/EN/API/types/classes/Int.md create mode 100644 doc/EN/API/types/classes/IntRange.md create mode 100644 doc/EN/API/types/classes/Interval.md create mode 100644 doc/EN/API/types/classes/Iterator.md create mode 100644 doc/EN/API/types/classes/Kind(N).md create mode 100644 doc/EN/API/types/classes/Matrix.md create mode 100644 doc/EN/API/types/classes/Module.md create mode 100644 doc/EN/API/types/classes/Nat.md create mode 100644 doc/EN/API/types/classes/Neg.md create mode 100644 doc/EN/API/types/classes/Never.md create mode 100644 doc/EN/API/types/classes/NonZero.md create mode 100644 doc/EN/API/types/classes/Object.md create mode 100644 doc/EN/API/types/classes/Operator.md create mode 100644 doc/EN/API/types/classes/Option.md create mode 100644 doc/EN/API/types/classes/Pos.md create mode 100644 doc/EN/API/types/classes/Ratio.md create mode 100644 doc/EN/API/types/classes/Record.md create mode 100644 doc/EN/API/types/classes/Result.md create mode 100644 doc/EN/API/types/classes/Str!.md create mode 100644 doc/EN/API/types/classes/Str.md create mode 100644 doc/EN/API/types/classes/StrWithLen.md create mode 100644 doc/EN/API/types/classes/Subroutine.md create mode 100644 doc/EN/API/types/classes/Tensor.md create mode 100644 doc/EN/API/types/classes/TransCell(T).md create mode 100644 doc/EN/API/types/classes/Tuple.md create mode 100644 doc/EN/API/types/classes/Type.md create mode 100644 doc/EN/API/types/classes/Vector.md create mode 100644 doc/EN/API/types/patches/BinOp.md create mode 100644 doc/EN/API/types/patches/UnaryOp.md create mode 100644 doc/EN/API/types/traits/Add(R,O).md create mode 100644 doc/EN/API/types/traits/Div(R,O).md create mode 100644 doc/EN/API/types/traits/Eq.md create mode 100644 doc/EN/API/types/traits/Into.md create mode 100644 doc/EN/API/types/traits/Iterable.md create mode 100644 doc/EN/API/types/traits/Num.md create mode 100644 doc/EN/API/types/traits/Ord.md create mode 100644 doc/EN/API/types/traits/SafeDiv(R,O).md create mode 100644 doc/EN/API/types/traits/Sample.md create mode 100644 doc/EN/API/types/traits/Seq.md create mode 100644 doc/EN/API/types/traits/Show.md create mode 100644 doc/EN/API/types/traits/Unpack.md create mode 100644 doc/EN/compiler/TODO_hint.md create mode 100644 doc/EN/compiler/TODO_recov_suggest.md create mode 100644 doc/EN/compiler/TODO_warn.md create mode 100644 doc/EN/compiler/abandoned.md create mode 100644 doc/EN/compiler/hir.md create mode 100644 doc/EN/compiler/index.md create mode 100644 doc/EN/compiler/inference.md create mode 100644 doc/EN/compiler/refinement_subtyping.md create mode 100644 doc/EN/compiler/trait_method_resolving.md create mode 100644 doc/EN/compiler/transpile.md create mode 100644 doc/EN/compiler/type_var_normalization.md create mode 100644 doc/EN/syntax/container_ownership.md create mode 100644 doc/EN/syntax/type/advanced/_rank2type.md create mode 100644 doc/EN/syntax/type/advanced/typeof.md create mode 100644 doc/EN/syntax/type/advanced/variance.md create mode 100644 doc/EN/syntax/type/advanced/widening.md create mode 100644 doc/EN/tools/build.md create mode 100644 doc/EN/tools/env.md create mode 100644 doc/EN/tools/fmt.md create mode 100644 doc/EN/tools/index.md create mode 100644 doc/EN/tools/install.md create mode 100644 doc/EN/tools/pack.md create mode 100644 doc/EN/tools/repl.md create mode 100644 doc/EN/tools/test.md create mode 100644 doc/zh_CN/API/consts.md create mode 100644 doc/zh_CN/API/funcs.md create mode 100644 doc/zh_CN/API/index.md create mode 100644 doc/zh_CN/API/modules/external/alstruct.md create mode 100644 doc/zh_CN/API/modules/repl.md create mode 100644 doc/zh_CN/API/modules/status.md create mode 100644 doc/zh_CN/API/modules/unit.md create mode 100644 doc/zh_CN/API/modules/unsound.md create mode 100644 doc/zh_CN/API/operators.md create mode 100644 doc/zh_CN/API/procs.md create mode 100644 doc/zh_CN/API/special.md create mode 100644 doc/zh_CN/API/types.md create mode 100644 doc/zh_CN/API/types/classes/Array!(T).md create mode 100644 doc/zh_CN/API/types/classes/Array(T).md create mode 100644 doc/zh_CN/API/types/classes/ArrayWithLen(T,N).md create mode 100644 doc/zh_CN/API/types/classes/ArrayWithMutLength!(T,N).md create mode 100644 doc/zh_CN/API/types/classes/Class.md create mode 100644 doc/zh_CN/API/types/classes/Complex.md create mode 100644 doc/zh_CN/API/types/classes/Dict!.md create mode 100644 doc/zh_CN/API/types/classes/Either.md create mode 100644 doc/zh_CN/API/types/classes/Float.md create mode 100644 doc/zh_CN/API/types/classes/Function(N).md create mode 100644 doc/zh_CN/API/types/classes/Inf.md create mode 100644 doc/zh_CN/API/types/classes/Int.md create mode 100644 doc/zh_CN/API/types/classes/IntRange.md create mode 100644 doc/zh_CN/API/types/classes/Interval.md create mode 100644 doc/zh_CN/API/types/classes/Iterator.md create mode 100644 doc/zh_CN/API/types/classes/Kind(N).md create mode 100644 doc/zh_CN/API/types/classes/Matrix.md create mode 100644 doc/zh_CN/API/types/classes/Module.md create mode 100644 doc/zh_CN/API/types/classes/Nat.md create mode 100644 doc/zh_CN/API/types/classes/Neg.md create mode 100644 doc/zh_CN/API/types/classes/Never.md create mode 100644 doc/zh_CN/API/types/classes/NonZero.md create mode 100644 doc/zh_CN/API/types/classes/Object.md create mode 100644 doc/zh_CN/API/types/classes/Operator.md create mode 100644 doc/zh_CN/API/types/classes/Option.md create mode 100644 doc/zh_CN/API/types/classes/Pos.md create mode 100644 doc/zh_CN/API/types/classes/Ratio.md create mode 100644 doc/zh_CN/API/types/classes/Record.md create mode 100644 doc/zh_CN/API/types/classes/Result.md create mode 100644 doc/zh_CN/API/types/classes/Str!.md create mode 100644 doc/zh_CN/API/types/classes/Str.md create mode 100644 doc/zh_CN/API/types/classes/StrWithLen.md create mode 100644 doc/zh_CN/API/types/classes/Subroutine.md create mode 100644 doc/zh_CN/API/types/classes/Tensor.md create mode 100644 doc/zh_CN/API/types/classes/TransCell(T).md create mode 100644 doc/zh_CN/API/types/classes/Tuple.md create mode 100644 doc/zh_CN/API/types/classes/Type.md create mode 100644 doc/zh_CN/API/types/classes/Vector.md create mode 100644 doc/zh_CN/API/types/patches/BinOp.md create mode 100644 doc/zh_CN/API/types/patches/UnaryOp.md create mode 100644 doc/zh_CN/API/types/traits/Add(R,O).md create mode 100644 doc/zh_CN/API/types/traits/Div(R,O).md create mode 100644 doc/zh_CN/API/types/traits/Eq.md create mode 100644 doc/zh_CN/API/types/traits/Into.md create mode 100644 doc/zh_CN/API/types/traits/Iterable.md create mode 100644 doc/zh_CN/API/types/traits/Num.md create mode 100644 doc/zh_CN/API/types/traits/Ord.md create mode 100644 doc/zh_CN/API/types/traits/SafeDiv(R,O).md create mode 100644 doc/zh_CN/API/types/traits/Sample.md create mode 100644 doc/zh_CN/API/types/traits/Seq.md create mode 100644 doc/zh_CN/API/types/traits/Show.md create mode 100644 doc/zh_CN/API/types/traits/Unpack.md create mode 100644 doc/zh_CN/compiler/TODO_hint.md create mode 100644 doc/zh_CN/compiler/TODO_recov_suggest.md create mode 100644 doc/zh_CN/compiler/TODO_warn.md create mode 100644 doc/zh_CN/compiler/abandoned.md create mode 100644 doc/zh_CN/compiler/architecture.md create mode 100644 doc/zh_CN/compiler/errors.md create mode 100644 doc/zh_CN/compiler/hir.md create mode 100644 doc/zh_CN/compiler/index.md create mode 100644 doc/zh_CN/compiler/inference.md create mode 100644 doc/zh_CN/compiler/overview.md create mode 100644 doc/zh_CN/compiler/parsing.md create mode 100644 doc/zh_CN/compiler/refinement_subtyping.md create mode 100644 doc/zh_CN/compiler/trait_method_resolving.md create mode 100644 doc/zh_CN/compiler/transpile.md create mode 100644 doc/zh_CN/compiler/type_var_normalization.md create mode 100644 doc/zh_CN/dev_guide/branches.md create mode 100644 doc/zh_CN/dev_guide/build_features.md create mode 100644 doc/zh_CN/dev_guide/directories.md create mode 100644 doc/zh_CN/dev_guide/doc_guideline.md create mode 100644 doc/zh_CN/dev_guide/env.md create mode 100644 doc/zh_CN/dev_guide/faq_syntax.md create mode 100644 doc/zh_CN/dev_guide/i18n_messages.md create mode 100644 doc/zh_CN/dev_guide/index.md create mode 100644 doc/zh_CN/dev_guide/rust_code_guideline.md create mode 100644 doc/zh_CN/dev_guide/terms.md create mode 100644 doc/zh_CN/dev_guide/unify_terms.md create mode 100644 doc/zh_CN/faq_general.md create mode 100644 doc/zh_CN/faq_technical.md create mode 100644 doc/zh_CN/improved_points.md create mode 100644 doc/zh_CN/index.md create mode 100644 doc/zh_CN/migration_from_py.md create mode 100644 doc/zh_CN/python/bytecode_instructions.md create mode 100644 doc/zh_CN/python/bytecode_specification.md create mode 100644 doc/zh_CN/python/class_system.md create mode 100644 doc/zh_CN/python/index.md create mode 100644 doc/zh_CN/syntax/00_basic.md create mode 100644 doc/zh_CN/syntax/01_literal.md create mode 100644 doc/zh_CN/syntax/02_name.md create mode 100644 doc/zh_CN/syntax/03_declaration.md create mode 100644 doc/zh_CN/syntax/04_function.md create mode 100644 doc/zh_CN/syntax/05_builtin_funcs.md create mode 100644 doc/zh_CN/syntax/06_operator.md create mode 100644 doc/zh_CN/syntax/07_side_effect.md create mode 100644 doc/zh_CN/syntax/08_procedure.md create mode 100644 doc/zh_CN/syntax/09_builtin_procs.md create mode 100644 doc/zh_CN/syntax/10_array.md create mode 100644 doc/zh_CN/syntax/11_tuple.md create mode 100644 doc/zh_CN/syntax/12_dict.md create mode 100644 doc/zh_CN/syntax/13_record.md create mode 100644 doc/zh_CN/syntax/14_set.md create mode 100644 doc/zh_CN/syntax/15_type.md create mode 100644 doc/zh_CN/syntax/16_iterator.md create mode 100644 doc/zh_CN/syntax/17_mutability.md create mode 100644 doc/zh_CN/syntax/18_ownership.md create mode 100644 doc/zh_CN/syntax/19_visibility.md create mode 100644 doc/zh_CN/syntax/20_naming_rule.md create mode 100644 doc/zh_CN/syntax/21_lambda.md create mode 100644 doc/zh_CN/syntax/22_subroutine.md create mode 100644 doc/zh_CN/syntax/23_closure.md create mode 100644 doc/zh_CN/syntax/24_module.md create mode 100644 doc/zh_CN/syntax/25_object_system.md create mode 100644 doc/zh_CN/syntax/26_pattern_matching.md create mode 100644 doc/zh_CN/syntax/27_comprehension.md create mode 100644 doc/zh_CN/syntax/28_spread_syntax.md create mode 100644 doc/zh_CN/syntax/29_decorator.md create mode 100644 doc/zh_CN/syntax/30_error_handling.md create mode 100644 doc/zh_CN/syntax/31_pipeline.md create mode 100644 doc/zh_CN/syntax/32_integration_with_Python.md create mode 100644 doc/zh_CN/syntax/33_package_system.md create mode 100644 doc/zh_CN/syntax/34_generator.md create mode 100644 doc/zh_CN/syntax/SUMMARY.md create mode 100644 doc/zh_CN/syntax/container_ownership.md create mode 100644 doc/zh_CN/syntax/grammar.txt create mode 100644 doc/zh_CN/syntax/indexes.md create mode 100644 doc/zh_CN/syntax/quick_tour.md create mode 100644 doc/zh_CN/syntax/type/01_type_system.md create mode 100644 doc/zh_CN/syntax/type/02_basic.md create mode 100644 doc/zh_CN/syntax/type/03_trait.md create mode 100644 doc/zh_CN/syntax/type/04_class.md create mode 100644 doc/zh_CN/syntax/type/05_inheritance.md create mode 100644 doc/zh_CN/syntax/type/06_nst_vs_sst.md create mode 100644 doc/zh_CN/syntax/type/07_patch.md create mode 100644 doc/zh_CN/syntax/type/08_value.md create mode 100644 doc/zh_CN/syntax/type/09_attributive.md create mode 100644 doc/zh_CN/syntax/type/10_interval.md create mode 100644 doc/zh_CN/syntax/type/11_enum.md create mode 100644 doc/zh_CN/syntax/type/12_refinement.md create mode 100644 doc/zh_CN/syntax/type/13_algebraic.md create mode 100644 doc/zh_CN/syntax/type/14_dependent.md create mode 100644 doc/zh_CN/syntax/type/15_quantified.md create mode 100644 doc/zh_CN/syntax/type/16_subtyping.md create mode 100644 doc/zh_CN/syntax/type/17_type_casting.md create mode 100644 doc/zh_CN/syntax/type/18_mut.md create mode 100644 doc/zh_CN/syntax/type/19_bound.md create mode 100644 doc/zh_CN/syntax/type/advanced.md create mode 100644 doc/zh_CN/syntax/type/advanced/GADTs.md create mode 100644 doc/zh_CN/syntax/type/advanced/_rank2type.md create mode 100644 doc/zh_CN/syntax/type/advanced/default_param.md create mode 100644 doc/zh_CN/syntax/type/advanced/erasure.md create mode 100644 doc/zh_CN/syntax/type/advanced/existential.md create mode 100644 doc/zh_CN/syntax/type/advanced/keyword_param.md create mode 100644 doc/zh_CN/syntax/type/advanced/kind.md create mode 100644 doc/zh_CN/syntax/type/advanced/marker_trait.md create mode 100644 doc/zh_CN/syntax/type/advanced/mut_struct.md create mode 100644 doc/zh_CN/syntax/type/advanced/newtype.md create mode 100644 doc/zh_CN/syntax/type/advanced/overloading.md create mode 100644 doc/zh_CN/syntax/type/advanced/phantom.md create mode 100644 doc/zh_CN/syntax/type/advanced/projection.md create mode 100644 doc/zh_CN/syntax/type/advanced/quantified_dependent.md create mode 100644 doc/zh_CN/syntax/type/advanced/shared.md create mode 100644 doc/zh_CN/syntax/type/advanced/special.md create mode 100644 doc/zh_CN/syntax/type/advanced/typeof.md create mode 100644 doc/zh_CN/syntax/type/advanced/variance.md create mode 100644 doc/zh_CN/syntax/type/advanced/widening.md create mode 100644 doc/zh_CN/tips.md create mode 100644 doc/zh_CN/tools/build.md create mode 100644 doc/zh_CN/tools/env.md create mode 100644 doc/zh_CN/tools/fmt.md create mode 100644 doc/zh_CN/tools/index.md create mode 100644 doc/zh_CN/tools/install.md create mode 100644 doc/zh_CN/tools/pack.md create mode 100644 doc/zh_CN/tools/repl.md create mode 100644 doc/zh_CN/tools/test.md diff --git a/doc/EN/API/consts.md b/doc/EN/API/consts.md new file mode 100644 index 00000000..daf7d1e5 --- /dev/null +++ b/doc/EN/API/consts.md @@ -0,0 +1,13 @@ +# built-in constants + +## True + +## False + +## None + +## Ellipsis + +## Not Implemented + +## Inf \ No newline at end of file diff --git a/doc/EN/API/funcs.md b/doc/EN/API/funcs.md new file mode 100644 index 00000000..78128595 --- /dev/null +++ b/doc/EN/API/funcs.md @@ -0,0 +1,121 @@ +# functions + +## basic functions + +### if|T; U|(cond: Bool, then: T, else: U) -> T or U + +### map|T; U|(i: Iterable T, f: T -> U) -> Map U + +Note that the order of arguments is reversed from Python. + +### log(x: Object, type: LogType = Info) -> None + +Log `x` in debug display. Logs are summarized and displayed after the execution is finished. +Emoji-capable terminals are prefixed according to `type`. + +* type == Info: 💬 +* type == Ok: ✅ +* type == Warn: ⚠️ +* type == Hint: 💡 + +### panic(msg: Str) -> Panic + +Display msg and stop. +Emoji-capable terminals have a 🚨 prefix. + +### discard|T|(x: ...T) -> NoneType + +Throw away `x`. Used when the return value is not used. Unlike `del`, it does not make the variable `x` inaccessible. + +``` erg +p!x= + # Let q! return some None or non-() value + # use `discard` if you don't need it + discard q!(x) + f x + +discard True +assert True # OK +``` + +### import(path: Path) -> Module or CompilerPanic + +Import a module. Raises a compilation error if the module is not found. + +### eval(code: Str) -> Object + +Evaluate code as code and return. + +### classof(object: Object) -> Class + +Returns the class of `object`. +However, since classes cannot be compared, use `object in Class` instead of `classof(object) == Class` if you want to judge instances. +The structure type determined at compile time is obtained with `Typeof`. + +## Iterator, Array generation system + +### repeat|T|(x: T) -> RepeatIterator T + +``` erg +rep = repeat 1 # Repeater(1) +for! rep, i => + print!i +# 1 1 1 1 1 ... +``` + +### dup|T; N|(x: T, N: Nat) -> [T; N] + +``` erg +[a, b, c] = dup new(), 3 +print! a #
\ No newline at end of file diff --git a/doc/EN/syntax/15_type.md b/doc/EN/syntax/15_type.md index 97b8bad7..8430dc74 100644 --- a/doc/EN/syntax/15_type.md +++ b/doc/EN/syntax/15_type.md @@ -4,4 +4,4 @@ Types are a very important feature in Erg, so we have a [dedicated section](./ty + \ No newline at end of file diff --git a/doc/EN/syntax/18_ownership.md b/doc/EN/syntax/18_ownership.md index 26b463a0..1f1e0232 100644 --- a/doc/EN/syntax/18_ownership.md +++ b/doc/EN/syntax/18_ownership.md @@ -1,110 +1,110 @@ -# Ownership System +# Ownership system -Since Erg is a language that uses Python as its host language, its method of memory management is dependent on the Python implementation. -Semantically, however, Erg's memory management is different from that of Python. The most noticeable differences appear in the ownership system and the prohibition of circular references. +Since Erg is a language that uses Python as the host language, the method of memory management depends on the Python implementation. +But semantically Erg's memory management is different from Python's. A notable difference is in the ownership system and the prohibition of circular references. ## Ownership -Erg has an ownership system influenced by Rust. -While Rust's ownership system is generally considered arcane, Erg's has been simplified to make it intuitive. -In Erg, ownership is attached to __mutable objects__, which cannot be referenced after you lose ownership. +Erg has an ownership system inspired by Rust. +Rust's ownership system is generally considered esoteric, but Erg's is simplified to be intuitive. +In Erg, __mutable objects__ are owned and cannot be referenced after ownership is lost. -```erg -v = [1, 2, 3].into [Int; !3]. +``` erg +v = [1, 2, 3].into [Int; !3] -push!vec, x = +push! vec, x = vec.push!(x) - vec. + vec -# ownership of v's contents ([1, 2, 3]) is transferred to w +# The contents of v ([1, 2, 3]) are owned by w w = push! v, 4 print! v # error: v was moved -print! w # [1, 2, 3, 4] +print!w # [1, 2, 3, 4] ``` -Ownership transfers occur when an object is passed to a subroutine, for example. -If you wish to retain ownership of the object after passing it to a subroutine, you must do cloning, freezing, or borrowing. -However, as described below, borrowing can only be used in limited situations. +Ownership transfer occurs, for example, when an object is passed to a subroutine. +If you want to still have ownership after giving it away, you'll need to clone, freeze, or borrow. +However, as will be explained later, there are limited situations in which it can be borrowed. -## Cloning +## replication -Duplicate an object and transfer ownership of it. This is done by applying the `.clone` method to the real argument. -The cloned object will be exactly the same as the original object, but independent of each other and unaffected by changes. +Duplicate an object and transfer its ownership. It does this by applying the `.clone` method to the actual arguments. +The duplicated object is exactly the same as the original, but independent of each other and unaffected by changes. -Cloning is equivalent to deep copying in Python, and is generally more computationally and memory expensive than freezing and borrowing, since it re-creates the same object in its entirety. -Subroutines that require object duplication are called "argument-consuming" subroutines. +Duplication is equivalent to Python's deep copy, and since it recreates the same object entirely, the computation and memory costs are generally higher than freezing and borrowing. +A subroutine that needs to duplicate an object is said to be an "argument consuming" subroutine. -```erg -capitalize s: Str! - s.capitalize!() +``` erg +capitalize s: Str!= + s. capitalize!() s -s1 = !" hello" +s1 = !"hello" s2 = capitalize s1.clone() -log s2, s1 # !" HELLO hello" +log s2, s1 # !"HELLO hello" ``` -## Freezing +## freeze -Taking advantage of the fact that immutable objects can be referenced from multiple places, a variable object is converted to an immutable object. -This is called freezing. Freezing is used to create iterators from mutable arrays. -Since iterators cannot be created directly from mutable arrays, they are converted to immutable arrays. -If you do not want to destroy the array, use the [`.freeze_map` method](./type/mut.md), etc. +We take advantage of the fact that immutable objects can be referenced from multiple places and convert mutable objects to immutable objects. +This is called freezing. Freezing is used, for example, when creating an iterator from a mutable array. +Since you can't create an iterator directly from a mutable array, convert it to an immutable array. +If you don't want to destroy the array, use the [`.freeze_map` method](./type/mut.md). -```erg -# Calculate the sum of the values produced by the iterator +``` erg +# Compute the sum of the values produced by the iterator sum|T <: Add + HasUnit| i: Iterator T = ... -x = [1, 2, 3].into [Int; !3]. +x = [1, 2, 3].into [Int; !3] x.push!(4) -i = x.iter() # TypeError: [Int; !4] has no method `iter`. +i = x.iter() # TypeError: [Int; !4] has no method `iter` y = x.freeze() i = y.iter() assert sum(i) == 10 -y # y is still touched after this. +y # y can still be touched ``` -## Borrowing +## borrow -Borrowing is less expensive than cloning or freezing. -Borrowing can be done in simple cases such as the following. +Borrowing is cheaper than duplicating or freezing. +Borrowing can be done in the following simple cases: -```erg +``` erg peek_str ref(s: Str!) = log s -s = !" hello" +s = !"hello" peek_str s ``` -The borrowed value is called a __reference__ to the original object. -You can "subloan" a reference to another subroutine, but you can't consume it because you are only borrowing it. +A borrowed value is called a __reference__ to the original object. +You can "sublease" the reference to another subroutine, but you cannot consume it because you are only borrowing it. -```erg -steal_str ref(s: Str!) =. - # The log function only borrows arguments, so it can subloan +``` erg +steal_str ref(s: Str!) = + # Since the log function only borrows the arguments, it can be sub-leased log s - # Discard function consumes arguments, so it is an error + # error because the discard function consumes arguments discard s # OwnershipError: cannot consume a borrowed value # hint: use `clone` method ``` -```erg +``` erg steal_str ref(s: Str!) = - # this is also no good (= consumes the right side) + # This is no good either (= consumes the right side) x = s # OwnershipError: cannot consume a borrowed value x ``` -Erg references are more restrictive than Rust. Although references are first-class objects in the language, they cannot be created explicitly and can only be specified as a way of passing real arguments by `ref`/`ref!`. -This means that it is not possible to pack references into arrays or create classes with references as attributes. +Erg's references are more restrictive than Rust's. References are first-class objects in the language, but cannot be created explicitly, they can only be specified as argument passing via `ref`/`ref!`. +This means that you cannot stuff references into arrays or create classes with references as attributes. -However, such restrictions are common in languages without references, so they are not that inconvenient. +However, such restrictions are a natural specification in languages without references in the first place, and they are not so inconvenient. -## Circular references +## circular references -Erg is designed to prevent unintentional memory leaks, and the memory checker will generate an error when it detects a circular reference. In most cases, this error can be resolved with a weak reference `Weak`. However, this does not allow the creation of objects with circular structures such as cyclic graphs, so we plan to implement an API that can create circular references as an unsafe operation. +Erg is designed to prevent unintentional memory leaks, and will issue an error if the memory checker detects a circular reference. In most cases, this error can be resolved with a weak reference `Weak`. However, since it is not possible to generate objects with circular structures such as cyclic graphs, we plan to implement an API that can generate circular references as unsafe operations. + \ No newline at end of file diff --git a/doc/EN/syntax/19_visibility.md b/doc/EN/syntax/19_visibility.md index 4c1fef53..e5ef1e80 100644 --- a/doc/EN/syntax/19_visibility.md +++ b/doc/EN/syntax/19_visibility.md @@ -1,56 +1,56 @@ # Visibility Erg variables have the concept of __visibility__. -All variables we have seen so far are called __private variables__. These are variables that are invisible to the outside world. -For example, a private variable defined in the `foo` module cannot be referenced from another module. +All the variables we've seen so far are called __private variables__. This is an externally invisible variable. +For example, a private variable defined in the `foo` module cannot be referenced by another module. -```erg +``` erg # foo.er x = "this is an invisible variable" ``` -```erg -# bar.er +``` erg +#bar.er foo = import "foo" foo.x # AttributeError: Module 'foo' has no attribute 'x' ('x' is private) ``` -In contrast, there is also a __public variable__, which can be referenced externally. +On the other hand, there are also __public variables__, which can be referenced from the outside. Public variables are defined with `.`. -```erg +``` erg # foo.er .x = "this is a visible variable" ``` -```erg -# bar.er +``` erg +#bar.er foo = import "foo" assert foo.x == "this is a visible variable" ``` -Private variables do not need to be marked with anything, but can be marked with `::` or `self::` (or `Self::` for types, etc.) to make them explicitly private. A module can also be `module::`. +You don't need to add anything to private variables, but you can also add `::` or `self::` (`Self::` for types etc.) to indicate that they are private. increase. It can also be `module::` if it is a module. -```erg +``` erg ::x = "this is an invisible variable" assert ::x == x -assert self::x == ::x +assert self ::x == ::x assert module::x == ::x ``` -In the context of mere sequential execution, private variables are almost synonymous with local variables. They can be referenced from inner scope. +In the context of purely sequential execution, private variables are almost synonymous with local variables. It can be referenced from the inner scope. -```erg +``` erg ::x = "this is a private variable" y = x + 1 # exactly module::x ``` -The `::` allows you to distinguish between variables with the same name in a scope. -Specify the scope of the variable you want to reference on the left. For the top level, specify `module`. -If not specified, the innermost variable is referenced as in the normal case. +By using `::`, you can distinguish variables with the same name within the scope. +Specify the scope of the variable you want to refer to on the left. Specify `module` for the top level. +If not specified, the innermost variable is referenced as usual. -```erg +``` erg ::x = 0 assert x == 0 y = @@ -64,38 +64,38 @@ y = assert module::x == 0 ``` -In the scope of an anonymous subroutine, `self` specifies its own scope. +In the anonymous subroutine scope, `self` specifies its own scope. -```erg +``` erg x = 0 f = x -> log module::x, self::x -f 1 # 0 1 +f1# 0 1 ``` `::` is also responsible for accessing private instance attributes. -```erg +``` erg x = 0 C = Class {x = Int} C. - # Top-level x is referenced (warns to make it module::x) + # Top-level x is referenced (warning to use module::x) f1 self = x - # x of instance attribute is referenced + # instance attribute x is referenced f2 self = self::x ``` ## Visibility in external modules -A class defined in one module can actually define methods from an external module as well. +A class defined in one module can actually define methods from an external module. -```erg -## foo.er +``` erg +# foo.er .Foo = Class() ``` -```erg -# bar.er +``` erg +#bar.er {Foo; ...} = import "foo" Foo:: @@ -109,45 +109,45 @@ Foo. foo::private() # AttributeError ``` -However, both of those methods can only be used within that module. -Externally defined private methods can be referenced by methods of the `Foo` class only within the defining module. -Public methods are exposed outside the class, but not to outside the module. +However, both of those methods are only available within that module. +Private methods defined externally are visible to methods of the `Foo` class only within the defining module. +Public methods are exposed outside the class, but not outside the module. -```erg -# baz.er. +``` erg +# baz.er {Foo; ...} = import "foo" foo = Foo.new() foo.public() # AttributeError: 'Foo' has no attribute 'public' ('public' is defined in module 'bar') ``` -Also, you cannot define a method on the type you are re-exporting. -This is to avoid confusion when a method is found or not found depending on the module from which it is imported. +Also, methods cannot be defined in the type to be re-exported. +This is to avoid confusion about methods being found or not found depending on the module they are imported from. -```erg -# bar.er +``` erg +#bar.er {.Foo; ...} = import "foo" .Foo:: private self = pass # Error -.Foo. - Foo:: public self = self::private() # Error +Foo. + public self = self::private() # Error ``` If you want to do something like this, define a [patch](./type/07_patch.md). -```erg -# bar.er. +``` erg +#bar.er {Foo; ...} = import "foo" FooImpl = Patch Foo -FooImpl:: +FooImpl :=: private self = pass -FooImpl. +Foo Impl. public self = self::private() ``` -```erg +``` erg # baz.er {Foo; ...} = import "foo" {FooImpl; ...} = import "bar" @@ -156,7 +156,7 @@ foo = Foo.new() foo.public() ``` -## Restricted Public Variables +## restricted public variables Variable visibility is not limited to complete public/private. You can also publish with restrictions. @@ -164,14 +164,14 @@ You can also publish with restrictions. ``` erg # foo.er .record = { - .a = { - .(.record)x = 0 - .(module)y = 0 - .z = 0 - } - _ = .a.x # OK - _ = .a.y # OK - _ = .a.z # OK + .a = { + .(.record)x = 0 + .(module)y = 0 + .z = 0 + } + _ = .a.x # OK + _ = .a.y # OK + _ = .a.z # OK } _ = .record.a.x # VisibilityError @@ -187,5 +187,5 @@ _ = foo.record.a.z # OK ``` + Previous | Next + \ No newline at end of file diff --git a/doc/EN/syntax/20_naming_rule.md b/doc/EN/syntax/20_naming_rule.md index f729d83e..dee0d1cf 100644 --- a/doc/EN/syntax/20_naming_rule.md +++ b/doc/EN/syntax/20_naming_rule.md @@ -1,38 +1,38 @@ -# Naming Conventions +# Naming convention -If a variable is to be used as a constant expression, it must begin with a capital letter. The second and succeeding letters may be in lowercase. +If you want to use a variable as a constant expression, make sure it starts with a capital letter. Two or more letters may be lowercase. -```erg +``` erg i: Option Type = Int match i: t: Type -> log "type" None -> log "None" ``` -Objects with side-effects must end with `!` must end with `!`. They are procedures, procedural methods, and mutable types. -However, the `Proc` type itself is not a mutable type. +Objects with side effects always end with `!`. Procedures and procedural methods, and mutable types. +However, the `Proc` type itself is not mutable. -```erg +``` erg # Callable == Func or Proc c: Callable = print! match c: - p! -> log "proc" # can omit `: Proc` since it is self-explanatory + p! -> log "proc" # `: Proc` can be omitted since it is self-explanatory f -> log "func" ``` -If you want to expose the attribute to the outside world, define it with `.`. `.` attribute is not prefixed, the attribute is not public. To avoid confusion, they cannot coexist in the same scope. +If you want to expose an attribute to the outside world, define it with `.` at the beginning. If you don't put `.` at the beginning, it will be private. To avoid confusion, they cannot coexist within the same scope. -```erg +``` erg o = {x = 1; .x = 2} # SyntaxError: private and public variables with the same name cannot coexist ``` ## Literal Identifiers -The above rule can be avoided by enclosing the string in single quotes (''). That is, a procedural object can also be assigned without `!`. In this case, however, even if the value is a constant expression, it is not considered a constant. -Such a string identifier enclosed in single quotes is called a literal identifier. -This is used when calling the API (FFI) of other languages such as Python. +The above rule can be circumvented by enclosing the string in single quotes (''). That is, procedural objects can also be assigned without `!`. However, in this case, even if the value is a constant expression, it is not considered a constant. +A character string enclosed in single quotes like this is called a literal identifier. +This is used when calling APIs (FFI) of other languages such as Python. -```erg +``` erg bar! = pyimport("foo").'bar' ``` @@ -40,11 +40,11 @@ Identifiers that are also valid in Erg do not need to be enclosed in ''. Furthermore, literal identifiers can contain both symbols and spaces, so strings that cannot normally be used as identifiers can be used as identifiers. -```erg +``` erg '∂/∂t' y 'test 1: pass x to y'() ``` + \ No newline at end of file diff --git a/doc/EN/syntax/21_lambda.md b/doc/EN/syntax/21_lambda.md index 67167106..08415e13 100644 --- a/doc/EN/syntax/21_lambda.md +++ b/doc/EN/syntax/21_lambda.md @@ -1,94 +1,95 @@ -# Anonymous Function +# anonymous function -An anonymous function is a syntax for creating function objects on the fly without naming them. +Anonymous functions are a syntax for creating function objects on the fly without naming them. -```erg -# `->` is the anonymous function operator +``` erg +# `->` is an anonymous function operator # same as `f x, y = x + y` f = (x, y) -> x + y # same as `g(x, y: Int): Int = x + y` g = (x, y: Int): Int -> x + y ``` -You can omit `()` if there is only one argument. +You can omit the `()` if there is only one argument. -```erg -assert [1, 2, 3].map_collect(i -> i + 1) == [2, 3, 4]. -assert ((i, j) -> [i, j])(1, 2) == [1, 2]. +``` erg +assert [1, 2, 3].map_collect(i -> i + 1) == [2, 3, 4] +assert ((i, j) -> [i, j])(1, 2) == [1, 2] ``` -In the case below `0..9, (i -> ...)`, not `(0..9, i) -> ...`. -`->` takes only one argument on the left side. Multiple arguments are taken as a single tuple. +In the case below it is `0..9, (i -> ...)` and not `(0..9, i) -> ...`. +`->` takes only one argument on the left side. Multiple arguments are received as a single tuple. -```erg +``` erg for 0..9, i: Int -> ... ``` -For anonymous functions, there is a difference in syntactic interpretation due to whitespace. +In anonymous functions, there is a difference in parsing due to whitespace. -```erg -# In this case, it is interpreted as ``T(() -> Int)``. -i: T () -> Int -# In this case, it is interpreted as (U()) -> Int +``` erg +# In this case, interpreted as `T(() -> Int)` +i: T() -> Int +# in this case it is interpreted as (U()) -> Int k: U() -> Int ``` -Anonymous functions can be used without arguments. `=>` is an anonymous procedure operator. +Anonymous functions can be used without arguments. -```erg -p!= () => print!"`p!` was called" -# `() ->`, `() =>` have the sugar-coated constructs `do`, `do!`. +``` erg +# `=>` is an anonymous procedure operator +p! = () => print! "`p!` was called" +# `() ->`, `() =>` have syntax sugar `do`, `do!` # p! = do! print! "`p!` was called" p!() # `p!` was called ``` -Argumentless functions can be used for lazy initialization. +No-argument functions can be used for lazy initialization. -```erg +``` erg time = import "time" date = import "datetime" now = if! True: - do! - time.sleep! + do!: + time. sleep! 1000 date.now!() do date.new("1970", "1", "1", "00", "00") ``` -Typing and pattern matching can also be done. For this reason, the ``match`` function is realized almost entirely by the power of anonymous functions. -The anonymous functions given as arguments to the ``match`` function are tried in order from the top. So, it is necessary to describe special cases at the top and more general cases as you go down. If you get the order wrong (as far as possible), the compiler will issue a Warning. +You can also type and pattern match. Because of this, the `match` function is mostly implemented with the power of anonymous functions. +Anonymous functions given as arguments to the `match` function are tried in order from the top. So, you should describe the special cases at the top and the more general cases at the bottom. If you get the order wrong, the compiler will issue a warning (if possible). -```erg -n = (Complex or Ratio or Int).sample! -i = match n: +``` erg +n = (Complex or Ratio or Int).sample!() +i = matchn: PI -> PI # if equal to constant PI - (i: 1..10) -> i # if 1~10 Int - (i: Int) -> i # for Int - (c: Complex) -> c.real() # case of Complex, Int < Complex, but can fall back - _ -> panic "cannot convert to Int" # none of the above; match must cover all patterns + For (i: 1..10) -> i # Int from 1 to 10 + (i: Int) -> i # Int + (c: Complex) -> c.real() # For Complex. Int < Complex, but can fallback + _ -> panic "cannot convert to Int" # If none of the above apply. match must cover all patterns ``` -Error handling can also be done using `?` or `match`. +Error handling is also generally done using `?` or `match`. -```erg +``` erg res: ParseResult Int -match res: +matchres: i: Int -> i err: Error -> panic err.msg res2: Result Int, Error match res2: - ok: Not Error -> log Typeof ok + ok: Not Error -> log Type of ok err: Error -> panic err.msg ``` -## Anonymous Polymorphic Function +## Anonymous polycorrelation coefficient -```erg +``` erg # same as id|T| x: T = x id = |T| x: T -> x ``` + \ No newline at end of file diff --git a/doc/EN/syntax/23_closure.md b/doc/EN/syntax/23_closure.md index 3d5040d9..52c6c917 100644 --- a/doc/EN/syntax/23_closure.md +++ b/doc/EN/syntax/23_closure.md @@ -1,32 +1,32 @@ # Closure -Erg subroutines have a "closure" feature that captures external variables. +Erg subroutines have a feature called a "closure" that captures external variables. -```erg +``` erg outer = 1 f x = outer + x assert f(1) == 2 ``` -Like immutable objects, mutable objects can also be captured. +As with immutable objects, mutable objects can also be captured. -```erg +``` erg sum = !0 for! 1..10, i => - sum.add! + sum.add!i assert sum == 45 -p! x = - sum.add! +p!x= + sum.add!x p!(1) assert sum == 46 ``` Note, however, that functions cannot capture mutable objects. -If mutable objects could be referenced in a function, the following code could be written. +If a mutable object can be referenced in a function, you can write code like the following. -```erg -# !!! This code is actually an error !!! +``` erg +# !!! This code actually gives an error !!! i = !0 f x = i + x assert f 1 == 1 @@ -34,31 +34,31 @@ i.add! 1 assert f 1 == 2 ``` -The function should return the same value for the same argument, but that assumption has been violated. -Note that ``i`` is evaluated for the first time at call time. +The function should return the same value for the same arguments, but the assumption is broken. +Note that `i` is evaluated only at call time. -If you want the contents of a mutable object at the time of the function definition, `.clone` it. +Call `.clone` if you want the contents of the mutable object at the time the function was defined. -```erg +``` erg i = !0 immut_i = i.clone().freeze() -f x = immut_i + x +fx = immut_i + x assert f 1 == 1 i.add! 1 assert f 1 == 1 ``` -## Avoiding Mutable States, Functional Programming +## avoid mutable state, functional programming -```erg -## Erg +``` erg +# Erg sum = !0 for! 1..10, i => - sum.add! + sum.add!i assert sum == 45 ``` -The equivalent program above can be written in Python as follows. +The equivalent program above can be written in Python as follows: ```python # Python @@ -68,29 +68,29 @@ for i in range(1, 10): assert sum == 45 ``` -However, Erg recommends a simpler way of writing. -Instead of using subroutines and mutable objects to carry around state, the style is to localize the state using functions. This is called functional programming. +However, Erg recommends a simpler notation. +Instead of carrying around state using subroutines and mutable objects, use a style of localizing state using functions. This is called functional programming. -```erg +``` erg # Functional style sum = (1..10).sum() assert sum == 45 ``` -The above code produces exactly the same result as the previous one, but it can be seen that this one is much simpler. +The code above gives exactly the same result as before, but you can see that this one is much simpler. -The `fold` function can be used to perform a variety of operations other than summing. +The `fold` function can be used to do more than sum. `fold` is an iterator method that executes the argument `f` for each iteration. -The initial value of the counter to accumulate the results is specified by `init` and accumulated in `acc`. +The initial value of the counter that accumulates results is specified in `init` and accumulated in `acc`. -```erg +``` erg # start with 0, result will sum = (1..10).fold(init: 0, f: (acc, i) -> acc + i) assert sum == 45 ``` -Erg is designed to be a natural and concise description of programming with invariant objects. +Erg is designed to be a natural succinct description of programming with immutable objects. + \ No newline at end of file diff --git a/doc/EN/syntax/24_module.md b/doc/EN/syntax/24_module.md index ba586185..2a7c92d9 100644 --- a/doc/EN/syntax/24_module.md +++ b/doc/EN/syntax/24_module.md @@ -39,4 +39,4 @@ Since module types are also record types, deconstruction assignment is possible. + \ No newline at end of file diff --git a/doc/EN/syntax/25_object_system.md b/doc/EN/syntax/25_object_system.md index 7b85ea6f..c02573ea 100644 --- a/doc/EN/syntax/25_object_system.md +++ b/doc/EN/syntax/25_object_system.md @@ -1,64 +1,68 @@ # Object -All data that can be assigned to a variable. The `Object` class has the following attributes. +All data that can be assigned to a variable. The attributes of the `Object` class are as follows. -* `. __repr__`: returns a (non-rich) string representation of the object. -* `. __sizeof__`: returns the size of the object (including heap allocation). -* `. __dir__`: return a list of attributes of the object. -* `. __hash__`: return the hash value of the object. -* `. __getattribute__`: retrieve and return an object's attributes * `. -* `.clone`: create and return a clone of an object (an independent entity in memory). -* `.copy`: return a copy of an object (identical in memory). +* `.__repr__`: Returns a (non-rich) string representation of the object +* `.__sizeof__`: Returns the size of the object (including heap allocation) +* `.__dir__`: Returns a list of object attributes +* `.__hash__`: returns the hash value of the object +* `.__getattribute__`: Get and return an attribute of an object +* `.clone`: Creates and returns a clone of an object (with an independent entity in memory) +* `.copy`: Returns a copy of the object (pointing to the same thing in memory) ## Record -An object created by a record literal (`{attr = value; ...}`). -This object can be a `.clone` or a `. __sizeof__` and other basic methods. +An object generated by a record literal (`{attr = value; ...}`). +This object has basic methods such as `.clone` and `.__sizeof__`. -```erg +``` erg obj = {.x = 1} assert obj.x == 1 -obj2 = {. .x; .y = 2} +obj2 = {...x; .y = 2} assert obj2.x == 1 and obj2.y == 2 ``` ## Attribute -An object associated with an object. In particular, a subroutine attribute that takes itself (`self`) as its implicit first argument is called a method. +An object associated with an object. In particular, a subroutine attribute that takes self (`self`) as its implicit first argument is called a method. -```erg -# Note that private_attr does not have `. Note that there is no `. +``` erg +# note that there is no `.` in private_attr record = {.public_attr = j; private_attr = 2; .method = self -> self.i + 1} -record.public_attr == 2 +record. public_attr == 2 record.private_attr # AttributeError: private_attr is private assert record.method() == 3 ``` ## Element -An object belonging to a specific type (e.g. `1` is an element of type `Int`). All objects are at least `{=}` type. -In the case of an element of a class, it is sometimes called an instance. +An object belonging to a particular type (e.g. `1` is an element of type `Int`). All objects are at least elements of type `{=}`. +Elements of classes are sometimes called instances. ## Subroutine -An object that is an instance of a function or procedure (including methods). The class representing a subroutine is `Subroutine`. -More generally, `.__call__` is called a `Callable`. +Indicates an object that is an instance of a function or procedure (including methods). The class representing a subroutine is `Subroutine`. +An object that implements `.__call__` is more commonly called a `Callable`. ## Callable -Object that implements `.__call__`. Superclass of `Subroutine`. +An object that implements `.__call__`. It is also the superclass of `Subroutine`. ## Type -An object that defines required attributes and makes objects common. -There are two main types: polymorphic type and monomorphic type. Typical monomorphic types are `Int`, `Str`, etc. Polymorphic types include `Option Int`, `[Int; 3]` and so on. -In addition, types that define methods to change the state of an object are called mutable types, and require variable attributes marked with `!` (e.g., dynamic arrays: `[T; !_]`). +An object that defines requirement attributes and commonizes objects. +There are two main types: Polymorphic Type and Monomorphic Type. Typical monomorphic types are `Int`, `Str`, etc., and polymorphic types are `Option Int`, `[Int; 3]`, etc. +Furthermore, a type that defines a method that changes the state of an object is called a Mutable type, and it is necessary to add `!` to the variable attribute (e.g. dynamic array: `[T; !_]`) . + +## Class + +A type that has `.__new__`, `.__init__` methods, etc. Implement class-based object orientation. ## Function -Subroutines that have read permission for external variables (excluding static variables) but do not have read/write permission for external variables. In other words, it has no external side effects. -Erg functions are defined differently than Python because they do not allow side effects. +A subroutine that has read permission for external variables (excluding static variables) but does not have read/write permission for external variables. In other words, it has no external side effects. +Erg functions are defined differently than Python's because they do not allow side effects. ## Procedure @@ -71,8 +75,8 @@ A subroutine that implicitly takes `self` as the first argument. It is a differe ## Entity Objects that are not subroutines and types. -Monomorphic entities (`1`, `"a"`, etc.) are also called value objects, and polymorphic entities (`[1, 2, 3], {"a": 1}`) are also called container objects. +Monomorphic entities (`1`, `"a"`, etc.) are also called value objects, polymorphic entities (`[1, 2, 3], {"a": 1}`) are also called container objects . + \ No newline at end of file diff --git a/doc/EN/syntax/26_pattern_matching.md b/doc/EN/syntax/26_pattern_matching.md index 80819de2..8539689e 100644 --- a/doc/EN/syntax/26_pattern_matching.md +++ b/doc/EN/syntax/26_pattern_matching.md @@ -1,52 +1,56 @@ -# Pattern matching, Irrefutability +# pattern matching, refutable -## Patterns Available in Erg +## Patterns available in Erg -### Variable Pattern +### variable pattern -```erg -# basic assignment +``` erg +# basic assignments i = 1 # with type i: Int = 1 # with anonymous type i: {1, 2, 3} = 2 -# function + +# functions fn x = x + 1 # equals fn x: Add(Int) = x + 1 # (anonymous) function fn = x -> x + 1 fn: Int -> Int = x -> x + 1 + # higher-order type a: [Int; 4] = [0, 1, 2, 3] # or -a: Array Int, 4 = [0, 1, 2, 3] # or +a: Array Int, 4 = [0, 1, 2, 3] ``` -### Literal Pattern +### Literal patterns -```erg -# if `i` cannot be determined to be 1 at compile time, TypeError occurs. -# short hand of `_: {1} = i` +``` erg +# Raise a TypeError if `i` cannot be determined to be 1 at compile time. +# omit `_: {1} = i` 1 = i + # simple pattern matching match x: 1 -> "1" 2 -> "2" _ -> "other" + # fibonacci function -fib 0 = 0 -fib 1 = 1 -fib n: Nat = fib n-1 + fib n-2 +fib0 = 0 +fib1 = 1 +fibn: Nat = fibn-1 + fibn-2 ``` -### Constant Pattern +### constant pattern -```erg -cond = False +``` erg +cond=False match! cond: - True => print! + True => print! "cond is True" _ => print! "cond is False" PI = 3.141592653589793 @@ -58,61 +62,61 @@ name = match num: _ -> "unnamed" ``` -### Refinement Pattern +### Sieve pattern -```erg +``` erg +# these two are the same Array(T, N: {N | N >= 3}) -# == == Array(T, N | N >= 3) f M, N | M >= 0, N >= 1 = ... f(1, 0) # TypeError: N (2nd parameter) must be 1 or more ``` -### Discard (Wildcard) Pattern +### discard (wildcard) pattern -```erg +``` erg _ = 1 _: Int = 1 -zero _ = 0 +zero_ = 0 right(_, r) = r ``` -### Varargs Patterns +### Variable length patterns -Used in combination with the tuple/array/record pattern described below. +It is used in combination with the tuple/array/record pattern described later. -```erg -[i, . .j] = [1, 2, 3, 4] -assert j == [2, 3, 4]. +``` erg +[i,...j] = [1, 2, 3, 4] +assert j == [2, 3, 4] first|T|(fst: T, ...rest: T) = fst assert first(1, 2, 3) == 1 ``` -### Tuple Pattern +### Tuple pattern -```erg +``` erg (i, j) = (1, 2) ((k, l), _) = ((1, 2), (3, 4)) -# () can be omitted if not nested (1, 2 are treated as (1, 2)) +# If not nested, () can be omitted (1, 2 are treated as (1, 2)) m, n = 1, 2 f(x, y) = ... ``` -### Array Pattern +### array pattern -```erg +``` erg [i, j] = [1, 2] [[k, l], _] = [[1, 2], [3, 4]] -length [] = 0 -length [_, . .rest] = 1 + length rest +length[] = 0 +length[_, ...rest] = 1 + lengthrest ``` -### Record Pattern +#### record pattern -```erg +``` erg record = {i = 1; j = 2; k = 3} {j; ...} = record # i, k will be freed @@ -127,9 +131,9 @@ age = match person: f {x: Int; y: Int} = ... ``` -### Data Class Pattern +### Data class pattern -```erg +``` erg Point = Inherit {x = Int; y = Int} p = Point::{x = 1; y = 2} Point::{x; y} = p @@ -144,46 +148,46 @@ List T. _ -> ... second self = match self: - Cons::{rest=Cons::{head; ...} ; ...} -> head + Cons::{rest=Cons::{head; ...}; ...} -> head _ -> ... ``` -### Enumeration Pattern +### enumeration pattern -* actually just an enumerated type +*Actually, it's just an enumeration type -```erg +``` erg match x: i: {1, 2} -> "one or two: {i}" _ -> "other" ``` -### Range Pattern +### range pattern -* actually just an interval type +*Actually, it is just an interval type. -```erg +``` erg # 0 < i < 1 -i: 0<... <1 = 0.5 +i: 0<..<1 = 0.5 # 1 < j <= 2 -_: {[I, J] | I, J: 1<. .2} = [1, 2] +_: {[I, J] | I, J: 1<..2} = [1, 2] # 1 <= i <= 5 match i i: 1..5 -> ... ``` -### Non-patterns and Non-patternable Items +### Things that aren't patterns, things that can't be patterned -A pattern is something that can be uniquely specified. In this respect, pattern matching differs from ordinary conditional branching. +A pattern is something that can be uniquely specified. In this respect pattern matching differs from ordinary conditional branching. -The specification of a condition is not unique. For example, to determine whether the number `n` is even, the orthodox way is `n % 2 == 0`, but it can also be written as `(n / 2).round() == n / 2`. -The non-unique form is non-trivial, whether it works correctly or is equivalent to another condition. +Condition specifications are not unique. For example, to check if the number `n` is even, the orthodox is `n % 2 == 0`, but you can also write `(n / 2).round() == n / 2`. +A non-unique form is not trivial whether it works correctly or is equivalent to another condition. -#### Set +#### set -There is no pattern for sets. There is no pattern for sets because there is no way to retrieve elements uniquely. -They can be retrieved with an iterator, but the order is not guaranteed. +There is no set pattern. Because the set has no way to uniquely retrieve the elements. +You can retrieve them by iterator, but the order is not guaranteed. + \ No newline at end of file diff --git a/doc/EN/syntax/27_comprehension.md b/doc/EN/syntax/27_comprehension.md index 91a9a4b5..bd4ea15b 100644 --- a/doc/EN/syntax/27_comprehension.md +++ b/doc/EN/syntax/27_comprehension.md @@ -1,56 +1,65 @@ # Comprehension -An array can be created by `[expr | (name <- iterable)+ (predicate)*]`, -And a set can be created by `{expr | (name <- iterable)+ (predicate)*}`. +Array with `[expr | (name <- iterable)+ (predicate)*]`, +set with `{expr | (name <- iterable)+ (predicate)*}`, +You can create a Dict with `{key: value | (name <- iterable)+ (predicate)*}`. -Dict can be created by `{key: value | (name <- iterable)+ (predicate)*}`. +The first part of the clauses separated by `|` is called the layout clause (location clause), the second part is called the bind clause (binding clause), and the third part is called the guard clause (conditional clause). +A guard clause can be omitted, but a bind clause cannot be omitted, and a guard clause cannot precede a bind clause. -The first part of a clause delimited by `|` is called a layout clause, the second part is called a bind clause, and the third part is called a guard clause. -The guard clause can be omitted, but not the bind clause, and the guard clause cannot be placed before the bind clause. +Comprehension example -e.g. +``` erg +# the layout clause is i +# bind clause is i <- [0, 1, 2] +assert [i | i <- [0, 1, 2]] == [0, 1, 2] -```erg -assert [i | i <- [0, 1, 2]] == [0, 1, 2]] -assert [i / 2 | i <- 0..2] == [0.0, 0.5, 1.0]] +# layout clause is i / 2 +# bind clause is i <- 0..2 +assert [i/2 | i <- 0..2] == [0.0, 0.5, 1.0] + +# layout clause is (i, j) +# bind clause i <- 0..2, j <- 0..2 +# guard clause is (i + j) % 2 == 0 assert [(i, j) | i <- 0..2; j <- 0..2; (i + j) % 2 == 0] == [(0, 0), (0, 2), (1, 1), (2, 0), (2, 2)] + assert {i % 2 | i <- 0..9} == {0, 1} assert {k: v | k <- ["a", "b"]; v <- [1, 2]} == {"a": 1, "b": 2} ``` -Erg's comprehension notation is influenced by Haskell, but there are some differences. -In Haskell's list comprehensions, the order of variables makes a difference in the result, but not in Erg. +Erg comprehensions are inspired by Haskell, but with some differences. +For Haskell list comprehensions, the order of variables makes a difference in the result, but in Erg it doesn't matter. -```haskell +``` haskell -- Haskell -[(i, j) | i <- [1..3], j <- [3..5]] == [(1,3),(1,4),(1,5),(2,3),(2,4),(2,5),(3,3),(3,4),(3,5)] -[(i, j) | j <- [3..5], i <- [1..3]] == [(1,3),(2,3),(3,3),(1,4),(2,4),(3,4),(1,5),(2,5),(3,5)] +[(i, j) | i <- [1..3], j <- [3..5]] == [(1,3),(1,4),(1,5),(2 ,3),(2,4),(2,5),(3,3),(3,4),(3,5)] +[(i, j) | j <- [3..5], i <- [1..3]] == [(1,3),(2,3),(3,3),(1 ,4),(2,4),(3,4),(1,5),(2,5),(3,5)] ``` -```erg +``` erg # Erg -assert [(i, j) | i <- 1. <3; j <- 3.. <5] == [(i, j) | j <- 3.. <5; i <- 1.. <3] +assert [(i, j) | i <- 1..<3; j <- 3..<5] == [(i, j) | j <- 3..<5; i <- 1.. <3] ``` -これはPythonと同じである。 +This specification is the same as that of Python. ```python # Python assert [(i, j) for i in range(1, 3) for j in range(3, 5)] == [(i, j) for j in range(3, 5) for i in range(1, 3)] ``` -## Refinement type +## Sieve type -Similar to comprehensions are refinement types. A refinement type is a type (enumerated type) in the form `{Name: Type | Predicate}`. -In the case of a refinement type, Name is limited to one and the layout cannot be specified (but multiple values can be handled by using a tuple type, for example), and Predicate must be a compile-time computation, i.e., a constant expression. +Similar to comprehensions are sieve types. A sieve type is a type (enumerated type) created in the form `{Name: Type | Predicate}`. +In the case of the sieve type, only one Name can be specified and the layout cannot be specified (however, multiple values can be handled if it is a tuple type), and the Predicate can be calculated at compile time, that is, only a constant expression can be specified. -```erg +``` erg Nat = {I: Int | I >= 0} -# If the predicate expression is and only, it can be replaced by ;. +# If the predicate expression is only and, it can be replaced with ; # Nat2D = {(I, J): (Int, Int) | I >= 0; J >= 0} Nat2D = {(I, J): (Int, Int) | I >= 0 and J >= 0} ``` + \ No newline at end of file diff --git a/doc/EN/syntax/28_spread_syntax.md b/doc/EN/syntax/28_spread_syntax.md index 74f54a12..aed87510 100644 --- a/doc/EN/syntax/28_spread_syntax.md +++ b/doc/EN/syntax/28_spread_syntax.md @@ -1,42 +1,42 @@ # Spread assignment -In a spread assignment, a variable can be prefixed with `...` in front of the variable, all the remaining elements can be expanded into the variable. This is called a spread assignment. +In a decomposing assignment, putting `...` in front of a variable expands all remaining elements into that variable. This is called expansion assignment. -```erg -[x, ... .y] = [1, 2, 3] +``` erg +[x,...y] = [1, 2, 3] assert x == 1 -assert y == [2, 3]. -x, ... .y = (1, 2, 3) +assert y == [2, 3] +x, ...y = (1, 2, 3) assert x == 1 assert y == (2, 3) ``` ## Extract assignment -If nothing is written after `...`, the remaining elements are ignored and an assignment is made. This type of expansion assignment is specifically called an extract assignment. -Extract assignment is a useful syntax for bringing certain attributes local to a module or record. +If nothing is written after `...`, the remaining elements are ignored and assigned. This type of expansion assignment is specifically called extractive assignment. +Extraction assignment is a convenient syntax for localizing specific attributes within a module or record. -```erg -{sin; cos; tan; ...} = import "math" +``` erg +{sin; cos; tan; ..} = import "math" ``` -This way, `sin`, `cos`, `tan` can be used locally from then on. +After that, you can use `sin, cos, tan` locally. You can do the same with records. -```erg +``` erg record = {x = 1; y = 2} {x; y; ...} = record ``` -If you want to expand all of them, use `{*} = record`, this is equivalent to `open` in OCaml and so on. +If you want to expand all, use `{*} = record`. It is `open` in OCaml. -```erg +``` erg record = {x = 1; y = 2} -{*} = record +{*} = records assert x == 1 and y == 2 ``` + \ No newline at end of file diff --git a/doc/EN/syntax/29_decorator.md b/doc/EN/syntax/29_decorator.md index 2e1889eb..a5ed389c 100644 --- a/doc/EN/syntax/29_decorator.md +++ b/doc/EN/syntax/29_decorator.md @@ -1,82 +1,81 @@ -# Decorator +# decorator (modifier) -Decorators are used to add or make explicit a specific state or behavior for a type or function. -The syntax for decorators is as follows. +Decorators are used to add or demonstrate a particular state or behavior to a type or function. +The syntax of the decorator is as follows. -```erg +``` erg @deco -X = ... +X=... ``` -There can be more than one decorator, as long as they do not conflict. +You can have multiple decorators as long as they don't conflict. -A decorator is not a special object; its entity is simply a single-argument function. A decorator is equivalent to the following pseudo code. +A decorator is not a special object, it's just a one-argument function. The decorator is equivalent to the following pseudocode. -```erg -X = ... +``` erg +X=... X = deco(X) ``` -Erg does not allow reassignment of variables, so the above code will not pass. -For a simple variable, `X = deco(...)` is the same, but for instant blocks and subroutines, you can't do that, so you need decorators. +Erg doesn't allow reassignment of variables, so code like the one above won't work. +For simple variables it's the same as `X = deco(...)`, but for instant blocks and subroutines you can't do that, so you need a decorator. -```erg +``` erg @deco -f x = ... +f x = y = ... x + y -# Can also prevent code from going horizontal. +# You can also prevent the code from becoming horizontal @LongNameDeco1 @LongNameDeco2 -C = Class ... +C = Class... ``` -Here are some frequently used built-in decorators. +Below are some frequently used built-in decorators. ## Inheritable -Indicates that the type being defined is an inheritable class. If the `scope` argument is set to `"public"`, the class can be inherited by classes in external modules. By default, it is `"private"` and cannot be inherited from outside. +Indicates that the defining type is an inheritable class. If you specify `"public"` for the argument `scope`, it will be possible to inherit even the class of the external module. By default it is `"private"` and cannot be inherited externally. -## Final +##Final -disables overriding the `"final"` method. If you attach it to a class, it becomes a non-inheritable class, but since it is the default, it is meaningless. +Make the method non-overridable. Adding it to a class makes it a non-inheritable class, but since it's the default it doesn't make sense. ## Override -Use to override an attribute, which by default Erg will fail if you try to define an attribute that is the same as the base class. +Used when overriding attributes. By default, Erg will throw an error if you try to define the same attribute as the base class. ## Impl -Indicates implementation of traits. +Indicates that the argument trait is implemented. -```erg -ClosedAdd = Trait { - . `_+_` = Self.(Self) -> Self +``` erg +Add = Trait { + .`_+_` = Self.(Self) -> Self } -ClosedSub = Trait { - . `_-_` = Self.(Self) -> Self +Sub = Trait { + .`_-_` = Self.(Self) -> Self } -C = Class {i = Int} +C = Class({i = Int}, Impl := Add and Sub) C. - @Impl ClosedAdd + @Impl Add `_+_` self, other = C.new {i = self::i + other::i} - @Impl ClosedSub + @Impl Sub `_-_` self, other = C.new {i = self::i - other::} ``` ## Attach Specifies the attachment patch that comes with the trait by default. -This allows you to reproduce the same behavior as the Rust trait. +This allows you to reproduce the same behavior as Rust traits. -```erg +``` erg # foo.er - Add R = Trait { - .`_+_` = Self.(R) -> Self.AddO .AddO = Type + .`_+_` = Self.(R) -> Self.AddO } @Attach AddForInt, AddForOdd ClosedAdd = Subsume Add(Self) @@ -87,35 +86,35 @@ AddForOdd = Patch(Odd, Impl := ClosedAdd) AddForOdd.AddO = Even ``` -This way, when you import traits from other modules, the attachment patch is automatically applied. +This will automatically apply the attachment patch when importing traits from other modules. -```erg -# Originally IntIsBinAdd, OddIsBinAdd must be imported at the same time, but can be omitted with attachment patch +``` erg +# Originally, IntIsBinAdd and OddIsBinAdd should be imported at the same time, but if it's an attachment patch, you can omit it {BinAdd; ...} = import "foo" -assert Int.AddO == Int +assert Int. AddO == Int assert Odd.AddO == Even ``` -Internally, they are only connected together using the trait's `.attach` method. If there is a conflict, it can be removed using the trait's `.detach` method. +Internally it's just attached using the trait's `.attach` method. Conflicts can be removed with the trait's `.detach` method. -```erg +``` erg @Attach X -T = Trait ... -assert X in T.attaches +T = Trait... +assert X in T. attaches U = T.detach(X).attach(Y) -assert X not in U.attaches -assert Y in U.attaches +assert X not in U. attaches +assert Y in U. attaches ``` -## Deprecated +##Deprecated -Indicates that the variable is outdated and deprecated. +Indicates that the variable specification is obsolete and deprecated. ## Test -Indicates a subroutine for tests. Test subroutines are executed with the `erg test` command. +Indicates that this is a test subroutine. Test subroutines are run with the `erg test` command. + \ No newline at end of file diff --git a/doc/EN/syntax/30_error_handling.md b/doc/EN/syntax/30_error_handling.md index 1a45a675..c67e363a 100644 --- a/doc/EN/syntax/30_error_handling.md +++ b/doc/EN/syntax/30_error_handling.md @@ -1,22 +1,22 @@ -# Error Handling +# error handling system -Mainly uses Result type. -Erg will throw away Error type objects (not supported at top level). +Mainly use Result type. +In Erg, an error occurs if you throw away an Error type object (not supported at the top level). -## Exceptions, Interoperation with Python +## Exceptions, interop with Python -Erg does not have an exception mechanism (Exception). +Erg does not have an exception mechanism (Exception). When importing a Python function -* Set the return value as `T or Error` type. -* set the return value to `T or Panic` type (which may raise an error at runtime). +* Set return value to `T or Error` type +* `T or Panic` type (may cause runtime error) -The latter is the default for `pyimport`. If you want to import as the former, use -If you want to import as the former, specify `Error` in `pyimport`'s `exception_type` (`exception_type: {Error, Panic}`). +There are two options, `pyimport` defaults to the latter. If you want to import as the former, use +Specify `Error` in `pyimport` `exception_type` (`exception_type: {Error, Panic}`). ## Exceptions and Result types -The `Result` type represents a value that may be an error. Error handling with `Result` is superior to the exception mechanism in several ways. -First, you can tell from the type definition that a subroutine may raise an error, and it is obvious when you actually use it. +The `Result` type represents values that may be errors. Error handling with `Result` is superior to the exception mechanism in several ways. +First of all, it's obvious from the type definition that the subroutine might throw an error, and it's also obvious when you actually use it. ```python # Python @@ -28,31 +28,31 @@ except e: print(e) ``` -In the above example, it is not clear from the code alone which function sends the exception. Even going back to the function definition, it is difficult to determine if the function raises the exception. +In the above example, it is not possible to tell from this code alone which function raised the exception. Even going back to the function definition, it's hard to tell if the function throws an exception. -```erg +``` erg # Erg -try! - do! - x = foo!()? .bar()? - y = baz! +try!: + do!: + x = foo!()?.bar() + y = baz!() qux!()? e => - print! + print! e ``` -On the flip side, we can see that `foo!` and `qux!` can produce errors in this example. -To be precise, `y` could also be of type `Result`, but we will have to deal with that eventually in order to use the values inside. +On the other hand, in this example we can see that `foo!` and `qux!` can raise an error. +Precisely `y` could also be of type `Result`, but you'll have to deal with it eventually to use the value inside. -That is not the only advantage of using the `Result` type. The `Result` type is also thread-safe. This means that error information can be passed around (easily) during parallel execution. +The benefits of using the `Result` type don't stop there. The `Result` type is also thread-safe. This means that error information can be (easily) passed between parallel executions. ## Context -Unlike exceptions, the `Error`/`Result` types by themselves do not have side-effects, so they do not have context, but the `.context` method can be used to add information to the `Error` object. The `.context` method is a type of method that creates a new `Error` object by consuming the `Error` object itself. It is chainable and can hold multiple contexts. +Since the `Error`/`Result` type alone does not cause side effects, unlike exceptions, it cannot have information such as the sending location (Context), but if you use the `.context` method, you can put information in the `Error` object. can be added. The `.context` method is a type of method that consumes the `Error` object itself and creates a new `Error` object. They are chainable and can hold multiple contexts. -```erg +``` erg f() = - todo() \f} + todo() \ .context "to be implemented in ver 1.2" \ .context "and more hints ..." @@ -62,23 +62,22 @@ f() # hint: and more hints ... ``` -Note that `Error` attributes such as `.msg`, `.kind`, etc., are not secondary and are not context and cannot be overwritten as they were when they were first generated. +Note that `Error` attributes such as `.msg` and `.kind` are not secondary, so they are not context and cannot be overridden as they were originally created. -## Stack Trace +## Stack trace -The `Result` type has been adopted by many other languages because of its convenience, but it has the disadvantage that the source of the error is harder to identify than the exception mechanism. -Therefore, Erg has an attribute `.stack` on the `Error` object to reproduce a pseudo-exception mechanism-like stack trace. - -`.stack` is an array of caller objects. Each time an Error object is `return`ed (including by `?`) it stacks its calling subroutine on the `.stack`. +The `Result` type is often used in other languages because of its convenience, but it has the disadvantage of making it difficult to understand the source of an error compared to the exception mechanism. +Therefore, in Erg, the `Error` object has an attribute called `.stack`, and reproduces a pseudo-exception mechanism-like stack trace. +`.stack` is an array of caller objects. Each time an Error object is `returned` (including by `?`) it pushes its calling subroutine onto the `.stack`. And if it is `?`ed or `.unwrap`ed in a context where `return` is not possible, it will panic with a traceback. -```erg +``` erg f x = ... y = foo.try_some(x)? ... -g x = ... +g x = y = f(x)? ... @@ -89,22 +88,22 @@ i = g(1)? # 10 | y = foo.try_some(x)? # module::f, line 23, file "foo.er" # 23 | y = f(x)? -# module::g, line 40, file "foo.er"? +# module::g, line 40, file "foo.er" # 40 | i = g(1)? # Error: ... ``` ## Panic -Erg also has a mechanism called __panicking__ to deal with unrecoverable errors. -Unrecoverable errors are errors caused by external factors such as software/hardware malfunctions, errors that are so fatal that it makes no sense to continue executing the code, or errors that the programmer did not anticipate. When such an error occurs, the program is terminated on the spot because it cannot be restored to the normal system through the programmer's efforts. This is called "panicking". +Erg also has a mechanism for dealing with unrecoverable errors called __panicing__. +An unrecoverable error is an error caused by an external factor such as a software/hardware malfunction, an error so fatal that it makes no sense to continue executing the code, or an error unexpected by the programmer. Etc. If this happens, the program will be terminated immediately, because the programmer's efforts cannot restore normal operation. This is called "panicing". -Panicking is done with the `panic` function. +Panic is done with the `panic` function. -```erg +``` erg panic "something went wrong!" ``` + \ No newline at end of file diff --git a/doc/EN/syntax/31_pipeline.md b/doc/EN/syntax/31_pipeline.md index 10ae5ace..652f756d 100644 --- a/doc/EN/syntax/31_pipeline.md +++ b/doc/EN/syntax/31_pipeline.md @@ -1,6 +1,6 @@ -# Pipeline Operator +# pipeline operator -The pipeline operator is used like this: +Pipeline operators are used like this: ``` erg assert f(g(x)) == (x |> g |> f) @@ -8,17 +8,20 @@ assert f(g(x, y)) == ((x, y) |> g |> f) ``` In other words, the order `Callable(object)` can be changed to `object |> Callable`. -Pipeline operators can also be used on methods. For methods, `object.method(args)` changes to `object |>.method(args)`. -It looks like just an increase in `|>`, but since the bond strength is low, the amount of `()` may be reduced. +The pipeline operator can also be used on methods. For methods, `object.method(args)` changes to `object |>.method(args)`. +It looks like just more `|>`, but since the bond strength is low, you may be able to reduce the amount of `()`. ``` erg rand = -1.0..1.0 |>.sample!() log rand # 0.2597... + 1+1*2 |>.times do log("a", end := "") # aaa -# without `|>`, the following will be `evens = (1..100).iter().filter(i -> i % 2 == 0).collect(Array)` + evens = 1..100 |>.iter |>.filter i -> i % 2 == 0 |>.collect Array +# When implemented without the pipeline operator, +_evens = (1..100).iter().filter(i -> i % 2 == 0).collect(Array) # or -_evens = 1..100\ +__evens = 1..100 \ .iter() \ .filter i -> i % 2 == 0 \ .collect Array @@ -26,4 +29,4 @@ _evens = 1..100\ + \ No newline at end of file diff --git a/doc/EN/syntax/container_ownership.md b/doc/EN/syntax/container_ownership.md new file mode 100644 index 00000000..3067bb35 --- /dev/null +++ b/doc/EN/syntax/container_ownership.md @@ -0,0 +1,42 @@ +# Subscript (index access) + +`[]` is different from normal methods. + +``` erg +a = [!1, !2] +a[0].inc!() +assert a == [2, 2] +``` + +Recall that the return value of a subroutine cannot be a reference. +The type of `a[0]` here should clearly be `Ref!(Int!)` (the type of `a[0]` depends on the context). +So `[]` is actually part of a special syntax, just like `.`. Unlike Python, it cannot be overloaded. +It is also not possible to reproduce the behavior of `[]` in a method. + +``` erg +C = Class {i = Int!} +C. get(ref self) = + self::i # TypeError: `self::i` is `Int!` (require ownership) but `get` doesn't own `self` +C.steal(self) = + self::i +#NG +C.new({i = 1}).steal().inc!() # OwnershipWarning: `C.new({i = 1}).steal()` is not owned by anyone +# hint: assign to a variable or use `uwn_do!` +# OK (assigning) +c = C.new({i = 1}) +i = c.steal() +i.inc!() +assert i == 2 +# or (own_do!) +own_do! C.new({i = 1}).steal(), i => i.inc!() +``` + +Also, `[]` can be disowned, but the element is not shifted. + +``` erg +a = [!1, !2] +i = a[0] +i.inc!() +assert a[1] == 2 +a[0] # OwnershipError: `a[0]` is moved to `i` +``` \ No newline at end of file diff --git a/doc/EN/syntax/grammar.txt b/doc/EN/syntax/grammar.txt index deaff920..d9dbbb2a 100644 --- a/doc/EN/syntax/grammar.txt +++ b/doc/EN/syntax/grammar.txt @@ -76,7 +76,7 @@ record ::= '{' '=' '}' set ::= '{' '}' | '{' expr (',' expr)* ','? '}' dict ::= '{' ':' '}' - | '{' symbol ':' expr (',' symbol ':' expr)* ','? '}' + | '{' expr ':' expr (',' expr ':' expr)* ','? '}' tuple ::= '(' ')' | '(' expr (',' expr)* ','? ')' indent ::= /* ... */ diff --git a/doc/EN/syntax/indexes.md b/doc/EN/syntax/indexes.md index fb591da9..9a530a07 100644 --- a/doc/EN/syntax/indexes.md +++ b/doc/EN/syntax/indexes.md @@ -1,14 +1,14 @@ -# Index +# index -For APIs not in this index, see [here](./API/index.md). -For the meaning of terms, see [here](./dev_guide/terms.md) for the meaning of terms. +See [here](../API/index.md) for APIs not in this index. +See [here](../dev_guide/terms.md) for terminology. -## Symbols +## symbol * ! - * !-type → [Mutable type](./type/mut.md) + * !-type → [mutable type](./type/mut.md) * [#](./00_basic.md/#comment) -* $ +*$ * % * & * && @@ -16,18 +16,18 @@ For the meaning of terms, see [here](./dev_guide/terms.md) for the meaning of te * () * * * [*-less multiplication](./01_literal.md/#less-multiplication) -* + (unary) - * +_ → + (unary) -* + (binary) +* + (prefix) + * +_ → + (prefix) +* + (infix) * , -* − (unary) - * −_ → − (unary) -* − (binary) +* − (prefix) + * −_ → − (prefix) +* − (infix) * −> * . → [Visibility] * / * : - * :] + * :: → [visibility] * ; * < * <: @@ -46,9 +46,9 @@ For the meaning of terms, see [here](./dev_guide/terms.md) for the meaning of te * ^ * ^^ * _ - * _+_ → + (binary) - * _-_ → − (binary) -* `` + * _+_ → + (infix) + * _-_ → − (infix) +*`` * {} * {} type * {:} @@ -58,7 +58,7 @@ For the meaning of terms, see [here](./dev_guide/terms.md) for the meaning of te * || * ~ -## Alphabet +## alphabet ### A @@ -68,7 +68,7 @@ For the meaning of terms, see [here](./dev_guide/terms.md) for the meaning of te * [assert] * [attribute] -### B +###B * [Base] * [Bool] @@ -77,24 +77,24 @@ For the meaning of terms, see [here](./dev_guide/terms.md) for the meaning of te * [Class] -### D +###D -* Deprecated +*Deprecated * [distinct] -### E +###E * [enum type] -* [Eq] -* [Erg] +*[Eq] +*[Erg] -### F +###F -* [for] +*[for] -### G +###G -### H +###H ### I @@ -103,74 +103,350 @@ For the meaning of terms, see [here](./dev_guide/terms.md) for the meaning of te * [in] * [Int] -### J +###J -### K +###K ### L -* let-polymorphism → [rank-1 polymorphism] +* let-polymorphism → [rank 1 polymorphism] * [log] -### M +###M * [match] -### N +###N -* [Nat] +*[Nat] * Never -* None -* None -* [Not] +*None +*None +*[Not] * [not] -### O +###O * [Option] * [Or] * [or] -* [Ord] +*[Ord] -### P +###P * panic * [print!](./../API/procs.md#print) * [Python] -### Q +###Q ### R * ref -* ref! +*ref! * [Result] -* [rootobj] +*[rootobj] -### S +###S -* self +*self * [Self](./type/special.md) * [side-effect](./07_side_effect.md) -* [Str] +*[Str] -### T +###T -* Trait +* Traits * [True] * [Type] * [type] -### U +###U -### V +###V ### W * [while!] -### X +###X -### Y +###Y -### Z +###Z + +## A line + +* [Assertion] +* value object +* [Attachment patch](./29_decorator.md#attach) +* Ad-hoc polymorphism → [No overloading](./type/overloading.md) +* Attribute → [Attribute] +* arity +* [dependent type](./type/dependent_type.md) +* immutable → [immutable] +* Argument → [Argument] +* instance +* [instant block](./00_basic.md# expression separator) +* index +* [indent](./00_basic.md#indent) +* alias +* error + * [Error handling] +* [operator](./06_operator.md) + * [operator binding strength] +* Override +* [No overloading](./type/overloading.md) +* Offside rule → [indent](./00_basic.md#indent) +* [object] + * Object-orientation +* Operand → [operand](./06_operator.md) +* operator → [operator](./06_operator.md) + +## Ka line + +* [Kind](./type/advanced/kind.md) +* [Visibility] +* [type] + * [type specification] + * [type erasure](./type/advanced/erasure.md) + * [type inference] + * [type annotation](./type/conv_type.md) + * [type argument] + * [type addition](./type/advanced/erasure.md) + * [type variable](./type/type_variable.md) + * [type constraint] +* [Guard] +* Encapsulation +* [variable] + * [mutable object] + * [variable] + * [variable reference] + * [variable array] + * [variable arguments] +* [function](./04_function.md) + * [Functional programming] (./23_scope.md#Avoiding mutable state Functional programming) +* base type +* Signed + * [Named type] → [Class](./type/04_class.md) + * [Annunciation] + * [nominal subtype](./type/05_nst_vs_sst.md) +* Capture → [Closure] +* [covariant] +* [keyword argument] +* empty set → [{}] +* section + * [Interval type](./type/11_interval.md) + * interval operator +* built-in + * [Built-in type] + * [Built-in functions](./05_builtin_funcs.md) + * [Built-in procedures](./09_builtin_procs.md) +* [class](./type/04_class.md) +* [Closure] +* [global variables] +* [Clone] +* [Inheritance](./type/07_inheritance.md) +* high floor + * [Advanced kind](./type/advanced/kind.md) + * higher order type + * Higher-order functions +* [public variable] +* [structural subtype] +* ~~backreference~~ → [backreference] +* [copy] +* comment +* [Collection](./10_array.md) +* colon → [:] +* [constructor](./type/04_class.md) +* container +* Compiler +* [compile-time calculation](./04_function.md#compile-time function) +* Comma → [,] + +## sa line + +* recursion + * recursive + * [Recursive function](./04_function.md#Recursive function) +* subscript → [index] +* [Subtyping Polymorphism](./type/overloading.md) +* Subroutine +* [reference] (./18_memory_management.md# borrowed) + * reference object + * [Reference counting (RC)] (./18_memory_management.md# memory management) + * Reference equality → [side effect](./07_side_effect.md) +* [identifier](./02_variable.md/# assignment) +* Signature + * type signature +* [dict](./11_dict.md) +* [Natural number] → [Nat] +* generics → [universal type] +* Generator +* [projective type] +* Borrow → [Reference](./18_memory_management.md#Borrow) +* [Shadowing] (./02_name.md# variables) +* Species → [Kind](./type/advanced/kind.md) +* [Set] → [Set] +* predicate + * [predicate function] +* Conditional branch +* [Ownership] +* Boolean → [Bool] +* Singleton +* [Symbol] → [Identifier](./02_name.md) + * [symbolization] +* [script](./00_basic.md# script) +* scope +* Spread operator → [expansion assignment] +* [slice](./10_array.md#slice) +* control character +* [Integer] → [Int] +* [set](./12_set.md) +* Semicolon → [;] +* [Declaration](./03_declaration.md) +* full name + * Universal type → [polymorphic type](./type/quantified.md) + * closed universal + * Open Universal + * universal function → polycorrelation function + * universal quantification +* prefix operator +* mutually recursive +* subscript → [index] +* [attribute] + * [attribute subtype] + +## Ta line + +* [algebra](./02_name.md) + * [Algebraic type](./type/13_algebraic.md) + * algebraic data types +* [assignment](./02_variable.md/#assignment) +* Multiple + * [Multiple inheritance](./type/07_inheritance.md/#Prohibition of multiple inheritance) + * Multiple assignment + * Overloading → [No overloading] +* Polyphase + * [polymorphic type](./type/quantified.md) + * polycorrelation coefficient +* polymorphism → [polymorphism] +* duck typing +* [tuple](./11_tuple.md) +* Single-phase + * Single phase + * Single-phase type + * Single correlation coefficient +* [lazy initialization] +* extraction assignment +* Abstract syntax tree → [AST] +* infix operator +* [constant](./02_name.md/#constant) + * [constant type](./type/advanced/const.md) + * [constant expression](./type/advanced/const.md) +*[definition] +* provided attributes +* [Apply] +* [decorator](./29_decorator.md) +* Destructor +* procedure → [procedure](./08_procedure.md) +* [default arguments](./04_function.md/#default arguments default-parameters) +* expand + * [expansion operator] + * [expansion assignment] +* [special format](./../API/special.md) +* Anonymous function → [anonymous function](./20_lambda.md) +* Dot operator (`.`) → [attribute reference] +* Top + * Top type → [Structural Object] + * Top class → [Object] +* [trait](./type/03_trait.md) + +## na line + +* [Comprehension](./27_comprehension.md) +* ~~Infix operator~~ → [Infix operator] +* [namespace] + +## is a line + +* [Array](./10_array.md) +* [derived type](./type/variances.md/# user-defined type variations) +* [pattern (match)](./26_pattern_matching.md) +* [package](./33_package_ssystem.md) +* Hashmap → [dictionary](./11_dict.md) +* [patch](./type/07_patch.md) +* public variable → [public variable](./19_visibility.md) +* Parameter → [argument](./04_function.md) +* [Parametric Polymorphism](./type/overloading.md) +* [contravariant](./type/advanced/variance.md) +* Compare + * [comparison operator] + * [comparable type] +* [private variable](./19_visibility.md) +* standard + * standard output + * standard input + * standard library +* [side effect](./07_side_effect.md) +* Complex number → [Complex] +* [Float] → [Float] +* Private Variable → [Private Variable] +* Boolean algebra → [Bool] +* [procedure](./08_procedure.md) +* [argument](./04_function.md) +* Partial Typing → [Subtyping] +* [immutable] + * [immutable object] + * [immutable type] + * [immutable reference] +* [sieve type](./type/12_refinement.md) +* [block] +* deconstruction assignment +* [variable](./02_variable.md) +* Bottom + * bottom type → [{}] + * Bottom class → [Never] +* [Polymorphism] + +## ma line + +* ~~ prefix operator ~~ → prefix operator +* [Marker type](./type/advanced/marker_trait.md) +* [anonymous function](./21_lambda.md) +* mutable → [mutable] +* [Move] +* methods +* Metacharacter +* [module](./24_module.md) +* [String] → [Str] + * [String interpolation](./01_literal.md/#str literal) +* Return value + +## or line + +* [Ghost type](./type/advanced/phantom.md) +* request attributes +* [element] +* [call] + +## Ra line + +* [Library] +* Lambda expression → [anonymous function](./20_lambda.md) +* rank + * [Rank 2 Polymorphism](./type/advanced/rank2type.md) +* [literal](./01_literal.md) + * [literal identifier](./18_naming_rule.md/#literal identifier) +* [quantified](./type/quantified.md) +* [Layout](./type/mut.md) +* [enum](./type/10_enum.md) +* [record](./12_record.md) + * [record type] + * Record Polymorphism → [Column Polymorphism] +* [column polymorphic] +* [local variable](./19_visibility.md) + +## line + +* Wildcard \ No newline at end of file diff --git a/doc/EN/syntax/quick_tour.md b/doc/EN/syntax/quick_tour.md index 12ecd719..0c5e6cf7 100644 --- a/doc/EN/syntax/quick_tour.md +++ b/doc/EN/syntax/quick_tour.md @@ -1 +1,267 @@ # Quick Tour + +The documentation below `syntax` is written with the aim of being understandable even for programming beginners. +For those who have already mastered languages such as Python, Rust, Haskell, etc., it may be a bit verbose. + +So, here's an overview of the Erg grammar. +Please think that the parts not mentioned are the same as Python. + +## variables, constants + +Variables are defined with `=`. As with Haskell, variables once defined cannot be changed. However, it can be shadowed in another scope. + +``` erg +i = 0 +if True: + i = 1 +assert i == 0 +``` + +Anything starting with an uppercase letter is a constant. Only things that can be computed at compile time can be constants. +Also, a constant is identical in all scopes since its definition. + +``` erg +PI = 3.141592653589793 +match random.random!(0..10): + PIs: + log "You get PI, it's a miracle!" +``` + +## declaration + +Unlike Python, only the variable type can be declared first. +Of course, the declared type and the type of the object actually assigned to must be compatible. + +``` erg +i: Int +i = 10 +``` + +## Functions + +You can define it just like in Haskell. + +``` erg +fib0 = 0 +fib1 = 1 +fibn = fib(n - 1) + fib(n - 2) +``` + +An anonymous function can be defined like this: + +``` erg +i -> i + 1 +assert [1, 2, 3].map(i -> i + 1).to_arr() == [2, 3, 4] +``` + +## operator + +The Erg-specific operators are: + +### mutating operator (!) + +It's like `ref` in Ocaml. + +``` erg +i = !0 +i.update! x -> x + 1 +assert i == 1 +``` + +## procedures + +Subroutines with side effects are called procedures and are marked with `!`. + +``` erg +print! 1 # 1 +``` + +## generic function (polycorrelation) + +``` erg +id|T|(x: T): T = x +id(1): Int +id("a"): Str +``` + +## Records + +You can use the equivalent of records in ML-like languages (or object literals in JS). + +``` erg +p = {x = 1; y = 2} +``` + +## Ownership + +Ergs are owned by mutable objects (objects mutated with the `!` operator) and cannot be rewritten from multiple places. + +``` erg +i = !0 +j = i +assert j == 0 +i#MoveError +``` + +Immutable objects, on the other hand, can be referenced from multiple places. + +## Visibility + +Prefixing a variable with `.` makes it a public variable and allows it to be referenced from external modules. + +``` erg +# foo.er +.x = 1 +y = 1 +``` + +``` erg +foo = import "foo" +assert foo.x == 1 +foo.y # VisibilityError +``` + +## pattern matching + +### variable pattern + +``` erg +# basic assignments +i = 1 +# with type +i: Int = 1 +# functions +fn x = x + 1 +fn: Int -> Int = x -> x + 1 +``` + +### Literal patterns + +``` erg +# if `i` cannot be determined to be 1 at compile time, TypeError occurs. +# shorthand of `_: {1} = i` +1 = i +# simple pattern matching +match x: + 1 -> "1" + 2 -> "2" + _ -> "other" +# fibonacci function +fib0 = 0 +fib1 = 1 +fibn: Nat = fibn-1 + fibn-2 +``` + +### constant pattern + +``` erg +PI = 3.141592653589793 +E = 2.718281828459045 +num = PI +name = match num: + PI -> "pi" + E -> "e" + _ -> "unnamed" +``` + +### discard (wildcard) pattern + +``` erg +_ = 1 +_: Int = 1 +right(_, r) = r +``` + +### Variable length patterns + +Used in combination with the tuple/array/record pattern described later. + +``` erg +[i,...j] = [1, 2, 3, 4] +assert j == [2, 3, 4] +first|T|(fst: T, ...rest: T) = fst +assert first(1, 2, 3) == 1 +``` + +### Tuple pattern + +``` erg +(i, j) = (1, 2) +((k, l), _) = ((1, 2), (3, 4)) +# If not nested, () can be omitted (1, 2 are treated as (1, 2)) +m, n = 1, 2 +``` + +### array pattern + +``` erg +length[] = 0 +length[_, ...rest] = 1 + lengthrest +``` + +#### record pattern + +``` erg +{sin; cos; tan; ...} = import "math" +{*} = import "math" # import all + +person = {name = "John Smith"; age = 20} +age = match person: + {name = "Alice"; _} -> 7 + {_; age} -> age +``` + +### Data class pattern + +``` erg +Point = Inherit {x = Int; y = Int} +p = Point::{x = 1; y = 2} +Point::{x; y} = p +``` + +## Comprehensions + +``` erg +odds = [i | i <- 1..100; i % 2 == 0] +``` + +## class + +Erg does not support multiple/multilevel inheritance. + +## Traits + +They are similar to Rust traits, but in a more literal sense, allowing composition and decoupling, and treating attributes and methods as equals. +Also, it does not involve implementation. + +``` erg +XY = Trait {x = Int; y = Int} +Z = Trait {z = Int} +XYZ = XY and Z +Show = Trait {show: Self.() -> Str} + +@Impl XYZ, Show +Point = Class {x = Int; y = Int; z = Int} +Point. + ... +``` + +## patch + +You can give implementations to classes and traits. + +## Sieve type + +A predicate expression can be type-restricted. + +``` erg +Nat = {I: Int | I >= 0} +``` + +## parametric type with value (dependent type) + +``` erg +a: [Int; 3] +b: [Int; 4] +a + b: [Int; 7] +``` \ No newline at end of file diff --git a/doc/EN/syntax/type/14_dependent.md b/doc/EN/syntax/type/14_dependent.md index 3108fd7c..c7ec3eb6 100644 --- a/doc/EN/syntax/type/14_dependent.md +++ b/doc/EN/syntax/type/14_dependent.md @@ -1,37 +1,37 @@ -# Dependent Types +# dependent type -Dependent types are one of the most important features of Erg. -Dependent types are types that take values as arguments. Normal polymorphic types can take only types as arguments, but dependent types loosen that restriction. +Dependent types are a feature that can be said to be the biggest feature of Erg. +A dependent type is a type that takes a value as an argument. Ordinary polymorphic types can take only types as arguments, but dependent types relax that restriction. -Dependent types, such as `[T; N]`(`Array(T, N)`), are equivalent. -This type depends not only on the type `T` of the contents, but also on the number `N` of the contents. `N` contains objects of type `Nat`. +Dependent types are equivalent to `[T; N]` (`Array(T, N)`). +This type is determined not only by the content type `T` but also by the number of contents `N`. `N` contains an object of type `Nat`. -```erg -a1 = [1, 2, 3]. -assert a1 in [Nat; 3]. +``` erg +a1 = [1, 2, 3] +assert a1 in [Nat; 3] a2 = [4, 5, 6, 7] -assert a1 in [Nat; 4]. -assert a1 + a2 in [Nat; 7]. +assert a1 in [Nat; 4] +assert a1 + a2 in [Nat; 7] ``` -If the type object passed as a function argument is related to a return type, write the following +If the type object passed in the function argument is related to the return type, write: -```erg +``` erg narray: |N: Nat| {N} -> [{N}; N] narray(N: Nat): [N; N] = [N; N] -assert narray(3) == [3, 3, 3]. +assert array(3) == [3, 3, 3] ``` When defining a dependent type, all type arguments must be constants. -Dependent types already exist in some languages, but Erg has the unique feature of allowing you to define procedural methods on dependent types. +Dependent types themselves exist in existing languages, but Erg has the feature of defining procedural methods on dependent types. -```erg -x = 1 +``` erg +x=1 f x = print! f::x, module::x -# Phantom types have an attribute called Phantom that has the same value as the type argument +# The Phantom type has an attribute called Phantom whose value is the same as the type argument T X: Int = Class Impl := Phantom X T(X). x self = self::Phantom @@ -39,36 +39,36 @@ T(X). T(1).x() # 1 ``` -Type arguments of variable-dependent types can be transitioned by applying methods. -Transitions are specified with `~>`. +Type arguments of mutable dependent types can be transitioned by method application. +Transition specification is done with `~>`. -```erg -# Note that `Id` is an immutable type and cannot be transitioned. -VM!(State: {"stopped", "running"}! := _, Id: Nat := _) = Class(... State). +``` erg +# Note that `Id` is an immutable type and cannot be transitioned +VM!(State: {"stopped", "running"}! := _, Id: Nat := _) = Class(..., Impl := Phantom! State) VM!(). # Variables that do not change can be omitted by passing `_`. start! ref! self("stopped" ~> "running") = - self.initialize_something! + self.initialize_something!() self::set_phantom!("running") -# You can also cut out each type argument (only within the defined module) -VM!.new() = VM!(!" stopped", 1).new() -VM!("running" ~> "running").stop! ref! self = +# You can also cut out by type argument (only in the module where it's defined) +VM!.new() = VM!(!"stopped", 1).new() +VM!("running" ~> "running").stop!ref!self = self.close_something!() - self::set_phantom!("stopped")) + self::set_phantom!("stopped") vm = VM!.new() vm.start!() vm.stop!() -vm.stop!() # TypeError: VM! stopped", 1) doesn't have .stop! -# TypeError: VM! running", 1) has .stop! +vm.stop!() # TypeError: VM!(!"stopped", 1) doesn't have .stop!() +# hint: VM!(!"running", 1) has .stop!() ``` -You can also create dependent types by incorporating or inheriting from existing types. +You can also embed or inherit existing types to create dependent types. -```erg -MyArray(T, N) = Inherit [T; N]. +``` erg +MyArray(T, N) = Inherit[T; N] -# type of self: Self(T, N) in conjunction with .array! +# The type of self: Self(T, N) changes in conjunction with .array MyStruct!(T, N: Nat!) = Class {.array: [T; !N]} -``` +``` \ No newline at end of file diff --git a/doc/EN/syntax/type/18_mut.md b/doc/EN/syntax/type/18_mut.md index e6a9c083..63ab9719 100644 --- a/doc/EN/syntax/type/18_mut.md +++ b/doc/EN/syntax/type/18_mut.md @@ -1,54 +1,54 @@ # Mutable Type -> __Warning__: The information in this section is out of date and contains some errors. +> __Warning__: The information in this section is old and contains some errors. -In Erg, by default, all types are immutable, i.e., their internal state cannot be updated. -However, variable types can of course be defined. Variable types are declared with `!`. +By default all types in Erg are immutable, i.e. their internal state cannot be updated. +But you can of course also define mutable types. Variable types are declared with `!`. -```erg +``` erg Person! = Class({name = Str; age = Nat!}) -Person! +Person!. greet! ref! self = print! "Hello, my name is {self::name}. I am {self::age}." - inc_age! ref! self = self::name.update! old -> old + 1 + inc_age!ref!self = self::name.update!old -> old + 1 ``` -To be precise, types whose base type is a variable type or a composite type that contains a variable type must end the type name with `!`! Types without `!` may exist in the same namespace and be treated as separate types. -In the example above, the `.age` attribute is variable and the `.name` attribute is immutable. If any one attribute is variable, the whole is a variable type. +To be precise, a type whose base type is a mutable type, or a composite type containing mutable types, must have a `!` at the end of the type name. Types without `!` can exist in the same namespace and are treated as separate types. +In the example above, the `.age` attribute is mutable and the `.name` attribute is immutable. If even one attribute is mutable, the whole is mutable. -A variable type can define procedural methods to rewrite instances, but just because it has procedural methods does not necessarily make it a variable type. For example, the array type `[T; N]` implements a `sample!` method that randomly selects elements, but this of course does not make destructive changes to the array. +Mutable types can define procedural methods that rewrite instances, but having procedural methods does not necessarily make them mutable. For example, the array type `[T; N]` implements a `sample!` method that randomly selects an element, but of course does not destructively modify the array. -Destructive manipulation of variable type objects is done primarily via the `.update!` method. The `.update!` method is a higher-order procedure that applies the function `f` to `self` to update it. +Destructive operations on mutable objects are primarily done via the `.update!` method. The `.update!` method is a higher-order procedure that updates `self` by applying the function `f`. -```erg +``` erg i = !1 i.update! old -> old + 1 assert i == 2 ``` -The `.set!` method simply discards the old content and replaces it with the new value. `.set! x = .update! _ -> x`. +The `.set!` method simply discards the old content and replaces it with the new value. .set!x = .update!_ -> x. -```erg +``` erg i = !1 i.set! 2 assert i == 2 ``` -The `.freeze_map` method invariantizes the value and performs the operation. +The `.freeze_map` method operates on values unchanged. -```erg +``` erg a = [1, 2, 3].into [Nat; !3] x = a.freeze_map a: [Nat; 3] -> a.iter().map(i -> i + 1).filter(i -> i % 2 == 0).collect(Array) ``` -In polymorphic invariant types, the type parameter `T` of a type is implicitly assumed to be an invariant type. +In a polymorphic immutable type the type argument `T` of the type is implicitly assumed to be immutable. -```erg +``` erg # ImmutType < Type -K T: ImmutType = Class ... -K! T: Type = Class ... +KT: ImmutType = Class ... +K!T: Type = Class ... ``` -In the standard library, mutable types `T!` are often based on immutable types `T`. However, `T!` and `T` types have no special linguistic relationship, and may not be constructed as such [1](#1) . +In the standard library, variable `(...)!` types are often based on immutable `(...)` types. However, `T!` and `T` types have no special linguistic relationship, and may not be constructed as such [1](#1) . Note that there are several types of object mutability. Below we will review the immutable/mutable semantics of the built-in collection types. @@ -60,20 +60,20 @@ Below we will review the immutable/mutable semantics of the built-in collection ## mutable types [T!; N] # can change contents one by one [T; !N] # variable length, content is immutable but can be modified by adding/deleting elements -[!T; N] # The content is an immutable object, but it can be replaced with an object whose type has been changed. -[!T; !N] # type and length can be changed. -[T!; !N] # contents and length can be changed. -[T!; N] # contents and type can be changed. -[T!; !N] # any variable operation can be performed +[!T; N] # The content is an immutable object, but it can be replaced by a different type (actually replaceable by not changing the type) +[!T; !N] # type and length can be changed +[T!; !N] # content and length can be changed +[!T!; N] # content and type can be changed +[!T!; !N] # Can perform all sorts of mutable operations ``` -Of course, it is not necessary to memorize and use all of these. -For variable array types, all you have to do is append `!`, and for practical use, `[T; N]`, `[T!; N]`, `[T; !N]`, and `[T!; !N]` can cover most cases. +Of course, you don't have to memorize and use all of them. +For variable array types, just add `!` to the part you want to be variable, and practically `[T; N]`, `[T!; N]`, `[T; !N]`, ` [T!; !N]` can cover most cases. -These array types are sugar-coated, and the actual types are as follows. +These array types are syntactic sugar, the actual types are: -```erg -# There are actually 4 types. +``` erg +# actually 4 types [T; N] = Array(T, N) [T; !N] = Array!(T, !N) [!T; N] = ArrayWithMutType!(!T, N) @@ -83,81 +83,81 @@ These array types are sugar-coated, and the actual types are as follows. [!T!; !N] = ArrayWithMutTypeAndLength!(!T!, !N) ``` -Note that type changeable means this. +This is what it means to be able to change the type. -```erg -a = [1, 2, 3].into [!Nat; 3]. +``` erg +a = [1, 2, 3].into [!Nat; 3] a.map!(_ -> "a") -a: [!Str; 3]. +a: [!Str; 3] ``` The same is true for other collection types. -```erg -## tuple types +``` erg +# tuple type ## immutable types -(T, U) ## immutable types: number of elements, contents unchangeable +(T, U) # No change in number of elements, contents cannot be changed ## mutable types -(T!, U) # number of elements immutable, first element can be changed -(T, U)! # number of elements invariant, contents can be replaced +(T!, U) # constant number of elements, first element can be changed +(T, U)! # No change in number of elements, content can be replaced ... ``` -```erg -## set types +``` erg +# Set type ## immutable types -{T; N} ## number of immutable elements, contents cannot be changed +{T; N} # number of immutable elements, contents cannot be changed ## mutable types -{T!; N} ## number of immutable types, contents can be changed (one by one) -{T; N}! ## variable number of elements, contents are unchangeable, but can be changed by adding or deleting elements, and the type inside can be changed. -{T!; N}! # variable number of elements, contents can be changed +{T!; N} # number of immutable elements, content can be changed (one by one) +{T; N}! # Number of variable elements, content cannot be changed +{T!; N}! # Number of variable elements, content can be changed ... ``` -```erg -# dictionary types. +``` erg +# Dictionary type ## immutable types -{K: V} ## invariant length, contents cannot be changed +{K: V} # immutable length, contents cannot be changed ## mutable types -{K: V!} ## invariant length, can change values (one by one) -{K: V}! ## variable length, cannot change content, but can add/delete elements, can change type inside +{K: V!} # constant length, values can be changed (one by one) +{K: V}! # Variable length, content cannot be changed, but can be added or deleted by adding or removing elements, content type can also be changed ... ``` -```erg -# Record type. +``` erg +# Record type ## immutable types -{x = Int; y = Str} ## cannot change content +{x = Int; y = Str} # content cannot be changed ## mutable types -{x = Int!; y = Str} # The value of x can be changed -{x = Int; y = Str}! ## can replace any instance of {x = Int; y = Str}! +{x = Int!; y = Str} # can change the value of x +{x = Int; y = Str}! # replace any instance of {x = Int; y = Str} ... ``` -If `T = (...)` and simply `T! = (...)!`, The type `(...)` is called a simple structural type. A simple structural type can also be said to be a type that (semantically) has no internal structure. -Arrays, tuples, sets, dictionaries, and record types are not all simple structure types, but Int and sieve types are. +A type `(...)` that simply becomes `T! = (...)!` when `T = (...)` is called a simple structured type. A simple structured type can also be said (semantically) to be a type that has no internal structure. +Arrays, tuples, sets, dictionaries, and record types are all non-simple structured types, but Int and Sieve types are. -```erg -## refinement type -## enumerated types -{1, 2, 3} # one of 1, 2, 3, cannot change -{1, 2, 3}! ## any of 1, 2, or 3, can be changed -## Interval type -1..12 # one of 1~12, cannot be changed -1..12! # any of 1~12, can be changed -## Sieve type (general form) -{I: Int | I % 2 == 0} # even type, cannot change +``` erg +# Sieve type +## Enums +{1, 2, 3} # one of 1, 2, 3, cannot be changed +{1, 2, 3}! # 1, 2, 3, you can change +## interval type +1..12 # 1 to 12, cannot be changed +1..12! # Any of 1-12, you can change +## Sieve type (general type) +{I: Int | I % 2 == 0} # even type, immutable {I: Int! | I % 2 == 0} # even type, can be changed -{I: Int | I % 2 == 0}! # exactly the same type as above, but the notation above is recommended +{I: Int | I % 2 == 0}! # Exactly the same type as above, but the above notation is preferred ``` -From the above explanation, a variable type is not only one that is variable itself, but also one whose internal type is variable. -Types such as `{x: Int!}` and `[Int!; 3]` are internal variable types in which the inner object is variable and not the instance itself. +From the above explanation, mutable types include not only those that are themselves mutable, but also those whose internal types are mutable. +Types such as `{x: Int!}` and `[Int!; 3]` are internal mutable types where the object inside is mutable and the instance itself is not mutable. -Types that have an internal structure and the type constructor itself is `! In the case of the type `K!(T, U)` with `! Local modifications are also possible. -However, since it is desirable to keep modification privileges as local as possible, it is better to use `K(T!, U)` when only `T` can be changed. -And in the case of type `T!`, which has no internal structure, this instance is simply a replaceable `T` box. The type cannot be changed by methods. +For a type `K!(T, U)` that has internal structure and has a `!` on the type constructor itself, `*self` can change the whole object. Local changes are also possible. +However, it is desirable to keep the change authority as local as possible, so if only `T` can be changed, it is better to use `K(T!, U)`. +And for the type `T!` which has no internal structure, this instance is simply a box of `T` which can be swapped. A method cannot change the type. --- -1 It is intentional that `T!` and `T` types have no special linguistic relationship. It is a design. If there is a relationship, for example, if the `T`/`T!` type exists in the namespace, it will not be possible to introduce the `T!`/`T` type from another module. Also, the mutable type is not uniquely defined for the immutable type. Given the definition `T = (U, V)`, the possible variable subtypes of `T!` are `(U!, V)` and `(U, V!)`. [↩](#f1) +1 It is intentional that `T!` and `T` types have no special linguistic relationship. It's a design. If there is a relationship, for example, if the `T`/`T!` type exists in the namespace, it will not be possible to introduce the `T!`/`T` type from another module. Also, the mutable type is not uniquely defined for the immutable type. Given the definition `T = (U, V)`, the possible variable subtypes of `T!` are `(U!, V)` and `(U, V!)`. [↩](#f1) \ No newline at end of file diff --git a/doc/EN/syntax/type/19_bound.md b/doc/EN/syntax/type/19_bound.md index 42de3272..90411ac4 100644 --- a/doc/EN/syntax/type/19_bound.md +++ b/doc/EN/syntax/type/19_bound.md @@ -1,18 +1,18 @@ # Type Bound -A type boundary is a condition on the type specification. The guard (guard clause) is the function that makes this possible. -In addition to function signatures and anonymous function signatures, sieve types can also use this feature. -The guard is described after the return type. +Type bounds add conditions to type specifications. A function that realizes this is a guard (guard clause). +This feature is available for function signatures, anonymous function signatures, as well as sieve types. +Guards are written after the return type. -## Predicate Expressions (Predicate) +## Predicate -The condition that a variable satisfies can be specified by an expression (predicate) that returns a `Bool`. -You can use [value object](./08_value.md) and operators. Compile-time functions may be supported in future versions. +You can specify the condition that the variable satisfies with an expression (predicate expression) that returns `Bool`. +Only [value objects](./08_value.md) and operators can be used. Compile-time functions may be supported in future versions. -```erg +``` erg f a: [T; N] | T, N, N > 5 = ... g a: [T; N | N > 5] | T, N = ... Odd = {I: Int | I % 2 == 1} R2Plus = {(L, R) | L, R: Ratio; L > 0 and R > 0} GeneralizedOdd = {I | U; I <: Div(Nat, U); I % 2 == 0} -``` +``` \ No newline at end of file diff --git a/doc/EN/syntax/type/advanced.md b/doc/EN/syntax/type/advanced.md index 6849961d..1fdeed74 100644 --- a/doc/EN/syntax/type/advanced.md +++ b/doc/EN/syntax/type/advanced.md @@ -1,2 +1 @@ -The following sections describe more advanced type systems. Beginners do not need to read the entire section. - +In the following, we will discuss more advanced type systems. Beginners do not have to read all the sections. \ No newline at end of file diff --git a/doc/EN/syntax/type/advanced/GADTs.md b/doc/EN/syntax/type/advanced/GADTs.md index f869085e..ee5da587 100644 --- a/doc/EN/syntax/type/advanced/GADTs.md +++ b/doc/EN/syntax/type/advanced/GADTs.md @@ -1,8 +1,8 @@ # Generalized Algebraic Data Types (GADTs) -Erg can create Generalized Algebraic Data Types (GADTs) by classifying Or (Union) types. +Erg can create Generalized Algebraic Data Types (GADTs) by classifying Or types. -```erg +``` erg Nil T = Class(Impl := Phantom T) Cons T = Class {head = T; rest = List T}, Impl := Unpack List T: Type = Class(Nil T or Cons T) @@ -10,7 +10,7 @@ List. nil|T|() = Self(T).new Nil(T).new() cons head, rest | T = Self(T).new Cons(T).new(head, rest) head self = match self: - {head; ...} : Cons _ -> head + {head; ...}: Cons_ -> head _: Nil -> panic "empty list" {nil; cons; ...} = List @@ -18,17 +18,17 @@ print! cons(1, cons(2, nil())).head() # 1 print! nil.head() # RuntimeError: "empty list" ``` -not `List(T).nil() = ...`, but `List.nil|T|() = ...`. This is because the type specification is no longer needed when using it. +The reason we say `List.nil|T|() = ...` instead of `List(T).nil() = ...` is that we don't need to specify the type when using it. -```erg +``` erg i = List.nil() _: List Int = cons 1, i ``` -The `List T` defined here is a GADTs, but it is a naive implementation and does not demonstrate the true value of GADTs. -For example, the `.head` method above will give a runtime error if the contents are empty, but this check can be done at compile time. +The `List T` defined here is GADTs, but it's a naive implementation and doesn't show the true value of GADTs. +For example, the `.head` method above will throw a runtime error if the body is empty, but this check can be done at compile time. -```erg +``` erg List: (Type, {"Empty", "Nonempty"}) -> Type List T, "Empty" = Class(Impl := Phantom T) List T, "Nonempty" = Class {head = T; rest = List(T, _)}, Impl := Unpack @@ -43,10 +43,10 @@ print! cons(1, cons(2, nil())).head() # 1 print! nil().head() # TypeError ``` -The GADTs example often described is a list whose contents can be judged as empty or not by type, as shown above. -Erg allows for further refinement, defining a list with length. +An example of GADTs that is often explained on the street is a list that can judge whether the contents are empty or not by type as above. +Erg can be further refined to define a list with length. -```erg +``` erg List: (Type, Nat) -> Type List T, 0 = Class(Impl := Phantom T) List T, N = Class {head = T; rest = List(T, N-1)}, Impl := Unpack @@ -56,11 +56,11 @@ List. List(_, N | N >= 1). head {head; ...} = head List(_, N | N >= 2). - pair {head = first; rest = {head = second; ...}} = [first, second]. + pair {head = first; rest = {head = second; ...}} = [first, second] {nil; cons; ...} = List -print! cons(1, cons(2, nil)).pair() # [1, 2]. -cons(1, nil).pair() # TypeError -cons(1, nil).head() # 1 -print! nil.head() # TypeError -``` +print! cons(1, cons(2, nil)).pair() # [1, 2] +print! cons(1, nil).pair() # TypeError +print! cons(1, nil).head() # 1 +print! nil. head() # TypeError +``` \ No newline at end of file diff --git a/doc/EN/syntax/type/advanced/_rank2type.md b/doc/EN/syntax/type/advanced/_rank2type.md new file mode 100644 index 00000000..11b4afcd --- /dev/null +++ b/doc/EN/syntax/type/advanced/_rank2type.md @@ -0,0 +1,142 @@ +# rank-2 polymorphism + +> __Warning__: This document is out of date and contains errors in general. + +Erg allows you to define functions that accept various types such as `id|T|(x: T): T = x`, ie polycorrelations. +So, can we define a function that accepts polycorrelations? +For example, a function like this (note that this definition is erroneous): + +``` erg +# I want tuple_map(i -> i * 2, (1, "a")) == (2, "aa") +tuple_map|T|(f: T -> T, tup: (Int, Str)): (Int, Str) = (f(tup.0), f(tup.1)) +``` + +Note that `1` and `"a"` have different types, so the anonymous function is not monomorphic once. Needs to be single-phased twice. +Such a function cannot be defined within the scope of the types we have discussed so far. This is because type variables have no notion of scope. +Let's leave the types for a moment and see the concept of scope at the value level. + +``` erg +arr = [1, 2, 3] +arr.map i -> i + 1 +``` + +`arr` and `i` in the code above are variables in different scopes. Therefore, each life span is different (`i` is shorter). + +The types so far have the same lifetime for all type variables. In other words, `T`, `X`, and `Y` must be determined at the same time and remain unchanged thereafter. +Conversely, if we can think of `T` as a type variable in the "inner scope", we can compose a `tuple_map` function. __Rank 2 type__ was prepared for that purpose. + +``` erg +# tuple_map: ((|T: Type| T -> T), (Int, Str)) -> (Int, Str) +tuple_map f: (|T: Type| T -> T), tup: (Int, Str) = (f(tup.0), f(tup.1)) +assert tuple_map(i -> i * 2, (1, "a")) == (2, "aa") +``` + +A type of the form `{(type) | (list of type variables)}` is called a universal type (see [Universal type](./../quantified.md) for details). +The `id` function we have seen so far is a typical universal function = polycorrelation function. + +``` erg +id x = x +id: |T: Type| T -> T +``` + +A universal type has special rules for association with the function type constructor `->`, and the semantics of the type are completely different depending on the way of association. + +Think about this in terms of simple one-argument functions. + +``` erg +f1: (T -> T) -> Int | T # a function that takes any function and returns an Int +f2: (|T: Type| T -> T) -> Int # Function that receives polycorrelation and returns Int +f3: Int -> (|T: Type| T -> T) # A function that takes an Int and returns a closed universal function +f4: |T: Type|(Int -> (T -> T)) # Same as above (preferred) +``` + +It seems strange that `f1` and `f2` are different, while `f3` and `f4` are the same. Let's actually construct a function of such a type. + +``` erg +# id: |T: Type| T -> T +id x = x +# same type as `f1` +take_univq_f_and_return_i(_: (|T: Type| T -> T), i: Int): Int = i +# same type as `f2` +take_arbit_f_and_return_i|T: Type|(_: T -> T, i: Int): Int = i +# same type as `f3` +take_i_and_return_univq_f(_: Int): (|T: Type| T -> T) = id +# same type as `f4` +take_i_and_return_arbit_f|T: Type|(_: Int): (T -> T) = id +``` + +After applying it, you will notice the difference. + +``` erg +_ = take_univq_f_and_return_i(x -> x, 1) # OK +_ = take_univq_f_and_return_i(x: Int -> x, 1) #NG +_ = take_univq_f_and_return_i(x: Str -> x, 1) # NG +_ = take_arbit_f_and_return_i(x -> x, 1) # OK +_ = take_arbit_f_and_return_i(x: Int -> x, 1) # OK +_ = take_arbit_f_anf_return_i(x: Str -> x, 1) # OK + +f: |T| T -> T = take_i_and_return_univq_f(1) +g: |T| T -> T = take_i_and_return_arbit_f(1) +assert f == g +f2: Int -> Int = take_i_and_return_univq_f|Int|(1) +g2: Int -> Int = take_i_and_return_arbit_f|Int|(1) +assert f2 == g2 +``` + +An open polycorrelation function type is specifically called an __arbitrary function type__. Arbitrary function types have an infinite number of possibilities: `Int -> Int`, `Str -> Str`, `Bool -> Bool`, `|T: Type| T -> T`, ... be. +On the other hand, there is only one closed (returning an object of the same type as the argument) polymorphic type `|T: Type| T -> T`. Such types are specifically called __polymorphic function types__. +In other words, `f1` can be passed `x: Int -> x+1`, `x: Bool -> not x`, `x -> x`, etc. = `f1` is a polycorrelated number Yes, but you can only pass `x -> x` etc. to `f2` = `f2` is not __a polycorrelation__. +But the types of functions like `f2` are clearly different from normal types, and we need new concepts to handle them well. That is the "rank" of the type. + +Regarding the definition of rank, types that are not quantified, such as `Int`, `Str`, `Bool`, `T`, `Int -> Int`, `Option Int`, etc., are treated as "rank 0". + +``` erg +# K is a polynomial kind such as Option +R0 = (Int or Str or Bool or ...) or (R0 -> R0) or K(R0) +``` + +Next, types with first-order universal quantification, such as `|T| T -> T`, or types that include them in the return value type are “rank 1”. +In addition, types with second-order universal quantification (types that have rank 1 types as arguments such as `(|T| T -> T) -> Int`) or types that include them in the return type are called "rank 2 ”. +The above is repeated to define the “Rank N” type. Also, the rank-N types include all types with a rank of N or less. Therefore, a type with mixed ranks has the same rank as the highest among them. + +``` erg +R1 = (|...| R0) or (R0 -> R1) or K(R1) or R0 +R2 = (|...| R1) or (R1 -> R2) or K(R2) or R1 +... +Rn = (|...| Rn-1) or (Rn-1 -> Rn) or K(Rn) or Rn-1 +``` + +Let's look at some examples. + +``` erg + (|T: Type| T -> T) -> (|U: Type| U -> U) +=> R1 -> R1 +=> R1 -> R2 +=> R2 + +Option(|T: Type| T -> T) +=> Option(R1) +=> K(R1) +=> R1 +``` + +By definition, `tuple_map` is a rank-2 type. + +``` erg +tuple_map: + ((|T: Type| T -> T), (Int, Str)) -> (Int, Str) +=> (R1, R0) -> R0 +=> R1 -> R2 +=> R2 +``` + +Erg can handle types up to rank 2 (because rank N types include all types with rank N or less, to be exact, all Erg types are rank 2 types). Attempting to construct a function of more types is an error. +For example, all functions that handle polycorrelations as they are require specification of other argument types. Also, such a function is not configurable. + +``` erg +# this is a rank-3 type function +# |X, Y: Type|((|T: Type| T -> T), (X, Y)) -> (X, Y) +generic_tuple_map|X, Y: Type| f: (|T: Type| T -> T), tup: (X, Y) = (f(tup.0), f(tup.1)) +``` + +It is known that types with rank 3 or higher are theoretically undecidable by type inference. However, most practical needs can be covered by the rank 2 type. \ No newline at end of file diff --git a/doc/EN/syntax/type/advanced/default_param.md b/doc/EN/syntax/type/advanced/default_param.md index e8108ea6..d18a9e02 100644 --- a/doc/EN/syntax/type/advanced/default_param.md +++ b/doc/EN/syntax/type/advanced/default_param.md @@ -1,8 +1,8 @@ -# Function type with default parameter +# Function type with default arguments -First, let's look at an example of the use of default parameters. +First, let's look at an example of using default arguments. -```erg +``` erg f: (Int, Int, z := Int) -> Int f(x, y, z := 0) = x + y + z @@ -11,18 +11,18 @@ g(x, y, z := 0, w := 1) = x + y + z + w fold: ((Int, Int) -> Int, [Int], acc := Int) -> Int fold(f, [], acc) = acc -fold(f, arr, acc := 0) = fold(f, arr[1...]) , f(acc, arr[0])) +fold(f, arr, acc := 0) = fold(f, arr[1..], f(acc, arr[0])) assert fold(f, [1, 2, 3]) == 6 assert fold(g, [1, 2, 3]) == 8 ``` -The parameters after `:=` are default parameters. +Arguments after `:=` are default arguments. The subtyping rules are as follows. -```erg +``` erg ((X, y := Y) -> Z) <: (X -> Z) -((X, y := Y, ...) -> Z) -> Z) <: ((X, ...) -> Z) +((X, y := Y, ...) -> Z) <: ((X, ...) -> Z) ``` -The first means that a function with a default parameter is identical to a function without it. -The second means that any default parameter can be omitted. +The first means that a function with default arguments can be identified with a function without. +The second means that any default argument can be omitted. \ No newline at end of file diff --git a/doc/EN/syntax/type/advanced/keyword_param.md b/doc/EN/syntax/type/advanced/keyword_param.md index debadb33..45db64bc 100644 --- a/doc/EN/syntax/type/advanced/keyword_param.md +++ b/doc/EN/syntax/type/advanced/keyword_param.md @@ -1,26 +1,26 @@ # Function type with keyword arguments -```erg +``` erg h(f) = f(y: 1, x: 2) h: |T: Type|((y: Int, x: Int) -> T) -> T ``` The subtyping rules for functions with keyword arguments are as follows. -```erg +``` erg ((x: T, y: U) -> V) <: ((T, U) -> V) # x, y are arbitrary keyword parameters ((y: U, x: T) -> V) <: ((x: T, y: U) -> V) ((x: T, y: U) -> V) <: ((y: U, x: T) -> V) ``` -This means that keyword arguments can be eliminated or replaced. -However, it is not possible to do both at the same time. -That is, `(x: T, y: U) -> V` cannot be cast to `(U, T) -> V`. -Note that keyword arguments are only available in top-level tuples, not in arrays or nested tuples. +This means that keyword arguments can be deleted or replaced. +But you can't do both at the same time. +That is, you cannot cast `(x: T, y: U) -> V` to `(U, T) -> V`. +Note that keyword arguments are attached only to top-level tuples, and not to arrays or nested tuples. -```erg +``` erg Valid: [T, U] -> V Invalid: [x: T, y: U] -> V Valid: (x: T, ys: (U,)) -> V Invalid: (x: T, ys: (y: U,)) -> V -``` +``` \ No newline at end of file diff --git a/doc/EN/syntax/type/advanced/kind.md b/doc/EN/syntax/type/advanced/kind.md index 9639faf5..64cd1f35 100644 --- a/doc/EN/syntax/type/advanced/kind.md +++ b/doc/EN/syntax/type/advanced/kind.md @@ -9,7 +9,7 @@ Note that `->` itself, which is an anonymous function operator, can also be seen Also note that a kind that is not an atomic kind is not a type. Just as `-1` is a number but `-` is not, `Option Int` is a type but `Option` is not. `Option` etc. are sometimes called type constructors. -```erg +``` erg assert not Option in Type assert Option in Type -> Type ``` @@ -17,7 +17,7 @@ assert Option in Type -> Type So code like the following will result in an error: In Erg, methods can only be defined in atomic kinds, and the name `self` cannot be used anywhere other than the first argument of a method. -```erg +``` erg #K is an unary kind K: Type -> Type K T = Class... @@ -32,7 +32,7 @@ Examples of binary or higher kinds are `{T: U}`(: `(Type, Type) -> Type`), `(T, There is also a zero-term kind `() -> Type`. This is sometimes equated with an atomic kind in type theory, but is distinguished in Erg. An example is `Class`. -```erg +``` erg Nil = Class() ``` @@ -40,23 +40,23 @@ Nil = Class() There is also a partial type relation, or rather a partial kind relation, between multinomial kinds. -```erg +``` erg K T = ... L = Inherit K -L <: K +L<: K ``` That is, for any `T`, if `L T <: K T`, then `L <: K`, and vice versa. -```console +``` erg ∀T. L T <: K T <=> L <: K ``` -## Higher-order Kind +## higher kind There is also a higher-order kind. This is a kind of the same concept as a higher-order function, a kind that receives a kind itself. `(Type -> Type) -> Type` is a higher kind. Let's define an object that belongs to a higher kind. -```erg +``` erg IntContainerOf K: Type -> Type = K Int assert IntContainerOf Option == Option Int assert IntContainerOf Result == Result Int @@ -65,30 +65,30 @@ assert IntContainerOf in (Type -> Type) -> Type The bound variables of a polynomial kind are usually denoted as K, L, ..., where K is K for Kind. -## Set kind +## set kind In type theory, there is the concept of a record. This is almost the same as the Erg record [2](#2). -```erg +``` erg # This is a record, and it corresponds to what is called a record in type theory {x = 1; y = 2} ``` When all record values were types, it was a kind of type called a record type. -```erg +``` erg assert {x = 1; y = 2} in {x = Int; y = Int} ``` A record type types a record. A good guesser might have thought that there should be a "record kind" to type the record type. Actually it exists. -```erg +``` erg log Typeof {x = Int; y = Int} # {{x = Int; y = Int}} ``` A type like `{{x = Int; y = Int}}` is a record kind. This is not a special notation. It is simply an enumeration type that has only `{x = Int; y = Int}` as an element. -```erg +``` erg Point = {x = Int; y = Int} Pointy = {Point} ``` @@ -96,7 +96,7 @@ Pointy = {Point} An important property of record kind is that if `T: |T|` and `U <: T` then `U: |T|`. This is also evident from the fact that enums are actually syntactic sugar for sieve types. -```erg +``` erg # {c} == {X: T | X == c} for normal objects, but # Equality may not be defined for types, so |T| == {X | X <: T} {Point} == {P | P <: Point} @@ -105,7 +105,7 @@ This is also evident from the fact that enums are actually syntactic sugar for s `U <: T` in type constraints is actually syntactic sugar for `U: |T|`. A kind that is a set of such types is commonly called a set kind. Setkind also appears in the Iterator pattern. -```erg +``` erg Iterable T = Trait { .Iterator = {Iterator} .iter = Self(T).() -> Self.Iterator T @@ -114,7 +114,7 @@ Iterable T = Trait { ## Type inference for polynomial kinds -```erg +``` erg Container K: Type -> Type, T: Type = Patch K(T, T) Container (K). f self = ... @@ -146,4 +146,4 @@ In this case, patches are selected according to the following priority criteria. 1 In type theory notation, `*=>*` [↩](#f1) -2 There are subtle differences such as visibility. [↩](#f2) +2 There are subtle differences such as visibility. [↩](#f2) \ No newline at end of file diff --git a/doc/EN/syntax/type/advanced/marker_trait.md b/doc/EN/syntax/type/advanced/marker_trait.md index 2c3af3f8..17b8326b 100644 --- a/doc/EN/syntax/type/advanced/marker_trait.md +++ b/doc/EN/syntax/type/advanced/marker_trait.md @@ -1,20 +1,20 @@ # Marker Trait -A marker trait is a trait with no required attributes. That is, it can be Impl without implementing a method. -It may seem meaningless without the required attribute, but it registers the information that it belongs to that trait, so that patch methods can be used and the compiler can give it special treatment. +Marker traits are traits without required attributes. That is, you can Impl without implementing any method. +It seems meaningless without the required attribute, but since the information that it belongs to the trait is registered, you can use the patch method or get special treatment by the compiler. -All marker traits are encompassed by the `Marker` trait. -The `Light` provided in the standard is a kind of marker trait. +All marker traits are subsumed by the `Marker` trait. +`Light` provided as standard is a kind of marker trait. -```erg +``` erg Light = Subsume Marker ``` -```erg +``` erg Person = Class {.name = Str; .age = Nat} and Light ``` -```erg +``` erg M = Subsume Marker MarkedInt = Inherit Int, Impl := M @@ -24,8 +24,8 @@ assert i + 1 == 2 assert i in M ``` -The marker class can also be removed with the `Excluding` argument. +Marker classes can also be excluded with the `Excluding` argument. -```erg +``` erg NInt = Inherit MarkedInt, Impl := N, Excluding: M -``` +``` \ No newline at end of file diff --git a/doc/EN/syntax/type/advanced/special.md b/doc/EN/syntax/type/advanced/special.md index 12f164a8..8fa6825b 100644 --- a/doc/EN/syntax/type/advanced/special.md +++ b/doc/EN/syntax/type/advanced/special.md @@ -1,22 +1,22 @@ -# Special Type(Self, Super) +# Special types (Self, Super) -`Self` represents itself types. It can be used simply as an alias, however note that its meaning changes in derived types (it refers to the derived own type). +`Self` represents its own type. You can just use it as an alias, but note that the meaning changes in derived types (refers to the own type). -```erg +``` erg @Inheritable C = Class() C. - new_self() = Self.new() + new_self() = Self. new() new_c() = C.new() D = Inherit C -classof D.new_self() # D -classof D.new_c() # C +classof D. new_self() # D +classof D. new_c() # C ``` -`Super` represents types of base classes. The method itself refers to the base class, however the instance uses its own type. +`Super` represents the type of the base class. The method itself refers to the base class, but the instance uses its own type. -```erg +``` erg @Inheritable C = Class() @@ -25,15 +25,15 @@ D. new_super() = Super.new() new_c() = C.new() -classof D.new_super() # D -classof D.new_c() # C +classof D. new_super() # D +classof D. new_c() # C ``` -## Special Type Variable +## special type variables -`Self` and `Super` can be used as type variables in structural types and traits. It refers to a class, which is a subtype of that type. That is, `Self` in type `T` means `Self <: T`. +`Self` and `Super` can be used as type variables in structured types and traits. This refers to classes that are subtypes of that type. That is, `Self` in type `T` means `Self <: T`. -```erg +``` erg Add R = Trait { .AddO = Type .`_+_`: Self, R -> Self.AddO @@ -48,4 +48,4 @@ assert 1 in Add(Int, Int) assert 1 in ClosedAdd assert Int < Add(Int, Int) assert Int < ClosedAdd -``` +``` \ No newline at end of file diff --git a/doc/EN/syntax/type/advanced/typeof.md b/doc/EN/syntax/type/advanced/typeof.md new file mode 100644 index 00000000..ab16bb84 --- /dev/null +++ b/doc/EN/syntax/type/advanced/typeof.md @@ -0,0 +1,65 @@ +# Typeof, classof + +`Typeof` is a function that can peek into Erg's type inference system, and its behavior is complex. + +``` erg +assert Typeof(1) == {I: Int | I == 1} +i: 1..3 or 5..10 = ... +assert Typeof(i) == {I: Int | (I >= 1 and I <= 3) or (I >= 5 and I <= 10)} + +C = Class {i = Int} +I = C. new {i = 1} +assert Typeof(I) == {X: C | X == I} +J: C = ... +assert Typeof(J) == {i = Int} + +assert {X: C | X == I} < C and C <= {i = Int} +``` + +The `Typeof` function returns the derived type, not the class of the object. +So for instance `I: C` of class `C = Class T`, `Typeof(I) == T`. +A value class does not have a corresponding record type. To solve this problem, value classes are supposed to be record types that have a `__valueclass_tag__` attribute. +Note that you cannot access this attribute, nor can you define a `__valueclass_tag__` attribute on a user-defined type. + +``` erg +i: Int = ... +assert Typeof(i) == {__valueclass_tag__ = Phantom Int} +s: Str = ... +assert Typeof(s) == {__valueclass_tag__ = Phantom Str} +``` + +`Typeof` outputs only structured types. I explained that structured types include attribute types, sieve types, and (true) algebraic types. +These are independent types (inference precedence exists) and inference conflicts do not occur. +Attribute types and algebraic types can span multiple classes, while sieve types are subtypes of a single class. +Erg infers object types as sieve types as much as possible, and when that is not possible, expands sieve base classes to structured types (see below). + +## structured + +All classes can be converted to derived types. This is called __structuring__. The structured type of a class can be obtained with the `Structure` function. +If a class is defined with `C = Class T` (all classes are defined in this form) then `Structure(C) == T`. + +``` erg +C = Class {i = Int} +assert Structure(C) == {i = Int} +D = Inherit C +assert Structure(D) == {i = Int} +Nat = Class {I: Int | I >= 0} +assert Structure(Nat) == {I: Int | I >= 0} +Option T = Class (T or NoneType) +assert Structure(Option Int) == Or(Int, NoneType) +assert Structure(Option) # TypeError: only monomorphized types can be structured +# You can't actually define a record with __valueclass_tag__, but conceptually +assert Structure(Int) == {__valueclass_tag__ = Phantom Int} +assert Structure(Str) == {__valueclass_tag__ = Phantom Str} +assert Structure((Nat, Nat)) == {__valueclass_tag__ = Phantom(Tuple(Nat, Nat))} +assert Structure(Nat -> Nat) == {__valueclass_tag__ = Phantom(Func(Nat, Nat))} +# Marker classes are also record types with __valueclass_tag__ +M = Inherit Marker +assert Structure(M) == {__valueclass_tag__ = Phantom M} +D = Inherit(C and M) +assert Structure(D) == {i = Int; __valueclass_tag__ = Phantom M} +E = Inherit(Int and M) +assert Structure(E) == {__valueclass_tag__ = Phantom(And(Int, M))} +F = Inherit(E not M) +assert Structure(F) == {__valueclass_tag__ = Phantom Int} +``` \ No newline at end of file diff --git a/doc/EN/syntax/type/advanced/variance.md b/doc/EN/syntax/type/advanced/variance.md new file mode 100644 index 00000000..6a7bec59 --- /dev/null +++ b/doc/EN/syntax/type/advanced/variance.md @@ -0,0 +1,143 @@ +# variation + +Erg can subtype polymorphic types, but there are some caveats. + +First, consider the inclusion relation of ordinary polymorphic types. In general, there is a container `K` and a type `A, B` to which it assigns, and when `A < B`, `K A < K B`. +For example, `Option Int < Option Object`. Therefore, methods defined in `Option Object` can also be used in `Option Int`. + +Consider the typical polymorphic type `Array!(T)`. +Note that this time it's not `Array!(T, N)` because we don't care about the number of elements. +Now, the `Array!(T)` type has methods called `.push!` and `.pop!`, which mean adding and removing elements, respectively. Here is the type: + +Array.push!: Self(T).(T) => NoneType +Array.pop!: Self(T).() => T + +As can be intuitively understood, + +* `Array!(Object).push!(s)` is OK when `s: Str` (just upcast `Str` to `Object`) +* When `o: Object`, `Array!(Str).push!(o)` is NG +* `Array!(Object).pop!().into(Str)` is NG +* `Array!(Str).pop!().into(Object)` is OK + +is. In terms of the type system, this is + +* (Self(Object).(Object) => NoneType) < (Self(Str).(Str) => NoneType) +* (Self(Str).() => Str) < (Self(Object).() => Object) + +means + +The former may seem strange. Even though `Str < Object`, the inclusion relation is reversed in the function that takes it as an argument. +In type theory, such a relation (the type relation of `.push!`) is called contravariant, and vice versa, the type relation of `.pop!` is called covariant. +In other words, function types are contravariant with respect to their argument types and covariant with respect to their return types. +It sounds complicated, but as we saw earlier, it's a reasonable rule if you apply it to an actual example. +If you still don't quite get it, consider the following. + +One of Erg's design principles is "large input types, small output types". This is precisely the case for function mutability. +Looking at the rules above, the larger the input type, the smaller the overall type. +This is because general-purpose functions are clearly rarer than special-purpose functions. +And the smaller the output type, the smaller the whole. + +As a result, the above policy is equivalent to saying "minimize the type of the function". + +## Immutability + +Erg has another modification. It is non-variance. +This is a modification that built-in types such as `SharedCell! T!` have. This means that for two types `T!, U!` where `T! != U!`, casts between `SharedCell! T!` and `SharedCell! means that +This is because `SharedCell! T!` is a shared reference. See [shared references](shared.md) for details. + +## Mutated generic type + +A universal type variable can specify its upper and lower bounds. + +``` erg +|A <: T| K(A) +|B :> T| K(B) +``` + +In the type variable list, the __variant specification__ of the type variable is performed. In the above variant specification, the type variable `A` is declared to be any subclass of type `T` and the type variable `B` is declared to be any superclass of type `T`. +In this case, `T` is also called the upper type for `A` and the lower type for `B`. + +Mutation specifications can also overlap. + +``` erg +# U U} +``` + +Here is an example of code that uses a variable specification. + +``` erg +show|S <: Show| s: S = log s + +Nil T = Class(Impl = Phantom T) +Cons T = Class(Nil T or List T) +List T = Class {head = T; rest = Cons T} +List(T). + push|U <: T|(self, x: U): List T = Self. new {head = x; rest = self} + upcast(self, U :> T): List U = self +``` + +## Change specification + +The `List T` example is tricky, so let's go into a little more detail. +To understand the code above, you need to know about polymorphic type degeneration. Variance is discussed in detail in [this section](./variance.md), but for now we need three facts: + +* Ordinary polymorphic types, such as `List T`, are covariant with `T` (`List U > List T` when `U > T`) +* The function `T -> U` is contravariant with respect to the argument type `T` (`(S -> U) < (T -> U)` when `S > T`) +* Function `T -> U` is covariant with return type `U` (`(T -> U) > (T -> S)` when `U > S`) + +For example, `List Int` can be upcast to `List Object` and `Obj -> Obj` can be upcast to `Int -> Obj`. + +Now let's consider what happens if we omit the variable specification of the method. + +``` erg +... +List T = Class {head = T; rest = Cons T} +List(T). + # List T can be pushed U if T > U + push|U|(self, x: U): List T = Self. new {head = x; rest = self} + # List T can be List U if T < U + upcast(self, U): List U = self +``` + +Even in this case, the Erg compiler does a good job of inferring the upper and lower types of `U`. +Note, however, that the Erg compiler doesn't understand the semantics of methods. The compiler simply infers and derives type relationships mechanically according to how variables and type variables are used. + +As written in the comments, the type `U` put in the `head` of `List T` is a subclass of `T` (`T: Int`, such as `Nat`). That is, it is inferred as `U <: T`. This constraint changes the argument type of `.push{U}` upcast `(List(T), U) -> List(T) to (List(T), T) -> List(T)`( e.g. disallow `List(Int).push{Object}`). Note, however, that the `U <: T` constraint does not alter the type containment of the function. The fact that `(List(Int), Object) -> List(Int) to (List(Int), Int) -> List(Int)` does not change, just in `.push` method It means that the cast cannot be performed. +Similarly, a cast from `List T` to `List U` is possible subject to the constraint `U :> T`, so the variation specification is inferred. This constraint changes the return type of `.upcast(U)` to upcast `List(T) -> List(T) to List(T) -> List(T)` (e.g. `List(Object) .upcast(Int)`) is prohibited. + +Now let's see what happens if we allow this upcast. +Let's invert the denaturation designation. + +``` erg +... +List T = Class {head = T; rest = Cons T} +List(T). + push|U :> T|(self, x: U): List T = Self. new {head = x; rest = self} + upcast(self, U :> T): List U = self +# TypeWarning: `U` in the `.push` cannot take anything other than `U == T`. Replace `U` with `T`. +# TypeWarning: `U` in the `.upcast` cannot take anything other than `U == T`. Replace `U` with `T`. +``` + +Both the constraint `U <: T` and the modification specification `U :> T` are satisfied only when `U == T`. So this designation doesn't make much sense. +Only "upcasts such that `U == T`" = "upcasts that do not change where `U`" are actually allowed. + +## Appendix: Modification of user-defined types + +Mutations of user-defined types are immutable by default. However, you can also specify mutability with the `Inputs/Outputs` marker trait. +If you specify `Inputs(T)`, the type is contravariant with respect to `T`. +If you specify `Outputs(T)`, the type is covariant with respect to `T`. + +``` erg +K T = Class(...) +assert not K(Str) <= K(Object) +assert not K(Str) >= K(Object) + +InputStream T = Class ..., Impl := Inputs(T) +# A stream that accepts Objects can also be considered to accept Strs +assert InputStream(Str) > InputStream(Object) + +OutputStream T = Class ..., Impl := Outputs(T) +# A stream that outputs a Str can also be considered to output an Object +assert OutputStream(Str) < OutputStream(Object) +``` \ No newline at end of file diff --git a/doc/EN/syntax/type/advanced/widening.md b/doc/EN/syntax/type/advanced/widening.md new file mode 100644 index 00000000..7d0a9b47 --- /dev/null +++ b/doc/EN/syntax/type/advanced/widening.md @@ -0,0 +1,92 @@ +# Type Widening + +For example, define the polycorrelation coefficient as follows. + +``` erg +ids|T|(x: T, y: T) = x, y +``` + +There's nothing wrong with assigning a pair of instances of the same class. +When you assign an instance pair of another class that has a containment relationship, it is upcast to the larger one and becomes the same type. +Also, it is easy to understand that an error will occur if another class that is not in the containment relationship is assigned. + +``` erg +assert ids(1, 2) == (1, 2) +assert ids(1, 2.0) == (1.0, 2.0) +ids(1, "a") #TypeError +``` + +Now, what about types that have different derived types? + +``` erg +i: Int or Str +j: Int or NoneType +ids(i, j) # ? +``` + +Before explaining this, we have to focus on the fact that Erg's type system doesn't actually look at (runtime) classes. + +``` erg +1: {__valueclass_tag__ = Phantom Int} +2: {__valueclass_tag__ = Phantom Int} +2.0: {__valueclass_tag__ = Phantom Ratio} +"a": {__valueclass_tag__ = Phantom Str} +ids(1, 2): {__valueclass_tag__ = Phantom Int} and {__valueclass_tag__ = Phantom Int} == {__valueclass_tag__ = Phantom Int} +ids(1, 2.0): {__valueclass_tag__ = Phantom Int} and {__valueclass_tag__ = Phantom Ratio} == {__valueclass_tag__ = Phantom Ratio} # Int < Ratio +ids(1, "a"): {__valueclass_tag__ = Phantom Int} and {__valueclass_tag__ = Phantom Str} == Never # TypeError +``` + +I don't see the class because it may not be seen exactly, because in Erg the class of an object belongs to runtime information. +For example, the class of an `Int or Str` type object is either `Int` or `Str`, but you can only know which one it is by executing it. +Of course, the class of an object of type `Int` is defined as `Int`, but in this case as well, what is visible from the type system is the structural type `{__valueclass_tag__ = Int}` of `Int`. + +Now let's go back to another structured type example. In conclusion, the above code will result in a TypeError as the type does not match. +However, if you do type expansion with type annotations, compilation will pass. + +``` erg +i: Int or Str +j: Int or NoneType +ids(i, j) # TypeError: types of i and j not matched +# hint: try type widening (e.g. ids