diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml new file mode 100644 index 00000000..2d210cad --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -0,0 +1,58 @@ +name: 🐛 Bug report +description: Create a report to help us improve +labels: + - bug +body: + - type: textarea + attributes: + label: Describe the bug? + validations: + required: true + + - type: textarea + attributes: + label: Reproducible code + validations: + required: false + + - type: textarea + attributes: + label: Expected result + validations: + required: false + + - type: textarea + attributes: + label: Actual result + validations: + required: false + + - type: textarea + attributes: + label: Additional context + validations: + required: false + + - type: input + attributes: + label: Erg version + validations: + required: true + + - type: input + attributes: + label: Python version + validations: + required: false + + - type: dropdown + attributes: + label: os + options: + - Windows 10 + - Windows 11 + - MacOS 12 (Monterey) + - MacOS 11 (Big Sur) + - Ubuntu + - Linux(other distro) + - Other (write in `Additional context`) diff --git a/compiler/erg_common/Cargo.toml b/compiler/erg_common/Cargo.toml index b8c3f415..305f0b34 100644 --- a/compiler/erg_common/Cargo.toml +++ b/compiler/erg_common/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "erg_common" -version = "0.5.8" description = "A common components library of Erg" -authors = ["erg-lang team "] -license = "MIT OR Apache-2.0" -edition = "2021" -repository = "https://github.com/erg-lang/erg/tree/main/src/erg_common" -documentation = "https://docs.rs/erg_common" -homepage = "https://erg-lang.github.io/" +version.workspace = true +authors.workspace = true +license.workspace = true +edition.workspace = true +repository.workspace = true +documentation.workspace = true +homepage.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/compiler/erg_compiler/Cargo.toml b/compiler/erg_compiler/Cargo.toml index 1658fca2..e2f5a6c3 100644 --- a/compiler/erg_compiler/Cargo.toml +++ b/compiler/erg_compiler/Cargo.toml @@ -12,10 +12,18 @@ homepage.workspace = true [features] # when "debug" feature is turned on, that of parser will also be turned on. -debug = [ "erg_common/debug", "erg_parser/debug", "erg_type/debug" ] -japanese = [ "erg_common/japanese", "erg_parser/japanese", "erg_type/japanese" ] -simplified_chinese = [ "erg_common/simplified_chinese", "erg_parser/simplified_chinese", "erg_type/simplified_chinese" ] -traditional_chinese = [ "erg_common/traditional_chinese", "erg_parser/traditional_chinese", "erg_type/traditional_chinese" ] +debug = ["erg_common/debug", "erg_parser/debug", "erg_type/debug"] +japanese = ["erg_common/japanese", "erg_parser/japanese", "erg_type/japanese"] +simplified_chinese = [ + "erg_common/simplified_chinese", + "erg_parser/simplified_chinese", + "erg_type/simplified_chinese", +] +traditional_chinese = [ + "erg_common/traditional_chinese", + "erg_parser/traditional_chinese", + "erg_type/traditional_chinese", +] [dependencies] erg_common = { version = "0.5.8", path = "../erg_common" } diff --git a/compiler/erg_compiler/codegen.rs b/compiler/erg_compiler/codegen.rs index 0929f794..9a578702 100644 --- a/compiler/erg_compiler/codegen.rs +++ b/compiler/erg_compiler/codegen.rs @@ -2040,7 +2040,7 @@ impl CodeGenerator { self.stack_dec(); self.emit_pop_top(); self.emit_global_import_items( - Identifier::public("prelude"), + Identifier::public("_erg_std_prelude"), vec![( Identifier::public("in_operator"), Some(Identifier::private("#in_operator")), diff --git a/compiler/erg_compiler/context/compare.rs b/compiler/erg_compiler/context/compare.rs index f695ecb3..a5aca769 100644 --- a/compiler/erg_compiler/context/compare.rs +++ b/compiler/erg_compiler/context/compare.rs @@ -850,6 +850,9 @@ impl Context { /// returns union of two types (A or B) pub(crate) fn union(&self, lhs: &Type, rhs: &Type) -> Type { + if lhs == rhs { + return lhs.clone(); + } // `?T or ?U` will not be unified // `Set!(?T, 3) or Set(?T, 3)` wii be unified to Set(?T, 3) if !lhs.is_unbound_var() && !rhs.is_unbound_var() { @@ -889,6 +892,9 @@ impl Context { /// returns intersection of two types (A and B) pub(crate) fn intersection(&self, lhs: &Type, rhs: &Type) -> Type { + if lhs == rhs { + return lhs.clone(); + } // ?T and ?U will not be unified if !lhs.is_unbound_var() && !rhs.is_unbound_var() { match (self.supertype_of(lhs, rhs), self.subtype_of(lhs, rhs)) { diff --git a/compiler/erg_compiler/context/initialize/mod.rs b/compiler/erg_compiler/context/initialize/mod.rs index 7365fb37..1b631095 100644 --- a/compiler/erg_compiler/context/initialize/mod.rs +++ b/compiler/erg_compiler/context/initialize/mod.rs @@ -1373,6 +1373,10 @@ impl Context { let mut record_type = Self::builtin_mono_class("RecordType", 2); record_type.register_superclass(builtin_mono("Record"), &record); record_type.register_superclass(builtin_mono("Type"), &type_); + /* Or (true or type) */ + let or_t = builtin_poly("Or", vec![ty_tp(mono_q("L")), ty_tp(mono_q("R"))]); + let mut or = Self::builtin_poly_class("Or", vec![PS::t_nd("L"), PS::t_nd("R")], 2); + or.register_superclass(Obj, &obj); /* Float_mut */ let mut float_mut = Self::builtin_mono_class("Float!", 2); float_mut.register_superclass(Float, &float); @@ -1744,6 +1748,7 @@ impl Context { ); self.register_builtin_type(builtin_mono("Record"), record, Const); self.register_builtin_type(builtin_mono("RecordType"), record_type, Const); + self.register_builtin_type(or_t, or, Const); self.register_builtin_type(builtin_mono("Int!"), int_mut, Const); self.register_builtin_type(builtin_mono("Nat!"), nat_mut, Const); self.register_builtin_type(builtin_mono("Float!"), float_mut, Const); diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index b138f31c..46f9bd7e 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -17,7 +17,7 @@ use erg_parser::ast::{self, Identifier}; use erg_parser::token::Token; use erg_type::constructors::{ - anon, builtin_mono, free_var, func, module, mono_proj, subr_t, v_enum, + anon, builtin_mono, builtin_poly, free_var, func, module, mono_proj, subr_t, v_enum, }; use erg_type::free::Constraint; use erg_type::typaram::TyParam; @@ -1454,7 +1454,7 @@ impl Context { } Type::Poly { path, name, .. } => { if self.path() == path { - if let Some((_, ctx)) = self.rec_get_mono_type(name) { + if let Some((_, ctx)) = self.rec_get_poly_type(name) { return Some(ctx); } } @@ -1469,7 +1469,7 @@ impl Context { .and_then(|cache| cache.ref_ctx(path.as_path())) }) { - if let Some((_, ctx)) = ctx.rec_get_mono_type(name) { + if let Some((_, ctx)) = ctx.rec_get_poly_type(name) { return Some(ctx); } } @@ -1516,16 +1516,10 @@ impl Context { return Some(res); } } - Type::Or(l, r) => { - let lctx = self.get_nominal_type_ctx(l)?; - let rctx = self.get_nominal_type_ctx(r)?; - // use smaller context - return match (self.supertype_of(l, r), self.supertype_of(r, l)) { - (true, true) => Some(lctx), - (true, false) => Some(rctx), - (false, true) => Some(lctx), - (false, false) => None, - }; + Type::Or(_l, _r) => { + if let Some(ctx) = self.get_nominal_type_ctx(&builtin_poly("Or", vec![])) { + return Some(ctx); + } } // FIXME: `F()`などの場合、実際は引数が省略されていてもmonomorphicになる other if other.is_monomorphic() => { diff --git a/compiler/erg_compiler/std/prelude.py b/compiler/erg_compiler/std/_erg_std_prelude.py similarity index 100% rename from compiler/erg_compiler/std/prelude.py rename to compiler/erg_compiler/std/_erg_std_prelude.py diff --git a/compiler/erg_compiler/std/prelude.er b/compiler/erg_compiler/std/prelude.er index b0c0df8f..5f01c9ea 100644 --- a/compiler/erg_compiler/std/prelude.er +++ b/compiler/erg_compiler/std/prelude.er @@ -2,7 +2,8 @@ discard _x = None discard 1 -cond c, then, else = +# if: |T, U|(Bool, T, U) -> T or U +cond|T: Type|(c: Bool, then: T, else: T): T = if c: do then do else diff --git a/compiler/erg_parser/Cargo.toml b/compiler/erg_parser/Cargo.toml index 1d33bb67..38288345 100644 --- a/compiler/erg_parser/Cargo.toml +++ b/compiler/erg_parser/Cargo.toml @@ -1,19 +1,19 @@ [package] name = "erg_parser" -version = "0.5.8" description = "The Erg parser" -authors = ["erg-lang team "] -license = "MIT OR Apache-2.0" -edition = "2021" -repository = "https://github.com/erg-lang/erg/tree/main/src/erg_compiler/erg_parser" -documentation = "https://docs.rs/erg_parser" -homepage = "https://erg-lang.github.io/" +version.workspace = true +authors.workspace = true +license.workspace = true +edition.workspace = true +repository.workspace = true +documentation.workspace = true +homepage.workspace = true [features] -debug = [ "erg_common/debug" ] -japanese = [ "erg_common/japanese" ] -simplified_chinese = [ "erg_common/simplified_chinese" ] -traditional_chinese = [ "erg_common/traditional_chinese" ] +debug = ["erg_common/debug"] +japanese = ["erg_common/japanese"] +simplified_chinese = ["erg_common/simplified_chinese"] +traditional_chinese = ["erg_common/traditional_chinese"] [dependencies] erg_common = { version = "0.5.8", path = "../erg_common" } diff --git a/compiler/erg_parser/parse.rs b/compiler/erg_parser/parse.rs index 739499ac..78d70a9c 100644 --- a/compiler/erg_parser/parse.rs +++ b/compiler/erg_parser/parse.rs @@ -469,7 +469,8 @@ impl Parser { } } } - Some(t) if t.is(LSqBr) => { + // x[...] (`x [...]` will interpreted as `x([...])`) + Some(t) if t.is(LSqBr) && acc.col_end().unwrap() == t.col_begin().unwrap() => { self.skip(); let index = self .try_reduce_expr(false, false) diff --git a/compiler/erg_type/Cargo.toml b/compiler/erg_type/Cargo.toml index 39234fea..3727d03c 100644 --- a/compiler/erg_type/Cargo.toml +++ b/compiler/erg_type/Cargo.toml @@ -1,21 +1,21 @@ [package] name = "erg_type" -version = "0.5.8" description = "APIs for Erg types" -authors = ["erg-lang team "] -license = "MIT OR Apache-2.0" -edition = "2021" -repository = "https://github.com/erg-lang/erg/tree/main/compiler/erg_type" -documentation = "https://docs.rs/erg_type" -homepage = "https://erg-lang.github.io/" +version.workspace = true +authors.workspace = true +license.workspace = true +edition.workspace = true +repository.workspace = true +documentation.workspace = true +homepage.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] -debug = [ "erg_common/debug" ] -japanese = [ "erg_common/japanese" ] -simplified_chinese = [ "erg_common/simplified_chinese" ] -traditional_chinese = [ "erg_common/traditional_chinese" ] +debug = ["erg_common/debug"] +japanese = ["erg_common/japanese"] +simplified_chinese = ["erg_common/simplified_chinese"] +traditional_chinese = ["erg_common/traditional_chinese"] [dependencies] erg_common = { version = "0.5.8", path = "../erg_common" } diff --git a/compiler/erg_type/lib.rs b/compiler/erg_type/lib.rs index 1aa7a7d8..ea9d161c 100644 --- a/compiler/erg_type/lib.rs +++ b/compiler/erg_type/lib.rs @@ -1922,11 +1922,6 @@ impl Type { matches!(self, Self::FreeVar(_)) } - /// FIXME: `Int or Str` should be monomorphic - pub fn is_monomorphic(&self) -> bool { - matches!(self.typarams_len(), Some(0) | None) - } - pub const fn is_callable(&self) -> bool { matches!(self, Self::Subr { .. } | Self::Callable { .. }) } @@ -1935,6 +1930,18 @@ impl Type { matches!(self, Self::FreeVar(fv) if fv.is_unbound() || fv.crack().is_unbound_var()) } + /// See also: `is_monomorphized` + pub fn is_monomorphic(&self) -> bool { + matches!(self.typarams_len(), Some(0) | None) + } + + /// `Set(Int, 3)` is not monomorphic but monomorphized + pub fn is_monomorphized(&self) -> bool { + matches!(self.typarams_len(), Some(0) | None) + || (self.has_no_qvar() && self.has_no_unbound_var()) + } + + /// if the type is polymorphic pub fn has_qvar(&self) -> bool { match self { Self::MonoQVar(_) | Self::PolyQVar { .. } => true, @@ -1972,6 +1979,10 @@ impl Type { } } + pub fn has_no_qvar(&self) -> bool { + !self.has_qvar() + } + pub fn is_cachable(&self) -> bool { match self { Self::FreeVar(_) => false, diff --git a/tests/fizzbuzz.er b/tests/fizzbuzz.er index afcf9b73..b725528e 100644 --- a/tests/fizzbuzz.er +++ b/tests/fizzbuzz.er @@ -1,6 +1,6 @@ for! 1..<100, i => - match (i % 3, i % 5): - (0, 0) => print! "FizzBuzz" - (0, _) => print! "Fizz" - (_, 0) => print! "Buzz" - (_, _) => print! i + match [i % 3, i % 5]: + [0, 0] => print! "FizzBuzz" + [0, _] => print! "Fizz" + [_, 0] => print! "Buzz" + [_, _] => print! i diff --git a/tests/test.rs b/tests/test.rs index 0766dc6c..90ca0349 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -56,6 +56,11 @@ fn exec_move_check() -> Result<(), ()> { expect_failure("examples/move_check.er") } +#[test] +fn exec_prelude() -> Result<(), ()> { + expect_success("compiler/erg_compiler/std/prelude.er") +} + #[test] fn exec_quantified() -> Result<(), ()> { expect_success("examples/quantified.er")