This commit is contained in:
Shunsuke Shibayama 2022-10-09 18:07:52 +09:00
commit befe2cf835
15 changed files with 148 additions and 59 deletions

58
.github/ISSUE_TEMPLATE/bug_report.yaml vendored Normal file
View file

@ -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`)

View file

@ -1,13 +1,13 @@
[package] [package]
name = "erg_common" name = "erg_common"
version = "0.5.8"
description = "A common components library of Erg" description = "A common components library of Erg"
authors = ["erg-lang team <moderation.erglang@gmail.com>"] version.workspace = true
license = "MIT OR Apache-2.0" authors.workspace = true
edition = "2021" license.workspace = true
repository = "https://github.com/erg-lang/erg/tree/main/src/erg_common" edition.workspace = true
documentation = "https://docs.rs/erg_common" repository.workspace = true
homepage = "https://erg-lang.github.io/" documentation.workspace = true
homepage.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -12,10 +12,18 @@ homepage.workspace = true
[features] [features]
# when "debug" feature is turned on, that of parser will also be turned on. # when "debug" feature is turned on, that of parser will also be turned on.
debug = [ "erg_common/debug", "erg_parser/debug", "erg_type/debug" ] debug = ["erg_common/debug", "erg_parser/debug", "erg_type/debug"]
japanese = [ "erg_common/japanese", "erg_parser/japanese", "erg_type/japanese" ] japanese = ["erg_common/japanese", "erg_parser/japanese", "erg_type/japanese"]
simplified_chinese = [ "erg_common/simplified_chinese", "erg_parser/simplified_chinese", "erg_type/simplified_chinese" ] simplified_chinese = [
traditional_chinese = [ "erg_common/traditional_chinese", "erg_parser/traditional_chinese", "erg_type/traditional_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] [dependencies]
erg_common = { version = "0.5.8", path = "../erg_common" } erg_common = { version = "0.5.8", path = "../erg_common" }

View file

@ -2040,7 +2040,7 @@ impl CodeGenerator {
self.stack_dec(); self.stack_dec();
self.emit_pop_top(); self.emit_pop_top();
self.emit_global_import_items( self.emit_global_import_items(
Identifier::public("prelude"), Identifier::public("_erg_std_prelude"),
vec![( vec![(
Identifier::public("in_operator"), Identifier::public("in_operator"),
Some(Identifier::private("#in_operator")), Some(Identifier::private("#in_operator")),

View file

@ -850,6 +850,9 @@ impl Context {
/// returns union of two types (A or B) /// returns union of two types (A or B)
pub(crate) fn union(&self, lhs: &Type, rhs: &Type) -> Type { pub(crate) fn union(&self, lhs: &Type, rhs: &Type) -> Type {
if lhs == rhs {
return lhs.clone();
}
// `?T or ?U` will not be unified // `?T or ?U` will not be unified
// `Set!(?T, 3) or Set(?T, 3)` wii be unified to Set(?T, 3) // `Set!(?T, 3) or Set(?T, 3)` wii be unified to Set(?T, 3)
if !lhs.is_unbound_var() && !rhs.is_unbound_var() { if !lhs.is_unbound_var() && !rhs.is_unbound_var() {
@ -889,6 +892,9 @@ impl Context {
/// returns intersection of two types (A and B) /// returns intersection of two types (A and B)
pub(crate) fn intersection(&self, lhs: &Type, rhs: &Type) -> Type { pub(crate) fn intersection(&self, lhs: &Type, rhs: &Type) -> Type {
if lhs == rhs {
return lhs.clone();
}
// ?T and ?U will not be unified // ?T and ?U will not be unified
if !lhs.is_unbound_var() && !rhs.is_unbound_var() { if !lhs.is_unbound_var() && !rhs.is_unbound_var() {
match (self.supertype_of(lhs, rhs), self.subtype_of(lhs, rhs)) { match (self.supertype_of(lhs, rhs), self.subtype_of(lhs, rhs)) {

View file

@ -1373,6 +1373,10 @@ impl Context {
let mut record_type = Self::builtin_mono_class("RecordType", 2); let mut record_type = Self::builtin_mono_class("RecordType", 2);
record_type.register_superclass(builtin_mono("Record"), &record); record_type.register_superclass(builtin_mono("Record"), &record);
record_type.register_superclass(builtin_mono("Type"), &type_); 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 */ /* Float_mut */
let mut float_mut = Self::builtin_mono_class("Float!", 2); let mut float_mut = Self::builtin_mono_class("Float!", 2);
float_mut.register_superclass(Float, &float); 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("Record"), record, Const);
self.register_builtin_type(builtin_mono("RecordType"), record_type, 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("Int!"), int_mut, Const);
self.register_builtin_type(builtin_mono("Nat!"), nat_mut, Const); self.register_builtin_type(builtin_mono("Nat!"), nat_mut, Const);
self.register_builtin_type(builtin_mono("Float!"), float_mut, Const); self.register_builtin_type(builtin_mono("Float!"), float_mut, Const);

View file

@ -17,7 +17,7 @@ use erg_parser::ast::{self, Identifier};
use erg_parser::token::Token; use erg_parser::token::Token;
use erg_type::constructors::{ 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::free::Constraint;
use erg_type::typaram::TyParam; use erg_type::typaram::TyParam;
@ -1454,7 +1454,7 @@ impl Context {
} }
Type::Poly { path, name, .. } => { Type::Poly { path, name, .. } => {
if self.path() == path { 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); return Some(ctx);
} }
} }
@ -1469,7 +1469,7 @@ impl Context {
.and_then(|cache| cache.ref_ctx(path.as_path())) .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); return Some(ctx);
} }
} }
@ -1516,16 +1516,10 @@ impl Context {
return Some(res); return Some(res);
} }
} }
Type::Or(l, r) => { Type::Or(_l, _r) => {
let lctx = self.get_nominal_type_ctx(l)?; if let Some(ctx) = self.get_nominal_type_ctx(&builtin_poly("Or", vec![])) {
let rctx = self.get_nominal_type_ctx(r)?; return Some(ctx);
// 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,
};
} }
// FIXME: `F()`などの場合、実際は引数が省略されていてもmonomorphicになる // FIXME: `F()`などの場合、実際は引数が省略されていてもmonomorphicになる
other if other.is_monomorphic() => { other if other.is_monomorphic() => {

View file

@ -2,7 +2,8 @@ discard _x = None
discard 1 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: if c:
do then do then
do else do else

View file

@ -1,19 +1,19 @@
[package] [package]
name = "erg_parser" name = "erg_parser"
version = "0.5.8"
description = "The Erg parser" description = "The Erg parser"
authors = ["erg-lang team <moderation.erglang@gmail.com>"] version.workspace = true
license = "MIT OR Apache-2.0" authors.workspace = true
edition = "2021" license.workspace = true
repository = "https://github.com/erg-lang/erg/tree/main/src/erg_compiler/erg_parser" edition.workspace = true
documentation = "https://docs.rs/erg_parser" repository.workspace = true
homepage = "https://erg-lang.github.io/" documentation.workspace = true
homepage.workspace = true
[features] [features]
debug = [ "erg_common/debug" ] debug = ["erg_common/debug"]
japanese = [ "erg_common/japanese" ] japanese = ["erg_common/japanese"]
simplified_chinese = [ "erg_common/simplified_chinese" ] simplified_chinese = ["erg_common/simplified_chinese"]
traditional_chinese = [ "erg_common/traditional_chinese" ] traditional_chinese = ["erg_common/traditional_chinese"]
[dependencies] [dependencies]
erg_common = { version = "0.5.8", path = "../erg_common" } erg_common = { version = "0.5.8", path = "../erg_common" }

View file

@ -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(); self.skip();
let index = self let index = self
.try_reduce_expr(false, false) .try_reduce_expr(false, false)

View file

@ -1,21 +1,21 @@
[package] [package]
name = "erg_type" name = "erg_type"
version = "0.5.8"
description = "APIs for Erg types" description = "APIs for Erg types"
authors = ["erg-lang team <moderation.erglang@gmail.com>"] version.workspace = true
license = "MIT OR Apache-2.0" authors.workspace = true
edition = "2021" license.workspace = true
repository = "https://github.com/erg-lang/erg/tree/main/compiler/erg_type" edition.workspace = true
documentation = "https://docs.rs/erg_type" repository.workspace = true
homepage = "https://erg-lang.github.io/" documentation.workspace = true
homepage.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features] [features]
debug = [ "erg_common/debug" ] debug = ["erg_common/debug"]
japanese = [ "erg_common/japanese" ] japanese = ["erg_common/japanese"]
simplified_chinese = [ "erg_common/simplified_chinese" ] simplified_chinese = ["erg_common/simplified_chinese"]
traditional_chinese = [ "erg_common/traditional_chinese" ] traditional_chinese = ["erg_common/traditional_chinese"]
[dependencies] [dependencies]
erg_common = { version = "0.5.8", path = "../erg_common" } erg_common = { version = "0.5.8", path = "../erg_common" }

View file

@ -1922,11 +1922,6 @@ impl Type {
matches!(self, Self::FreeVar(_)) 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 { pub const fn is_callable(&self) -> bool {
matches!(self, Self::Subr { .. } | Self::Callable { .. }) 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()) 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 { pub fn has_qvar(&self) -> bool {
match self { match self {
Self::MonoQVar(_) | Self::PolyQVar { .. } => true, 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 { pub fn is_cachable(&self) -> bool {
match self { match self {
Self::FreeVar(_) => false, Self::FreeVar(_) => false,

View file

@ -1,6 +1,6 @@
for! 1..<100, i => for! 1..<100, i =>
match (i % 3, i % 5): match [i % 3, i % 5]:
(0, 0) => print! "FizzBuzz" [0, 0] => print! "FizzBuzz"
(0, _) => print! "Fizz" [0, _] => print! "Fizz"
(_, 0) => print! "Buzz" [_, 0] => print! "Buzz"
(_, _) => print! i [_, _] => print! i

View file

@ -56,6 +56,11 @@ fn exec_move_check() -> Result<(), ()> {
expect_failure("examples/move_check.er") expect_failure("examples/move_check.er")
} }
#[test]
fn exec_prelude() -> Result<(), ()> {
expect_success("compiler/erg_compiler/std/prelude.er")
}
#[test] #[test]
fn exec_quantified() -> Result<(), ()> { fn exec_quantified() -> Result<(), ()> {
expect_success("examples/quantified.er") expect_success("examples/quantified.er")