mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 12:24:45 +00:00
WIP
This commit is contained in:
commit
befe2cf835
15 changed files with 148 additions and 59 deletions
58
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
Normal file
58
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
Normal 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`)
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,16 @@ homepage.workspace = true
|
||||||
# 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" }
|
||||||
|
|
|
@ -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")),
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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() => {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
[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"]
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
[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
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue