Merge branch 'erg-lang:main' into fix/md_links

This commit is contained in:
Slug 2022-09-27 15:25:07 +09:00 committed by GitHub
commit e8d731a652
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
53 changed files with 1492 additions and 494 deletions

10
Cargo.lock generated
View file

@ -15,7 +15,7 @@ dependencies = [
[[package]] [[package]]
name = "erg" name = "erg"
version = "0.5.1" version = "0.5.5-nightly.1"
dependencies = [ dependencies = [
"erg_common", "erg_common",
"erg_compiler", "erg_compiler",
@ -25,14 +25,14 @@ dependencies = [
[[package]] [[package]]
name = "erg_common" name = "erg_common"
version = "0.5.1" version = "0.5.5-nightly.1"
dependencies = [ dependencies = [
"atty", "atty",
] ]
[[package]] [[package]]
name = "erg_compiler" name = "erg_compiler"
version = "0.5.1" version = "0.5.5-nightly.1"
dependencies = [ dependencies = [
"erg_common", "erg_common",
"erg_parser", "erg_parser",
@ -41,14 +41,14 @@ dependencies = [
[[package]] [[package]]
name = "erg_parser" name = "erg_parser"
version = "0.5.1" version = "0.5.5-nightly.1"
dependencies = [ dependencies = [
"erg_common", "erg_common",
] ]
[[package]] [[package]]
name = "erg_type" name = "erg_type"
version = "0.5.1" version = "0.5.5-nightly.1"
dependencies = [ dependencies = [
"erg_common", "erg_common",
"erg_parser", "erg_parser",

View file

@ -1,8 +1,8 @@
[package] [package]
name = "erg" name = "erg"
version = "0.5.1" version = "0.5.5-nightly.1"
description = "The Erg programming language" description = "The Erg programming language"
authors = ["Shunsuke Shibayama <sbym1346@gmail.com>"] authors = ["erg-lang team <moderation.erglang@gmail.com>"]
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
edition = "2021" edition = "2021"
repository = "https://github.com/erg-lang/erg" repository = "https://github.com/erg-lang/erg"
@ -46,10 +46,10 @@ traditional_chinese = [
] ]
[dependencies] [dependencies]
erg_common = { version = "0.5.1", path = "./compiler/erg_common" } erg_common = { version = "0.5.5-nightly.1", path = "./compiler/erg_common" }
erg_parser = { version = "0.5.1", path = "./compiler/erg_parser" } erg_parser = { version = "0.5.5-nightly.1", path = "./compiler/erg_parser" }
erg_compiler = { version = "0.5.1", path = "./compiler/erg_compiler" } erg_compiler = { version = "0.5.5-nightly.1", path = "./compiler/erg_compiler" }
erg_type = { version = "0.5.1", path = "./compiler/erg_type" } erg_type = { version = "0.5.5-nightly.1", path = "./compiler/erg_type" }
# [workspace] # [workspace]
# member = ["cm", "dyne"] # member = ["cm", "dyne"]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "erg_common" name = "erg_common"
version = "0.5.1" version = "0.5.5-nightly.1"
description = "A common components library of Erg" description = "A common components library of Erg"
authors = ["erg-lang team <moderation.erglang@gmail.com>"] authors = ["erg-lang team <moderation.erglang@gmail.com>"]
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"

View file

@ -148,14 +148,6 @@ pub struct ErgConfig {
impl Default for ErgConfig { impl Default for ErgConfig {
#[inline] #[inline]
fn default() -> Self { fn default() -> Self {
let is_stdin_piped: bool = atty::isnt(atty::Stream::Stdin);
let input = if is_stdin_piped {
let mut buffer = String::new();
stdin().read_to_string(&mut buffer).unwrap();
Input::Pipe(buffer)
} else {
Input::REPL
};
Self { Self {
mode: "exec", mode: "exec",
opt_level: 1, opt_level: 1,
@ -163,7 +155,7 @@ impl Default for ErgConfig {
python_ver: None, python_ver: None,
py_server_timeout: 10, py_server_timeout: 10,
quiet_startup: false, quiet_startup: false,
input, input: Input::REPL,
module: "<module>", module: "<module>",
verbose: 2, verbose: 2,
ps1: ">>> ", ps1: ">>> ",
@ -173,6 +165,14 @@ impl Default for ErgConfig {
} }
impl ErgConfig { impl ErgConfig {
pub fn with_path(path: PathBuf) -> Self {
Self {
module: Box::leak(path.to_str().unwrap().to_string().into_boxed_str()),
input: Input::File(path),
..ErgConfig::default()
}
}
/// cloneのエイリアス(実際のcloneコストは低いので) /// cloneのエイリアス(実際のcloneコストは低いので)
#[inline] #[inline]
pub fn copy(&self) -> Self { pub fn copy(&self) -> Self {
@ -253,6 +253,17 @@ impl ErgConfig {
} }
} }
} }
if cfg.input == Input::REPL {
let is_stdin_piped = atty::isnt(atty::Stream::Stdin);
let input = if is_stdin_piped {
let mut buffer = String::new();
stdin().read_to_string(&mut buffer).unwrap();
Input::Pipe(buffer)
} else {
Input::REPL
};
cfg.input = input;
}
cfg cfg
} }
} }

View file

@ -564,6 +564,19 @@ pub trait ErrorDisplay {
} }
} }
#[macro_export]
macro_rules! impl_display_and_error {
($Strc: ident) => {
impl std::fmt::Display for $Strc {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
$crate::error::ErrorDisplay::format(self, f)
}
}
impl std::error::Error for $Strc {}
};
}
pub trait MultiErrorDisplay<Item: ErrorDisplay>: Stream<Item> { pub trait MultiErrorDisplay<Item: ErrorDisplay>: Stream<Item> {
fn fmt_all_stderr(&self) { fn fmt_all_stderr(&self) {
for err in self.iter() { for err in self.iter() {

View file

@ -33,3 +33,19 @@ pub fn levenshtein(lhs: &str, rhs: &str) -> usize {
} }
table[l_len][r_len] table[l_len][r_len]
} }
pub fn get_similar_name<'a, I: Iterator<Item = &'a str>>(
candidates: I,
name: &str,
) -> Option<&'a str> {
if name.len() <= 1 {
return None;
}
let most_similar_name = candidates.min_by_key(|v| levenshtein(v, name))?;
let len = most_similar_name.len();
if levenshtein(most_similar_name, name) >= len / 2 {
None
} else {
Some(most_similar_name)
}
}

View file

@ -1,6 +1,6 @@
[package] [package]
name = "erg_compiler" name = "erg_compiler"
version = "0.5.1" version = "0.5.5-nightly.1"
description = "Centimetre: the Erg compiler" description = "Centimetre: the Erg compiler"
authors = ["erg-lang team <moderation.erglang@gmail.com>"] authors = ["erg-lang team <moderation.erglang@gmail.com>"]
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
@ -17,9 +17,9 @@ simplified_chinese = [ "erg_common/simplified_chinese", "erg_parser/simplified_c
traditional_chinese = [ "erg_common/traditional_chinese", "erg_parser/traditional_chinese", "erg_type/traditional_chinese" ] traditional_chinese = [ "erg_common/traditional_chinese", "erg_parser/traditional_chinese", "erg_type/traditional_chinese" ]
[dependencies] [dependencies]
erg_common = { version = "0.5.1", path = "../erg_common" } erg_common = { version = "0.5.5-nightly.1", path = "../erg_common" }
erg_parser = { version = "0.5.1", path = "../erg_parser" } erg_parser = { version = "0.5.5-nightly.1", path = "../erg_parser" }
erg_type = { version = "0.5.1", path = "../erg_type" } erg_type = { version = "0.5.5-nightly.1", path = "../erg_type" }
[lib] [lib]
path = "lib.rs" path = "lib.rs"

View file

@ -13,7 +13,6 @@ use crate::hir::HIR;
use crate::lower::ASTLowerer; use crate::lower::ASTLowerer;
use crate::mod_cache::SharedModuleCache; use crate::mod_cache::SharedModuleCache;
use crate::ownercheck::OwnershipChecker; use crate::ownercheck::OwnershipChecker;
use crate::reorder::Reorderer;
/// Summarize lowering, side-effect checking, and ownership checking /// Summarize lowering, side-effect checking, and ownership checking
#[derive(Debug)] #[derive(Debug)]
@ -28,7 +27,12 @@ impl Runnable for HIRBuilder {
const NAME: &'static str = "Erg HIR builder"; const NAME: &'static str = "Erg HIR builder";
fn new(cfg: ErgConfig) -> Self { fn new(cfg: ErgConfig) -> Self {
HIRBuilder::new_with_cache(cfg, Str::ever("<module>"), SharedModuleCache::new()) HIRBuilder::new_with_cache(
cfg,
Str::ever("<module>"),
SharedModuleCache::new(),
SharedModuleCache::new(),
)
} }
#[inline] #[inline]
@ -62,9 +66,10 @@ impl HIRBuilder {
cfg: ErgConfig, cfg: ErgConfig,
mod_name: S, mod_name: S,
mod_cache: SharedModuleCache, mod_cache: SharedModuleCache,
py_mod_cache: SharedModuleCache,
) -> Self { ) -> Self {
Self { Self {
lowerer: ASTLowerer::new_with_cache(cfg, mod_name, mod_cache), lowerer: ASTLowerer::new_with_cache(cfg, mod_name, mod_cache, py_mod_cache),
ownership_checker: OwnershipChecker::new(), ownership_checker: OwnershipChecker::new(),
} }
} }
@ -99,9 +104,6 @@ impl HIRBuilder {
pub fn build(&mut self, src: String, mode: &str) -> Result<HIR, CompileErrors> { pub fn build(&mut self, src: String, mode: &str) -> Result<HIR, CompileErrors> {
let mut ast_builder = ASTBuilder::new(self.cfg().copy()); let mut ast_builder = ASTBuilder::new(self.cfg().copy());
let ast = ast_builder.build(src)?; let ast = ast_builder.build(src)?;
let ast = Reorderer::new()
.reorder(ast)
.map_err(|errs| self.convert(errs))?;
let hir = self.check(ast, mode)?; let hir = self.check(ast, mode)?;
Ok(hir) Ok(hir)
} }

View file

@ -1619,7 +1619,10 @@ impl CodeGenerator {
Expr::Compound(chunks) => { Expr::Compound(chunks) => {
self.emit_frameless_block(chunks, vec![]); self.emit_frameless_block(chunks, vec![]);
} }
// Dict, Decl Expr::TypeAsc(tasc) => {
self.emit_expr(*tasc.expr);
}
// Dict,
other => { other => {
self.errs.push(CompileError::feature_error( self.errs.push(CompileError::feature_error(
self.cfg.input.clone(), self.cfg.input.clone(),

View file

@ -103,8 +103,14 @@ impl Runnable for Compiler {
fn new(cfg: ErgConfig) -> Self { fn new(cfg: ErgConfig) -> Self {
let mod_cache = SharedModuleCache::new(); let mod_cache = SharedModuleCache::new();
let py_mod_cache = SharedModuleCache::new();
Self { Self {
builder: HIRBuilder::new_with_cache(cfg.copy(), "<module>", mod_cache.clone()), builder: HIRBuilder::new_with_cache(
cfg.copy(),
"<module>",
mod_cache.clone(),
py_mod_cache,
),
code_generator: CodeGenerator::new(cfg.copy()), code_generator: CodeGenerator::new(cfg.copy()),
mod_cache, mod_cache,
cfg, cfg,

View file

@ -606,10 +606,10 @@ impl Context {
self.poly_supertype_of(lhs, lparams, rparams) self.poly_supertype_of(lhs, lparams, rparams)
} }
(MonoQVar(name), r) | (PolyQVar { name, .. }, r) => { (MonoQVar(name), r) | (PolyQVar { name, .. }, r) => {
panic!("Not instantiated type variable: {name}, r: {r}") panic!("internal error: not instantiated type variable: '{name}, r: {r}")
} }
(l, MonoQVar(name)) | (l, PolyQVar { name, .. }) => { (l, MonoQVar(name)) | (l, PolyQVar { name, .. }) => {
panic!("Not instantiated type variable: {name}, l: {l}") panic!("internal error: not instantiated type variable: '{name}, l: {l}")
} }
(MonoProj { .. }, _) => todo!(), (MonoProj { .. }, _) => todo!(),
(_, MonoProj { .. }) => todo!(), (_, MonoProj { .. }) => todo!(),
@ -619,7 +619,11 @@ impl Context {
pub(crate) fn cyclic_supertype_of(&self, lhs: &FreeTyVar, rhs: &Type) -> bool { pub(crate) fn cyclic_supertype_of(&self, lhs: &FreeTyVar, rhs: &Type) -> bool {
// if `rhs` is {S: Str | ... }, `defined_rhs` will be Str // if `rhs` is {S: Str | ... }, `defined_rhs` will be Str
let (defined_rhs, _) = self.get_nominal_type_ctx(rhs).unwrap(); let defined_rhs = if let Some((defined_rhs, _)) = self.get_nominal_type_ctx(rhs) {
defined_rhs
} else {
return false;
};
if let Some(super_traits) = self.get_nominal_super_trait_ctxs(rhs) { if let Some(super_traits) = self.get_nominal_super_trait_ctxs(rhs) {
for (sup_trait, _) in super_traits { for (sup_trait, _) in super_traits {
if self.sup_conforms(lhs, defined_rhs, sup_trait) { if self.sup_conforms(lhs, defined_rhs, sup_trait) {
@ -846,18 +850,25 @@ impl Context {
| (Pred::GreaterEqual { .. }, Pred::LessEqual { .. }) | (Pred::GreaterEqual { .. }, Pred::LessEqual { .. })
| (Pred::NotEqual { .. }, Pred::Equal { .. }) => false, | (Pred::NotEqual { .. }, Pred::Equal { .. }) => false,
(Pred::Equal { rhs, .. }, Pred::Equal { rhs: rhs2, .. }) (Pred::Equal { rhs, .. }, Pred::Equal { rhs: rhs2, .. })
| (Pred::NotEqual { rhs, .. }, Pred::NotEqual { rhs: rhs2, .. }) => { | (Pred::NotEqual { rhs, .. }, Pred::NotEqual { rhs: rhs2, .. }) => self
self.try_cmp(rhs, rhs2).unwrap().is_eq() .try_cmp(rhs, rhs2)
} .map(|ord| ord.is_eq())
.unwrap_or(false),
// {T >= 0} :> {T >= 1}, {T >= 0} :> {T == 1} // {T >= 0} :> {T >= 1}, {T >= 0} :> {T == 1}
( (
Pred::GreaterEqual { rhs, .. }, Pred::GreaterEqual { rhs, .. },
Pred::GreaterEqual { rhs: rhs2, .. } | Pred::Equal { rhs: rhs2, .. }, Pred::GreaterEqual { rhs: rhs2, .. } | Pred::Equal { rhs: rhs2, .. },
) => self.try_cmp(rhs, rhs2).unwrap().is_le(), ) => self
.try_cmp(rhs, rhs2)
.map(|ord| ord.is_le())
.unwrap_or(false),
( (
Pred::LessEqual { rhs, .. }, Pred::LessEqual { rhs, .. },
Pred::LessEqual { rhs: rhs2, .. } | Pred::Equal { rhs: rhs2, .. }, Pred::LessEqual { rhs: rhs2, .. } | Pred::Equal { rhs: rhs2, .. },
) => self.try_cmp(rhs, rhs2).unwrap().is_ge(), ) => self
.try_cmp(rhs, rhs2)
.map(|ord| ord.is_ge())
.unwrap_or(false),
(lhs @ (Pred::GreaterEqual { .. } | Pred::LessEqual { .. }), Pred::And(l, r)) => { (lhs @ (Pred::GreaterEqual { .. } | Pred::LessEqual { .. }), Pred::And(l, r)) => {
self.is_super_pred_of(lhs, l) || self.is_super_pred_of(lhs, r) self.is_super_pred_of(lhs, l) || self.is_super_pred_of(lhs, r)
} }
@ -900,7 +911,7 @@ impl Context {
#[inline] #[inline]
fn type_of(&self, p: &TyParam) -> Type { fn type_of(&self, p: &TyParam) -> Type {
self.get_tp_t(p).unwrap() self.get_tp_t(p).unwrap_or(Type::Obj)
} }
// sup/inf({±∞}) = ±∞ではあるが、Inf/NegInfにはOrdを実装しない // sup/inf({±∞}) = ±∞ではあるが、Inf/NegInfにはOrdを実装しない
@ -915,7 +926,7 @@ impl Context {
if lhs == &refine.var => if lhs == &refine.var =>
{ {
if let Some(max) = &maybe_max { if let Some(max) = &maybe_max {
if self.try_cmp(rhs, max).unwrap() == Greater { if self.try_cmp(rhs, max) == Some(Greater) {
maybe_max = Some(rhs.clone()); maybe_max = Some(rhs.clone());
} }
} else { } else {
@ -943,7 +954,7 @@ impl Context {
if lhs == &refine.var => if lhs == &refine.var =>
{ {
if let Some(min) = &maybe_min { if let Some(min) = &maybe_min {
if self.try_cmp(rhs, min).unwrap() == Less { if self.try_cmp(rhs, min) == Some(Less) {
maybe_min = Some(rhs.clone()); maybe_min = Some(rhs.clone());
} }
} else { } else {

View file

@ -353,6 +353,7 @@ impl Context {
Str::ever("<unnamed record>"), Str::ever("<unnamed record>"),
2, 2,
self.mod_cache.clone(), self.mod_cache.clone(),
self.py_mod_cache.clone(),
self.clone(), self.clone(),
); );
for attr in record.attrs.iter() { for attr in record.attrs.iter() {
@ -424,6 +425,7 @@ impl Context {
Str::ever("<lambda>"), Str::ever("<lambda>"),
0, 0,
self.mod_cache.clone(), self.mod_cache.clone(),
self.py_mod_cache.clone(),
self.clone(), self.clone(),
); );
let return_t = lambda_ctx.eval_const_block(&lambda.body, None)?; let return_t = lambda_ctx.eval_const_block(&lambda.body, None)?;

View file

@ -3,7 +3,7 @@ use std::mem;
use erg_common::Str; use erg_common::Str;
use erg_common::astr::AtomicStr; use erg_common::astr::AtomicStr;
use erg_common::color::{RED, RESET}; use erg_common::color::{RED, RESET, YELLOW};
use erg_common::error::{ErrorCore, ErrorKind, Location}; use erg_common::error::{ErrorCore, ErrorKind, Location};
use erg_type::constructors::{and, builtin_mono, mono}; use erg_type::constructors::{and, builtin_mono, mono};
use erg_type::value::{EvalValueResult, TypeKind, TypeObj, ValueObj}; use erg_type::value::{EvalValueResult, TypeKind, TypeObj, ValueObj};
@ -18,20 +18,32 @@ pub fn class_func(
let require = args.remove_left_or_key("Requirement").ok_or_else(|| { let require = args.remove_left_or_key("Requirement").ok_or_else(|| {
ErrorCore::new( ErrorCore::new(
line!() as usize, line!() as usize,
ErrorKind::KeyError, ErrorKind::TypeError,
Location::Unknown, Location::Unknown,
AtomicStr::from(format!("{RED}Requirement{RESET} is not passed")), AtomicStr::from(format!("{RED}Requirement{RESET} is not passed")),
None, None,
) )
})?; })?;
let require = require.as_type().unwrap(); let require = if let Some(t) = require.as_type() {
t
} else {
return Err(ErrorCore::new(
line!() as usize,
ErrorKind::TypeError,
Location::Unknown,
AtomicStr::from(format!(
"non-type object {RED}{require}{RESET} is passed to {YELLOW}Requirement{RESET}",
)),
None,
));
};
let impls = args.remove_left_or_key("Impl"); let impls = args.remove_left_or_key("Impl");
let impls = impls.map(|v| v.as_type().unwrap()); let impls = impls.map(|v| v.as_type().unwrap());
let t = mono(mod_name, __name__.unwrap_or(Str::ever("<Lambda>"))); let t = mono(mod_name, __name__.unwrap_or(Str::ever("<Lambda>")));
Ok(ValueObj::gen_t(TypeKind::Class, t, require, impls, None)) Ok(ValueObj::gen_t(TypeKind::Class, t, require, impls, None))
} }
/// Super: Type, Impl := Type, Additional := Type -> ClassType /// Super: ClassType, Impl := Type, Additional := Type -> ClassType
pub fn inherit_func( pub fn inherit_func(
mut args: ValueArgs, mut args: ValueArgs,
mod_name: Str, mod_name: Str,
@ -46,7 +58,19 @@ pub fn inherit_func(
None, None,
) )
})?; })?;
let sup = sup.as_type().unwrap(); let sup = if let Some(t) = sup.as_type() {
t
} else {
return Err(ErrorCore::new(
line!() as usize,
ErrorKind::TypeError,
Location::Unknown,
AtomicStr::from(format!(
"non-class object {RED}{sup}{RESET} is passed to {YELLOW}Super{RESET}",
)),
None,
));
};
let impls = args.remove_left_or_key("Impl"); let impls = args.remove_left_or_key("Impl");
let impls = impls.map(|v| v.as_type().unwrap()); let impls = impls.map(|v| v.as_type().unwrap());
let additional = args.remove_left_or_key("Additional"); let additional = args.remove_left_or_key("Additional");
@ -97,7 +121,7 @@ pub fn inheritable_func(
} }
} }
/// Requirement: Type, Impl := Type -> ClassType /// Requirement: Type, Impl := Type -> TraitType
pub fn trait_func( pub fn trait_func(
mut args: ValueArgs, mut args: ValueArgs,
mod_name: Str, mod_name: Str,
@ -112,14 +136,26 @@ pub fn trait_func(
None, None,
) )
})?; })?;
let require = require.as_type().unwrap(); let require = if let Some(t) = require.as_type() {
t
} else {
return Err(ErrorCore::new(
line!() as usize,
ErrorKind::TypeError,
Location::Unknown,
AtomicStr::from(format!(
"non-type object {RED}{require}{RESET} is passed to {YELLOW}Requirement{RESET}",
)),
None,
));
};
let impls = args.remove_left_or_key("Impl"); let impls = args.remove_left_or_key("Impl");
let impls = impls.map(|v| v.as_type().unwrap()); let impls = impls.map(|v| v.as_type().unwrap());
let t = mono(mod_name, __name__.unwrap_or(Str::ever("<Lambda>"))); let t = mono(mod_name, __name__.unwrap_or(Str::ever("<Lambda>")));
Ok(ValueObj::gen_t(TypeKind::Trait, t, require, impls, None)) Ok(ValueObj::gen_t(TypeKind::Trait, t, require, impls, None))
} }
/// Super: Type, Impl := Type, Additional := Type -> ClassType /// Super: TraitType, Impl := Type, Additional := Type -> TraitType
pub fn subsume_func( pub fn subsume_func(
mut args: ValueArgs, mut args: ValueArgs,
mod_name: Str, mod_name: Str,
@ -134,7 +170,19 @@ pub fn subsume_func(
None, None,
) )
})?; })?;
let sup = sup.as_type().unwrap(); let sup = if let Some(t) = sup.as_type() {
t
} else {
return Err(ErrorCore::new(
line!() as usize,
ErrorKind::TypeError,
Location::Unknown,
AtomicStr::from(format!(
"non-trait object {RED}{sup}{RESET} is passed to {YELLOW}Super{RESET}",
)),
None,
));
};
let impls = args.remove_left_or_key("Impl"); let impls = args.remove_left_or_key("Impl");
let impls = impls.map(|v| v.as_type().unwrap()); let impls = impls.map(|v| v.as_type().unwrap());
let additional = args.remove_left_or_key("Additional"); let additional = args.remove_left_or_key("Additional");

View file

@ -180,10 +180,10 @@ impl Context {
// 型境界はすべて各サブルーチンで定義する // 型境界はすべて各サブルーチンで定義する
// push_subtype_boundなどはユーザー定義APIの型境界決定のために使用する // push_subtype_boundなどはユーザー定義APIの型境界決定のために使用する
fn init_builtin_traits(&mut self) { fn init_builtin_traits(&mut self) {
let unpack = Self::mono_trait("Unpack", None, Self::TOP_LEVEL); let unpack = Self::mono_trait("Unpack", None, None, Self::TOP_LEVEL);
let inheritable_type = Self::mono_trait("InheritableType", None, Self::TOP_LEVEL); let inheritable_type = Self::mono_trait("InheritableType", None, None, Self::TOP_LEVEL);
let named = Self::mono_trait("Named", None, Self::TOP_LEVEL); let named = Self::mono_trait("Named", None, None, Self::TOP_LEVEL);
let mut mutable = Self::mono_trait("Mutable", None, Self::TOP_LEVEL); let mut mutable = Self::mono_trait("Mutable", None, None, Self::TOP_LEVEL);
let proj = mono_proj(mono_q("Self"), "ImmutType"); let proj = mono_proj(mono_q("Self"), "ImmutType");
let f_t = func(vec![param_t("old", proj.clone())], None, vec![], proj); let f_t = func(vec![param_t("old", proj.clone())], None, vec![], proj);
let t = pr1_met(ref_mut(mono_q("Self"), None), f_t, NoneType); let t = pr1_met(ref_mut(mono_q("Self"), None), f_t, NoneType);
@ -193,16 +193,22 @@ impl Context {
); );
mutable.register_builtin_decl("update!", t, Public); mutable.register_builtin_decl("update!", t, Public);
// REVIEW: Immutatable? // REVIEW: Immutatable?
let mut immutizable = Self::mono_trait("Immutizable", None, Self::TOP_LEVEL); let mut immutizable = Self::mono_trait("Immutizable", None, None, Self::TOP_LEVEL);
immutizable.register_superclass(builtin_mono("Mutable"), &mutable); immutizable.register_superclass(builtin_mono("Mutable"), &mutable);
immutizable.register_builtin_decl("ImmutType", Type, Public); immutizable.register_builtin_decl("ImmutType", Type, Public);
// REVIEW: Mutatable? // REVIEW: Mutatable?
let mut mutizable = Self::mono_trait("Mutizable", None, Self::TOP_LEVEL); let mut mutizable = Self::mono_trait("Mutizable", None, None, Self::TOP_LEVEL);
mutizable.register_builtin_decl("MutType!", Type, Public); mutizable.register_builtin_decl("MutType!", Type, Public);
let mut in_ = Self::poly_trait("In", vec![PS::t("T", NonDefault)], None, Self::TOP_LEVEL); let mut in_ = Self::poly_trait(
"In",
vec![PS::t("T", NonDefault)],
None,
None,
Self::TOP_LEVEL,
);
let params = vec![PS::t("T", NonDefault)]; let params = vec![PS::t("T", NonDefault)];
let input = Self::poly_trait("Input", params.clone(), None, Self::TOP_LEVEL); let input = Self::poly_trait("Input", params.clone(), None, None, Self::TOP_LEVEL);
let output = Self::poly_trait("Output", params, None, Self::TOP_LEVEL); let output = Self::poly_trait("Output", params, None, None, Self::TOP_LEVEL);
in_.register_superclass(poly("Input", vec![ty_tp(mono_q("T"))]), &input); in_.register_superclass(poly("Input", vec![ty_tp(mono_q("T"))]), &input);
let op_t = fn1_met(mono_q("T"), mono_q("I"), Bool); let op_t = fn1_met(mono_q("T"), mono_q("I"), Bool);
let op_t = quant( let op_t = quant(
@ -213,7 +219,13 @@ impl Context {
// Erg does not have a trait equivalent to `PartialEq` in Rust // Erg does not have a trait equivalent to `PartialEq` in Rust
// This means, Erg's `Float` cannot be compared with other `Float` // This means, Erg's `Float` cannot be compared with other `Float`
// use `l - r < EPSILON` to check if two floats are almost equal // use `l - r < EPSILON` to check if two floats are almost equal
let mut eq = Self::poly_trait("Eq", vec![PS::t("R", WithDefault)], None, Self::TOP_LEVEL); let mut eq = Self::poly_trait(
"Eq",
vec![PS::t("R", WithDefault)],
None,
None,
Self::TOP_LEVEL,
);
eq.register_superclass(poly("Output", vec![ty_tp(mono_q("R"))]), &output); eq.register_superclass(poly("Output", vec![ty_tp(mono_q("R"))]), &output);
// __eq__: |Self <: Eq()| Self.(Self) -> Bool // __eq__: |Self <: Eq()| Self.(Self) -> Bool
let op_t = fn1_met(mono_q("Self"), mono_q("R"), Bool); let op_t = fn1_met(mono_q("Self"), mono_q("R"), Bool);
@ -229,6 +241,7 @@ impl Context {
"PartialOrd", "PartialOrd",
vec![PS::t("R", WithDefault)], vec![PS::t("R", WithDefault)],
None, None,
None,
Self::TOP_LEVEL, Self::TOP_LEVEL,
); );
partial_ord.register_superclass(poly("Eq", vec![ty_tp(mono_q("R"))]), &eq); partial_ord.register_superclass(poly("Eq", vec![ty_tp(mono_q("R"))]), &eq);
@ -245,20 +258,26 @@ impl Context {
}, },
); );
partial_ord.register_builtin_decl("__partial_cmp__", op_t, Public); partial_ord.register_builtin_decl("__partial_cmp__", op_t, Public);
let mut ord = Self::mono_trait("Ord", None, Self::TOP_LEVEL); let mut ord = Self::mono_trait("Ord", None, None, Self::TOP_LEVEL);
ord.register_superclass(poly("Eq", vec![ty_tp(builtin_mono("Self"))]), &eq); ord.register_superclass(poly("Eq", vec![ty_tp(builtin_mono("Self"))]), &eq);
ord.register_superclass( ord.register_superclass(
poly("PartialOrd", vec![ty_tp(builtin_mono("Self"))]), poly("PartialOrd", vec![ty_tp(builtin_mono("Self"))]),
&partial_ord, &partial_ord,
); );
// FIXME: poly trait // FIXME: poly trait
let num = Self::mono_trait("Num", None, Self::TOP_LEVEL); let num = Self::mono_trait("Num", None, None, Self::TOP_LEVEL);
/* vec![ /* vec![
poly("Add", vec![]), poly("Add", vec![]),
poly("Sub", vec![]), poly("Sub", vec![]),
poly("Mul", vec![]), poly("Mul", vec![]),
], */ ], */
let mut seq = Self::poly_trait("Seq", vec![PS::t("T", NonDefault)], None, Self::TOP_LEVEL); let mut seq = Self::poly_trait(
"Seq",
vec![PS::t("T", NonDefault)],
None,
None,
Self::TOP_LEVEL,
);
seq.register_superclass(poly("Output", vec![ty_tp(mono_q("T"))]), &output); seq.register_superclass(poly("Output", vec![ty_tp(mono_q("T"))]), &output);
let self_t = mono_q("Self"); let self_t = mono_q("Self");
let t = fn0_met(self_t.clone(), Nat); let t = fn0_met(self_t.clone(), Nat);
@ -278,7 +297,7 @@ impl Context {
let r_bound = static_instance("R", Type); let r_bound = static_instance("R", Type);
let params = vec![PS::t("R", WithDefault)]; let params = vec![PS::t("R", WithDefault)];
let ty_params = vec![ty_tp(mono_q("R"))]; let ty_params = vec![ty_tp(mono_q("R"))];
let mut add = Self::poly_trait("Add", params.clone(), None, Self::TOP_LEVEL); let mut add = Self::poly_trait("Add", params.clone(), None, None, Self::TOP_LEVEL);
// Rについて共変(__add__の型とは関係ない) // Rについて共変(__add__の型とは関係ない)
add.register_superclass(poly("Output", vec![ty_tp(mono_q("R"))]), &output); add.register_superclass(poly("Output", vec![ty_tp(mono_q("R"))]), &output);
let self_bound = subtypeof(mono_q("Self"), poly("Add", ty_params.clone())); let self_bound = subtypeof(mono_q("Self"), poly("Add", ty_params.clone()));
@ -290,7 +309,7 @@ impl Context {
let op_t = quant(op_t, set! {r_bound.clone(), self_bound}); let op_t = quant(op_t, set! {r_bound.clone(), self_bound});
add.register_builtin_decl("__add__", op_t, Public); add.register_builtin_decl("__add__", op_t, Public);
add.register_builtin_decl("Output", Type, Public); add.register_builtin_decl("Output", Type, Public);
let mut sub = Self::poly_trait("Sub", params.clone(), None, Self::TOP_LEVEL); let mut sub = Self::poly_trait("Sub", params.clone(), None, None, Self::TOP_LEVEL);
sub.register_superclass(poly("Output", vec![ty_tp(mono_q("R"))]), &output); sub.register_superclass(poly("Output", vec![ty_tp(mono_q("R"))]), &output);
let op_t = fn1_met( let op_t = fn1_met(
mono_q("Self"), mono_q("Self"),
@ -301,7 +320,7 @@ impl Context {
let op_t = quant(op_t, set! {r_bound.clone(), self_bound}); let op_t = quant(op_t, set! {r_bound.clone(), self_bound});
sub.register_builtin_decl("__sub__", op_t, Public); sub.register_builtin_decl("__sub__", op_t, Public);
sub.register_builtin_decl("Output", Type, Public); sub.register_builtin_decl("Output", Type, Public);
let mut mul = Self::poly_trait("Mul", params.clone(), None, Self::TOP_LEVEL); let mut mul = Self::poly_trait("Mul", params.clone(), None, None, Self::TOP_LEVEL);
mul.register_superclass(poly("Output", vec![ty_tp(mono_q("R"))]), &output); mul.register_superclass(poly("Output", vec![ty_tp(mono_q("R"))]), &output);
let op_t = fn1_met( let op_t = fn1_met(
mono_q("Self"), mono_q("Self"),
@ -312,7 +331,7 @@ impl Context {
let op_t = quant(op_t, set! {r_bound.clone(), self_bound}); let op_t = quant(op_t, set! {r_bound.clone(), self_bound});
mul.register_builtin_decl("__mul__", op_t, Public); mul.register_builtin_decl("__mul__", op_t, Public);
mul.register_builtin_decl("Output", Type, Public); mul.register_builtin_decl("Output", Type, Public);
let mut div = Self::poly_trait("Div", params, None, Self::TOP_LEVEL); let mut div = Self::poly_trait("Div", params, None, None, Self::TOP_LEVEL);
div.register_superclass(poly("Output", vec![ty_tp(mono_q("R"))]), &output); div.register_superclass(poly("Output", vec![ty_tp(mono_q("R"))]), &output);
let op_t = fn1_met(mono_q("Self"), r, mono_proj(mono_q("Self"), "Output")); let op_t = fn1_met(mono_q("Self"), r, mono_proj(mono_q("Self"), "Output"));
let self_bound = subtypeof(mono_q("Self"), poly("Div", ty_params.clone())); let self_bound = subtypeof(mono_q("Self"), poly("Div", ty_params.clone()));
@ -368,7 +387,7 @@ impl Context {
} }
fn init_builtin_classes(&mut self) { fn init_builtin_classes(&mut self) {
let mut obj = Self::mono_class("Obj", None, Self::TOP_LEVEL); let mut obj = Self::mono_class("Obj", None, None, Self::TOP_LEVEL);
let t = fn0_met(mono_q("Self"), mono_q("Self")); let t = fn0_met(mono_q("Self"), mono_q("Self"));
let t = quant(t, set! {subtypeof(mono_q("Self"), builtin_mono("Obj"))}); let t = quant(t, set! {subtypeof(mono_q("Self"), builtin_mono("Obj"))});
obj.register_builtin_impl("clone", t, Const, Public); obj.register_builtin_impl("clone", t, Const, Public);
@ -383,13 +402,13 @@ impl Context {
Immutable, Immutable,
Public, Public,
); );
let mut obj_in = Self::methods("In", None, Self::TOP_LEVEL); let mut obj_in = Self::methods("In", None, None, Self::TOP_LEVEL);
obj_in.register_builtin_impl("__in__", fn1_met(Obj, Type, Bool), Const, Public); obj_in.register_builtin_impl("__in__", fn1_met(Obj, Type, Bool), Const, Public);
obj.register_trait(Obj, poly("Eq", vec![ty_tp(Type)]), obj_in); obj.register_trait(Obj, poly("Eq", vec![ty_tp(Type)]), obj_in);
let mut obj_mutizable = Self::methods("Mutizable", None, Self::TOP_LEVEL); let mut obj_mutizable = Self::methods("Mutizable", None, None, Self::TOP_LEVEL);
obj_mutizable.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Obj!"))); obj_mutizable.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Obj!")));
obj.register_trait(Obj, builtin_mono("Mutizable"), obj_mutizable); obj.register_trait(Obj, builtin_mono("Mutizable"), obj_mutizable);
let mut float = Self::mono_class("Float", None, Self::TOP_LEVEL); let mut float = Self::mono_class("Float", None, None, Self::TOP_LEVEL);
float.register_superclass(Obj, &obj); float.register_superclass(Obj, &obj);
// TODO: support multi platform // TODO: support multi platform
float.register_builtin_const("EPSILON", ValueObj::Float(2.220446049250313e-16)); float.register_builtin_const("EPSILON", ValueObj::Float(2.220446049250313e-16));
@ -397,7 +416,7 @@ impl Context {
float.register_builtin_impl("Imag", Float, Const, Public); float.register_builtin_impl("Imag", Float, Const, Public);
float.register_marker_trait(builtin_mono("Num")); float.register_marker_trait(builtin_mono("Num"));
float.register_marker_trait(builtin_mono("Ord")); float.register_marker_trait(builtin_mono("Ord"));
let mut float_partial_ord = Self::methods("PartialOrd", None, Self::TOP_LEVEL); let mut float_partial_ord = Self::methods("PartialOrd", None, None, Self::TOP_LEVEL);
float_partial_ord.register_builtin_impl( float_partial_ord.register_builtin_impl(
"__cmp__", "__cmp__",
fn1_met(Float, Float, builtin_mono("Ordering")), fn1_met(Float, Float, builtin_mono("Ordering")),
@ -411,36 +430,36 @@ impl Context {
); );
// Float doesn't have an `Eq` implementation // Float doesn't have an `Eq` implementation
let op_t = fn1_met(Float, Float, Float); let op_t = fn1_met(Float, Float, Float);
let mut float_add = Self::methods("Add", None, Self::TOP_LEVEL); let mut float_add = Self::methods("Add", None, None, Self::TOP_LEVEL);
float_add.register_builtin_impl("__add__", op_t.clone(), Const, Public); float_add.register_builtin_impl("__add__", op_t.clone(), Const, Public);
float_add.register_builtin_const("Output", ValueObj::builtin_t(Float)); float_add.register_builtin_const("Output", ValueObj::builtin_t(Float));
float.register_trait(Float, poly("Add", vec![ty_tp(Float)]), float_add); float.register_trait(Float, poly("Add", vec![ty_tp(Float)]), float_add);
let mut float_sub = Self::methods("Sub", None, Self::TOP_LEVEL); let mut float_sub = Self::methods("Sub", None, None, Self::TOP_LEVEL);
float_sub.register_builtin_impl("__sub__", op_t.clone(), Const, Public); float_sub.register_builtin_impl("__sub__", op_t.clone(), Const, Public);
float_sub.register_builtin_const("Output", ValueObj::builtin_t(Float)); float_sub.register_builtin_const("Output", ValueObj::builtin_t(Float));
float.register_trait(Float, poly("Sub", vec![ty_tp(Float)]), float_sub); float.register_trait(Float, poly("Sub", vec![ty_tp(Float)]), float_sub);
let mut float_mul = Self::methods("Mul", None, Self::TOP_LEVEL); let mut float_mul = Self::methods("Mul", None, None, Self::TOP_LEVEL);
float_mul.register_builtin_impl("__mul__", op_t.clone(), Const, Public); float_mul.register_builtin_impl("__mul__", op_t.clone(), Const, Public);
float_mul.register_builtin_const("Output", ValueObj::builtin_t(Float)); float_mul.register_builtin_const("Output", ValueObj::builtin_t(Float));
float_mul.register_builtin_const("PowOutput", ValueObj::builtin_t(Float)); float_mul.register_builtin_const("PowOutput", ValueObj::builtin_t(Float));
float.register_trait(Float, poly("Mul", vec![ty_tp(Float)]), float_mul); float.register_trait(Float, poly("Mul", vec![ty_tp(Float)]), float_mul);
let mut float_div = Self::methods("Div", None, Self::TOP_LEVEL); let mut float_div = Self::methods("Div", None, None, Self::TOP_LEVEL);
float_div.register_builtin_impl("__div__", op_t, Const, Public); float_div.register_builtin_impl("__div__", op_t, Const, Public);
float_div.register_builtin_const("Output", ValueObj::builtin_t(Float)); float_div.register_builtin_const("Output", ValueObj::builtin_t(Float));
float_div.register_builtin_const("ModOutput", ValueObj::builtin_t(Float)); float_div.register_builtin_const("ModOutput", ValueObj::builtin_t(Float));
float.register_trait(Float, poly("Div", vec![ty_tp(Float)]), float_div); float.register_trait(Float, poly("Div", vec![ty_tp(Float)]), float_div);
let mut float_mutizable = Self::methods("Mutizable", None, Self::TOP_LEVEL); let mut float_mutizable = Self::methods("Mutizable", None, None, Self::TOP_LEVEL);
float_mutizable float_mutizable
.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Float!"))); .register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Float!")));
float.register_trait(Float, builtin_mono("Mutizable"), float_mutizable); float.register_trait(Float, builtin_mono("Mutizable"), float_mutizable);
// TODO: Int, Nat, Boolの継承元をRatioにする(今はFloat) // TODO: Int, Nat, Boolの継承元をRatioにする(今はFloat)
let mut ratio = Self::mono_class("Ratio", None, Self::TOP_LEVEL); let mut ratio = Self::mono_class("Ratio", None, None, Self::TOP_LEVEL);
ratio.register_superclass(Obj, &obj); ratio.register_superclass(Obj, &obj);
ratio.register_builtin_impl("Real", Ratio, Const, Public); ratio.register_builtin_impl("Real", Ratio, Const, Public);
ratio.register_builtin_impl("Imag", Ratio, Const, Public); ratio.register_builtin_impl("Imag", Ratio, Const, Public);
ratio.register_marker_trait(builtin_mono("Num")); ratio.register_marker_trait(builtin_mono("Num"));
ratio.register_marker_trait(builtin_mono("Ord")); ratio.register_marker_trait(builtin_mono("Ord"));
let mut ratio_partial_ord = Self::methods("PartialOrd", None, Self::TOP_LEVEL); let mut ratio_partial_ord = Self::methods("PartialOrd", None, None, Self::TOP_LEVEL);
ratio_partial_ord.register_builtin_impl( ratio_partial_ord.register_builtin_impl(
"__cmp__", "__cmp__",
fn1_met(Ratio, Ratio, builtin_mono("Ordering")), fn1_met(Ratio, Ratio, builtin_mono("Ordering")),
@ -452,33 +471,33 @@ impl Context {
poly("PartialOrd", vec![ty_tp(Ratio)]), poly("PartialOrd", vec![ty_tp(Ratio)]),
ratio_partial_ord, ratio_partial_ord,
); );
let mut ratio_eq = Self::methods("Eq", None, Self::TOP_LEVEL); let mut ratio_eq = Self::methods("Eq", None, None, Self::TOP_LEVEL);
ratio_eq.register_builtin_impl("__eq__", fn1_met(Ratio, Ratio, Bool), Const, Public); ratio_eq.register_builtin_impl("__eq__", fn1_met(Ratio, Ratio, Bool), Const, Public);
ratio.register_trait(Ratio, poly("Eq", vec![ty_tp(Ratio)]), ratio_eq); ratio.register_trait(Ratio, poly("Eq", vec![ty_tp(Ratio)]), ratio_eq);
let op_t = fn1_met(Ratio, Ratio, Ratio); let op_t = fn1_met(Ratio, Ratio, Ratio);
let mut ratio_add = Self::methods("Add", None, Self::TOP_LEVEL); let mut ratio_add = Self::methods("Add", None, None, Self::TOP_LEVEL);
ratio_add.register_builtin_impl("__add__", op_t.clone(), Const, Public); ratio_add.register_builtin_impl("__add__", op_t.clone(), Const, Public);
ratio_add.register_builtin_const("Output", ValueObj::builtin_t(Ratio)); ratio_add.register_builtin_const("Output", ValueObj::builtin_t(Ratio));
ratio.register_trait(Ratio, poly("Add", vec![ty_tp(Ratio)]), ratio_add); ratio.register_trait(Ratio, poly("Add", vec![ty_tp(Ratio)]), ratio_add);
let mut ratio_sub = Self::methods("Sub", None, Self::TOP_LEVEL); let mut ratio_sub = Self::methods("Sub", None, None, Self::TOP_LEVEL);
ratio_sub.register_builtin_impl("__sub__", op_t.clone(), Const, Public); ratio_sub.register_builtin_impl("__sub__", op_t.clone(), Const, Public);
ratio_sub.register_builtin_const("Output", ValueObj::builtin_t(Ratio)); ratio_sub.register_builtin_const("Output", ValueObj::builtin_t(Ratio));
ratio.register_trait(Ratio, poly("Sub", vec![ty_tp(Ratio)]), ratio_sub); ratio.register_trait(Ratio, poly("Sub", vec![ty_tp(Ratio)]), ratio_sub);
let mut ratio_mul = Self::methods("Mul", None, Self::TOP_LEVEL); let mut ratio_mul = Self::methods("Mul", None, None, Self::TOP_LEVEL);
ratio_mul.register_builtin_impl("__mul__", op_t.clone(), Const, Public); ratio_mul.register_builtin_impl("__mul__", op_t.clone(), Const, Public);
ratio_mul.register_builtin_const("Output", ValueObj::builtin_t(Ratio)); ratio_mul.register_builtin_const("Output", ValueObj::builtin_t(Ratio));
ratio_mul.register_builtin_const("PowOutput", ValueObj::builtin_t(Ratio)); ratio_mul.register_builtin_const("PowOutput", ValueObj::builtin_t(Ratio));
ratio.register_trait(Ratio, poly("Mul", vec![ty_tp(Ratio)]), ratio_mul); ratio.register_trait(Ratio, poly("Mul", vec![ty_tp(Ratio)]), ratio_mul);
let mut ratio_div = Self::methods("Div", None, Self::TOP_LEVEL); let mut ratio_div = Self::methods("Div", None, None, Self::TOP_LEVEL);
ratio_div.register_builtin_impl("__div__", op_t, Const, Public); ratio_div.register_builtin_impl("__div__", op_t, Const, Public);
ratio_div.register_builtin_const("Output", ValueObj::builtin_t(Ratio)); ratio_div.register_builtin_const("Output", ValueObj::builtin_t(Ratio));
ratio_div.register_builtin_const("ModOutput", ValueObj::builtin_t(Ratio)); ratio_div.register_builtin_const("ModOutput", ValueObj::builtin_t(Ratio));
ratio.register_trait(Ratio, poly("Div", vec![ty_tp(Ratio)]), ratio_div); ratio.register_trait(Ratio, poly("Div", vec![ty_tp(Ratio)]), ratio_div);
let mut ratio_mutizable = Self::methods("Mutizable", None, Self::TOP_LEVEL); let mut ratio_mutizable = Self::methods("Mutizable", None, None, Self::TOP_LEVEL);
ratio_mutizable ratio_mutizable
.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Ratio!"))); .register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Ratio!")));
ratio.register_trait(Ratio, builtin_mono("Mutizable"), ratio_mutizable); ratio.register_trait(Ratio, builtin_mono("Mutizable"), ratio_mutizable);
let mut int = Self::mono_class("Int", None, Self::TOP_LEVEL); let mut int = Self::mono_class("Int", None, None, Self::TOP_LEVEL);
int.register_superclass(Float, &float); // TODO: Float -> Ratio int.register_superclass(Float, &float); // TODO: Float -> Ratio
int.register_superclass(Obj, &obj); int.register_superclass(Obj, &obj);
int.register_marker_trait(builtin_mono("Num")); int.register_marker_trait(builtin_mono("Num"));
@ -487,7 +506,7 @@ impl Context {
// class("Rational"), // class("Rational"),
// class("Integral"), // class("Integral"),
int.register_builtin_impl("abs", fn0_met(Int, Nat), Immutable, Public); int.register_builtin_impl("abs", fn0_met(Int, Nat), Immutable, Public);
let mut int_partial_ord = Self::methods("PartialOrd", None, Self::TOP_LEVEL); let mut int_partial_ord = Self::methods("PartialOrd", None, None, Self::TOP_LEVEL);
int_partial_ord.register_builtin_impl( int_partial_ord.register_builtin_impl(
"__partial_cmp__", "__partial_cmp__",
fn1_met(Int, Int, option(builtin_mono("Ordering"))), fn1_met(Int, Int, option(builtin_mono("Ordering"))),
@ -495,30 +514,30 @@ impl Context {
Public, Public,
); );
int.register_trait(Int, poly("PartialOrd", vec![ty_tp(Int)]), int_partial_ord); int.register_trait(Int, poly("PartialOrd", vec![ty_tp(Int)]), int_partial_ord);
let mut int_eq = Self::methods("Eq", None, Self::TOP_LEVEL); let mut int_eq = Self::methods("Eq", None, None, Self::TOP_LEVEL);
int_eq.register_builtin_impl("__eq__", fn1_met(Int, Int, Bool), Const, Public); int_eq.register_builtin_impl("__eq__", fn1_met(Int, Int, Bool), Const, Public);
int.register_trait(Int, poly("Eq", vec![ty_tp(Int)]), int_eq); int.register_trait(Int, poly("Eq", vec![ty_tp(Int)]), int_eq);
// __div__ is not included in Int (cast to Ratio) // __div__ is not included in Int (cast to Ratio)
let op_t = fn1_met(Int, Int, Int); let op_t = fn1_met(Int, Int, Int);
let mut int_add = Self::methods("Add", None, Self::TOP_LEVEL); let mut int_add = Self::methods("Add", None, None, Self::TOP_LEVEL);
int_add.register_builtin_impl("__add__", op_t.clone(), Const, Public); int_add.register_builtin_impl("__add__", op_t.clone(), Const, Public);
int_add.register_builtin_const("Output", ValueObj::builtin_t(Int)); int_add.register_builtin_const("Output", ValueObj::builtin_t(Int));
int.register_trait(Int, poly("Add", vec![ty_tp(Int)]), int_add); int.register_trait(Int, poly("Add", vec![ty_tp(Int)]), int_add);
let mut int_sub = Self::methods("Sub", None, Self::TOP_LEVEL); let mut int_sub = Self::methods("Sub", None, None, Self::TOP_LEVEL);
int_sub.register_builtin_impl("__sub__", op_t.clone(), Const, Public); int_sub.register_builtin_impl("__sub__", op_t.clone(), Const, Public);
int_sub.register_builtin_const("Output", ValueObj::builtin_t(Int)); int_sub.register_builtin_const("Output", ValueObj::builtin_t(Int));
int.register_trait(Int, poly("Sub", vec![ty_tp(Int)]), int_sub); int.register_trait(Int, poly("Sub", vec![ty_tp(Int)]), int_sub);
let mut int_mul = Self::methods("Mul", None, Self::TOP_LEVEL); let mut int_mul = Self::methods("Mul", None, None, Self::TOP_LEVEL);
int_mul.register_builtin_impl("__mul__", op_t, Const, Public); int_mul.register_builtin_impl("__mul__", op_t, Const, Public);
int_mul.register_builtin_const("Output", ValueObj::builtin_t(Int)); int_mul.register_builtin_const("Output", ValueObj::builtin_t(Int));
int_mul.register_builtin_const("PowOutput", ValueObj::builtin_t(Nat)); int_mul.register_builtin_const("PowOutput", ValueObj::builtin_t(Nat));
int.register_trait(Int, poly("Mul", vec![ty_tp(Int)]), int_mul); int.register_trait(Int, poly("Mul", vec![ty_tp(Int)]), int_mul);
let mut int_mutizable = Self::methods("Mutizable", None, Self::TOP_LEVEL); let mut int_mutizable = Self::methods("Mutizable", None, None, Self::TOP_LEVEL);
int_mutizable.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Int!"))); int_mutizable.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Int!")));
int.register_trait(Int, builtin_mono("Mutizable"), int_mutizable); int.register_trait(Int, builtin_mono("Mutizable"), int_mutizable);
int.register_builtin_impl("Real", Int, Const, Public); int.register_builtin_impl("Real", Int, Const, Public);
int.register_builtin_impl("Imag", Int, Const, Public); int.register_builtin_impl("Imag", Int, Const, Public);
let mut nat = Self::mono_class("Nat", None, Self::TOP_LEVEL); let mut nat = Self::mono_class("Nat", None, None, Self::TOP_LEVEL);
nat.register_superclass(Int, &int); nat.register_superclass(Int, &int);
nat.register_superclass(Float, &float); // TODO: Float -> Ratio nat.register_superclass(Float, &float); // TODO: Float -> Ratio
nat.register_superclass(Obj, &obj); nat.register_superclass(Obj, &obj);
@ -538,10 +557,10 @@ impl Context {
); );
nat.register_marker_trait(builtin_mono("Num")); nat.register_marker_trait(builtin_mono("Num"));
nat.register_marker_trait(builtin_mono("Ord")); nat.register_marker_trait(builtin_mono("Ord"));
let mut nat_eq = Self::methods("Eq", None, Self::TOP_LEVEL); let mut nat_eq = Self::methods("Eq", None, None, Self::TOP_LEVEL);
nat_eq.register_builtin_impl("__eq__", fn1_met(Nat, Nat, Bool), Const, Public); nat_eq.register_builtin_impl("__eq__", fn1_met(Nat, Nat, Bool), Const, Public);
nat.register_trait(Nat, poly("Eq", vec![ty_tp(Nat)]), nat_eq); nat.register_trait(Nat, poly("Eq", vec![ty_tp(Nat)]), nat_eq);
let mut nat_partial_ord = Self::methods("PartialOrd", None, Self::TOP_LEVEL); let mut nat_partial_ord = Self::methods("PartialOrd", None, None, Self::TOP_LEVEL);
nat_partial_ord.register_builtin_impl( nat_partial_ord.register_builtin_impl(
"__cmp__", "__cmp__",
fn1_met(Nat, Nat, builtin_mono("Ordering")), fn1_met(Nat, Nat, builtin_mono("Ordering")),
@ -551,20 +570,20 @@ impl Context {
nat.register_trait(Nat, poly("PartialOrd", vec![ty_tp(Nat)]), nat_partial_ord); nat.register_trait(Nat, poly("PartialOrd", vec![ty_tp(Nat)]), nat_partial_ord);
// __sub__, __div__ is not included in Nat (cast to Int/ Ratio) // __sub__, __div__ is not included in Nat (cast to Int/ Ratio)
let op_t = fn1_met(Nat, Nat, Nat); let op_t = fn1_met(Nat, Nat, Nat);
let mut nat_add = Self::methods("Add", None, Self::TOP_LEVEL); let mut nat_add = Self::methods("Add", None, None, Self::TOP_LEVEL);
nat_add.register_builtin_impl("__add__", op_t.clone(), Const, Public); nat_add.register_builtin_impl("__add__", op_t.clone(), Const, Public);
nat_add.register_builtin_const("Output", ValueObj::builtin_t(Nat)); nat_add.register_builtin_const("Output", ValueObj::builtin_t(Nat));
nat.register_trait(Nat, poly("Add", vec![ty_tp(Nat)]), nat_add); nat.register_trait(Nat, poly("Add", vec![ty_tp(Nat)]), nat_add);
let mut nat_mul = Self::methods("Mul", None, Self::TOP_LEVEL); let mut nat_mul = Self::methods("Mul", None, None, Self::TOP_LEVEL);
nat_mul.register_builtin_impl("__mul__", op_t, Const, Public); nat_mul.register_builtin_impl("__mul__", op_t, Const, Public);
nat_mul.register_builtin_const("Output", ValueObj::builtin_t(Nat)); nat_mul.register_builtin_const("Output", ValueObj::builtin_t(Nat));
nat.register_trait(Nat, poly("Mul", vec![ty_tp(Nat)]), nat_mul); nat.register_trait(Nat, poly("Mul", vec![ty_tp(Nat)]), nat_mul);
let mut nat_mutizable = Self::methods("Mutizable", None, Self::TOP_LEVEL); let mut nat_mutizable = Self::methods("Mutizable", None, None, Self::TOP_LEVEL);
nat_mutizable.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Nat!"))); nat_mutizable.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Nat!")));
nat.register_trait(Nat, builtin_mono("Mutizable"), nat_mutizable); nat.register_trait(Nat, builtin_mono("Mutizable"), nat_mutizable);
nat.register_builtin_impl("Real", Nat, Const, Public); nat.register_builtin_impl("Real", Nat, Const, Public);
nat.register_builtin_impl("Imag", Nat, Const, Public); nat.register_builtin_impl("Imag", Nat, Const, Public);
let mut bool_ = Self::mono_class("Bool", None, Self::TOP_LEVEL); let mut bool_ = Self::mono_class("Bool", None, None, Self::TOP_LEVEL);
bool_.register_superclass(Nat, &nat); bool_.register_superclass(Nat, &nat);
bool_.register_superclass(Int, &int); bool_.register_superclass(Int, &int);
bool_.register_superclass(Float, &float); // TODO: Float -> Ratio bool_.register_superclass(Float, &float); // TODO: Float -> Ratio
@ -576,7 +595,7 @@ impl Context {
bool_.register_builtin_impl("__or__", fn1_met(Bool, Bool, Bool), Const, Public); bool_.register_builtin_impl("__or__", fn1_met(Bool, Bool, Bool), Const, Public);
bool_.register_marker_trait(builtin_mono("Num")); bool_.register_marker_trait(builtin_mono("Num"));
bool_.register_marker_trait(builtin_mono("Ord")); bool_.register_marker_trait(builtin_mono("Ord"));
let mut bool_partial_ord = Self::methods("PartialOrd", None, Self::TOP_LEVEL); let mut bool_partial_ord = Self::methods("PartialOrd", None, None, Self::TOP_LEVEL);
bool_partial_ord.register_builtin_impl( bool_partial_ord.register_builtin_impl(
"__cmp__", "__cmp__",
fn1_met(Bool, Bool, builtin_mono("Ordering")), fn1_met(Bool, Bool, builtin_mono("Ordering")),
@ -588,18 +607,18 @@ impl Context {
poly("PartialOrd", vec![ty_tp(Bool)]), poly("PartialOrd", vec![ty_tp(Bool)]),
bool_partial_ord, bool_partial_ord,
); );
let mut bool_eq = Self::methods("Eq", None, Self::TOP_LEVEL); let mut bool_eq = Self::methods("Eq", None, None, Self::TOP_LEVEL);
bool_eq.register_builtin_impl("__eq__", fn1_met(Bool, Bool, Bool), Const, Public); bool_eq.register_builtin_impl("__eq__", fn1_met(Bool, Bool, Bool), Const, Public);
bool_.register_trait(Bool, poly("Eq", vec![ty_tp(Bool)]), bool_eq); bool_.register_trait(Bool, poly("Eq", vec![ty_tp(Bool)]), bool_eq);
let mut bool_add = Self::methods("Add", None, Self::TOP_LEVEL); let mut bool_add = Self::methods("Add", None, None, Self::TOP_LEVEL);
bool_add.register_builtin_impl("__add__", fn1_met(Bool, Bool, Int), Const, Public); bool_add.register_builtin_impl("__add__", fn1_met(Bool, Bool, Int), Const, Public);
bool_add.register_builtin_const("Output", ValueObj::builtin_t(Nat)); bool_add.register_builtin_const("Output", ValueObj::builtin_t(Nat));
bool_.register_trait(Bool, poly("Add", vec![ty_tp(Bool)]), bool_add); bool_.register_trait(Bool, poly("Add", vec![ty_tp(Bool)]), bool_add);
let mut bool_mutizable = Self::methods("Mutizable", None, Self::TOP_LEVEL); let mut bool_mutizable = Self::methods("Mutizable", None, None, Self::TOP_LEVEL);
bool_mutizable bool_mutizable
.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Bool!"))); .register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Bool!")));
bool_.register_trait(Bool, builtin_mono("Mutizable"), bool_mutizable); bool_.register_trait(Bool, builtin_mono("Mutizable"), bool_mutizable);
let mut str_ = Self::mono_class("Str", None, Self::TOP_LEVEL); let mut str_ = Self::mono_class("Str", None, None, Self::TOP_LEVEL);
str_.register_superclass(Obj, &obj); str_.register_superclass(Obj, &obj);
str_.register_marker_trait(builtin_mono("Ord")); str_.register_marker_trait(builtin_mono("Ord"));
str_.register_builtin_impl( str_.register_builtin_impl(
@ -626,48 +645,49 @@ impl Context {
Immutable, Immutable,
Public, Public,
); );
let mut str_eq = Self::methods("Eq", None, Self::TOP_LEVEL); let mut str_eq = Self::methods("Eq", None, None, Self::TOP_LEVEL);
str_eq.register_builtin_impl("__eq__", fn1_met(Str, Str, Bool), Const, Public); str_eq.register_builtin_impl("__eq__", fn1_met(Str, Str, Bool), Const, Public);
str_.register_trait(Str, poly("Eq", vec![ty_tp(Str)]), str_eq); str_.register_trait(Str, poly("Eq", vec![ty_tp(Str)]), str_eq);
let mut str_seq = Self::methods("Seq", None, Self::TOP_LEVEL); let mut str_seq = Self::methods("Seq", None, None, Self::TOP_LEVEL);
str_seq.register_builtin_impl("len", fn0_met(Str, Nat), Const, Public); str_seq.register_builtin_impl("len", fn0_met(Str, Nat), Const, Public);
str_seq.register_builtin_impl("get", fn1_met(Str, Nat, Str), Const, Public); str_seq.register_builtin_impl("get", fn1_met(Str, Nat, Str), Const, Public);
str_.register_trait(Str, poly("Seq", vec![ty_tp(Str)]), str_seq); str_.register_trait(Str, poly("Seq", vec![ty_tp(Str)]), str_seq);
let mut str_add = Self::methods("Add", None, Self::TOP_LEVEL); let mut str_add = Self::methods("Add", None, None, Self::TOP_LEVEL);
str_add.register_builtin_impl("__add__", fn1_met(Str, Str, Str), Const, Public); str_add.register_builtin_impl("__add__", fn1_met(Str, Str, Str), Const, Public);
str_add.register_builtin_const("Output", ValueObj::builtin_t(Str)); str_add.register_builtin_const("Output", ValueObj::builtin_t(Str));
str_.register_trait(Str, poly("Add", vec![ty_tp(Str)]), str_add); str_.register_trait(Str, poly("Add", vec![ty_tp(Str)]), str_add);
let mut str_mul = Self::methods("Mul", None, Self::TOP_LEVEL); let mut str_mul = Self::methods("Mul", None, None, Self::TOP_LEVEL);
str_mul.register_builtin_impl("__mul__", fn1_met(Str, Nat, Str), Const, Public); str_mul.register_builtin_impl("__mul__", fn1_met(Str, Nat, Str), Const, Public);
str_mul.register_builtin_const("Output", ValueObj::builtin_t(Str)); str_mul.register_builtin_const("Output", ValueObj::builtin_t(Str));
str_.register_trait(Str, poly("Mul", vec![ty_tp(Nat)]), str_mul); str_.register_trait(Str, poly("Mul", vec![ty_tp(Nat)]), str_mul);
let mut str_mutizable = Self::methods("Mutizable", None, Self::TOP_LEVEL); let mut str_mutizable = Self::methods("Mutizable", None, None, Self::TOP_LEVEL);
str_mutizable.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Str!"))); str_mutizable.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Str!")));
str_.register_trait(Str, builtin_mono("Mutizable"), str_mutizable); str_.register_trait(Str, builtin_mono("Mutizable"), str_mutizable);
let mut type_ = Self::mono_class("Type", None, Self::TOP_LEVEL); let mut type_ = Self::mono_class("Type", None, None, Self::TOP_LEVEL);
type_.register_superclass(Obj, &obj); type_.register_superclass(Obj, &obj);
type_.register_builtin_impl("mro", array(Type, TyParam::erased(Nat)), Immutable, Public); type_.register_builtin_impl("mro", array(Type, TyParam::erased(Nat)), Immutable, Public);
type_.register_marker_trait(builtin_mono("Named")); type_.register_marker_trait(builtin_mono("Named"));
let mut type_eq = Self::methods("Eq", None, Self::TOP_LEVEL); let mut type_eq = Self::methods("Eq", None, None, Self::TOP_LEVEL);
type_eq.register_builtin_impl("__eq__", fn1_met(Type, Type, Bool), Const, Public); type_eq.register_builtin_impl("__eq__", fn1_met(Type, Type, Bool), Const, Public);
type_.register_trait(Type, poly("Eq", vec![ty_tp(Type)]), type_eq); type_.register_trait(Type, poly("Eq", vec![ty_tp(Type)]), type_eq);
let mut class_type = Self::mono_class("ClassType", None, Self::TOP_LEVEL); let mut class_type = Self::mono_class("ClassType", None, None, Self::TOP_LEVEL);
class_type.register_superclass(Type, &type_); class_type.register_superclass(Type, &type_);
class_type.register_superclass(Obj, &obj); class_type.register_superclass(Obj, &obj);
class_type.register_marker_trait(builtin_mono("Named")); class_type.register_marker_trait(builtin_mono("Named"));
let mut class_eq = Self::methods("Eq", None, Self::TOP_LEVEL); let mut class_eq = Self::methods("Eq", None, None, Self::TOP_LEVEL);
class_eq.register_builtin_impl("__eq__", fn1_met(Class, Class, Bool), Const, Public); class_eq.register_builtin_impl("__eq__", fn1_met(Class, Class, Bool), Const, Public);
class_type.register_trait(Class, poly("Eq", vec![ty_tp(Class)]), class_eq); class_type.register_trait(Class, poly("Eq", vec![ty_tp(Class)]), class_eq);
let mut module = Self::mono_class("Module", None, Self::TOP_LEVEL); let mut module = Self::mono_class("Module", None, None, Self::TOP_LEVEL);
module.register_superclass(Obj, &obj); module.register_superclass(Obj, &obj);
module.register_marker_trait(builtin_mono("Named")); module.register_marker_trait(builtin_mono("Named"));
let mut module_eq = Self::methods("Eq", None, Self::TOP_LEVEL); let mut module_eq = Self::methods("Eq", None, None, Self::TOP_LEVEL);
module_eq.register_builtin_impl("__eq__", fn1_met(Module, Module, Bool), Const, Public); module_eq.register_builtin_impl("__eq__", fn1_met(Module, Module, Bool), Const, Public);
module.register_trait(Module, poly("Eq", vec![ty_tp(Module)]), module_eq); module.register_trait(Module, poly("Eq", vec![ty_tp(Module)]), module_eq);
let mut array_ = Self::poly_class( let mut array_ = Self::poly_class(
"Array", "Array",
vec![PS::t_nd("T"), PS::named_nd("N", Nat)], vec![PS::t_nd("T"), PS::named_nd("N", Nat)],
None, None,
None,
Self::TOP_LEVEL, Self::TOP_LEVEL,
); );
array_.register_superclass(Obj, &obj); array_.register_superclass(Obj, &obj);
@ -693,7 +713,7 @@ impl Context {
)); ));
// [T; N].MutType! = [T; !N] (neither [T!; N] nor [T; N]!) // [T; N].MutType! = [T; !N] (neither [T!; N] nor [T; N]!)
array_.register_builtin_const("MutType!", mut_type); array_.register_builtin_const("MutType!", mut_type);
let mut array_eq = Self::methods("Eq", None, Self::TOP_LEVEL); let mut array_eq = Self::methods("Eq", None, None, Self::TOP_LEVEL);
array_eq.register_builtin_impl( array_eq.register_builtin_impl(
"__eq__", "__eq__",
fn1_met(array_t.clone(), array_t.clone(), Bool), fn1_met(array_t.clone(), array_t.clone(), Bool),
@ -704,9 +724,9 @@ impl Context {
array_.register_marker_trait(builtin_mono("Mutizable")); array_.register_marker_trait(builtin_mono("Mutizable"));
array_.register_marker_trait(poly("Seq", vec![ty_tp(mono_q("T"))])); array_.register_marker_trait(poly("Seq", vec![ty_tp(mono_q("T"))]));
// TODO: make Tuple6, Tuple7, ... etc. // TODO: make Tuple6, Tuple7, ... etc.
let mut tuple_ = Self::mono_class("Tuple", None, Self::TOP_LEVEL); let mut tuple_ = Self::mono_class("Tuple", None, None, Self::TOP_LEVEL);
tuple_.register_superclass(Obj, &obj); tuple_.register_superclass(Obj, &obj);
let mut tuple_eq = Self::methods("Eq", None, Self::TOP_LEVEL); let mut tuple_eq = Self::methods("Eq", None, None, Self::TOP_LEVEL);
tuple_eq.register_builtin_impl( tuple_eq.register_builtin_impl(
"__eq__", "__eq__",
fn1_met(builtin_mono("Tuple"), builtin_mono("Tuple"), Bool), fn1_met(builtin_mono("Tuple"), builtin_mono("Tuple"), Bool),
@ -718,10 +738,11 @@ impl Context {
poly("Eq", vec![ty_tp(builtin_mono("Tuple"))]), poly("Eq", vec![ty_tp(builtin_mono("Tuple"))]),
tuple_eq, tuple_eq,
); );
let mut tuple1 = Self::poly_class("Tuple1", vec![PS::t_nd("A")], None, Self::TOP_LEVEL); let mut tuple1 =
Self::poly_class("Tuple1", vec![PS::t_nd("A")], None, None, Self::TOP_LEVEL);
tuple1.register_superclass(builtin_mono("Tuple"), &tuple_); tuple1.register_superclass(builtin_mono("Tuple"), &tuple_);
tuple1.register_superclass(Obj, &obj); tuple1.register_superclass(Obj, &obj);
let mut tuple1_eq = Self::methods("Eq", None, Self::TOP_LEVEL); let mut tuple1_eq = Self::methods("Eq", None, None, Self::TOP_LEVEL);
tuple1_eq.register_builtin_impl( tuple1_eq.register_builtin_impl(
"__eq__", "__eq__",
fn1_met( fn1_met(
@ -741,11 +762,12 @@ impl Context {
"Tuple2", "Tuple2",
vec![PS::t_nd("A"), PS::t_nd("B")], vec![PS::t_nd("A"), PS::t_nd("B")],
None, None,
None,
Self::TOP_LEVEL, Self::TOP_LEVEL,
); );
tuple2.register_superclass(builtin_mono("Tuple"), &tuple_); tuple2.register_superclass(builtin_mono("Tuple"), &tuple_);
tuple2.register_superclass(Obj, &obj); tuple2.register_superclass(Obj, &obj);
let mut tuple2_eq = Self::methods("Eq", None, Self::TOP_LEVEL); let mut tuple2_eq = Self::methods("Eq", None, None, Self::TOP_LEVEL);
tuple2_eq.register_builtin_impl( tuple2_eq.register_builtin_impl(
"__eq__", "__eq__",
fn1_met( fn1_met(
@ -771,11 +793,12 @@ impl Context {
"Tuple3", "Tuple3",
vec![PS::t_nd("A"), PS::t_nd("B"), PS::t_nd("C")], vec![PS::t_nd("A"), PS::t_nd("B"), PS::t_nd("C")],
None, None,
None,
Self::TOP_LEVEL, Self::TOP_LEVEL,
); );
tuple3.register_superclass(builtin_mono("Tuple"), &tuple_); tuple3.register_superclass(builtin_mono("Tuple"), &tuple_);
tuple3.register_superclass(Obj, &obj); tuple3.register_superclass(Obj, &obj);
let mut tuple3_eq = Self::methods("Eq", None, Self::TOP_LEVEL); let mut tuple3_eq = Self::methods("Eq", None, None, Self::TOP_LEVEL);
tuple3_eq.register_builtin_impl( tuple3_eq.register_builtin_impl(
"__eq__", "__eq__",
fn1_met( fn1_met(
@ -810,11 +833,12 @@ impl Context {
"Tuple4", "Tuple4",
vec![PS::t_nd("A"), PS::t_nd("B"), PS::t_nd("C"), PS::t_nd("D")], vec![PS::t_nd("A"), PS::t_nd("B"), PS::t_nd("C"), PS::t_nd("D")],
None, None,
None,
Self::TOP_LEVEL, Self::TOP_LEVEL,
); );
tuple4.register_superclass(builtin_mono("Tuple"), &tuple_); tuple4.register_superclass(builtin_mono("Tuple"), &tuple_);
tuple4.register_superclass(Obj, &obj); tuple4.register_superclass(Obj, &obj);
let mut tuple4_eq = Self::methods("Eq", None, Self::TOP_LEVEL); let mut tuple4_eq = Self::methods("Eq", None, None, Self::TOP_LEVEL);
tuple4_eq.register_builtin_impl( tuple4_eq.register_builtin_impl(
"__eq__", "__eq__",
fn1_met( fn1_met(
@ -875,11 +899,12 @@ impl Context {
PS::t_nd("E"), PS::t_nd("E"),
], ],
None, None,
None,
Self::TOP_LEVEL, Self::TOP_LEVEL,
); );
tuple5.register_superclass(builtin_mono("Tuple"), &tuple_); tuple5.register_superclass(builtin_mono("Tuple"), &tuple_);
tuple5.register_superclass(Obj, &obj); tuple5.register_superclass(Obj, &obj);
let mut tuple5_eq = Self::methods("Eq", None, Self::TOP_LEVEL); let mut tuple5_eq = Self::methods("Eq", None, None, Self::TOP_LEVEL);
tuple5_eq.register_builtin_impl( tuple5_eq.register_builtin_impl(
"__eq__", "__eq__",
fn1_met( fn1_met(
@ -945,11 +970,12 @@ impl Context {
PS::t_nd("F"), PS::t_nd("F"),
], ],
None, None,
None,
Self::TOP_LEVEL, Self::TOP_LEVEL,
); );
tuple6.register_superclass(builtin_mono("Tuple"), &tuple_); tuple6.register_superclass(builtin_mono("Tuple"), &tuple_);
tuple6.register_superclass(Obj, &obj); tuple6.register_superclass(Obj, &obj);
let mut tuple6_eq = Self::methods("Eq", None, Self::TOP_LEVEL); let mut tuple6_eq = Self::methods("Eq", None, None, Self::TOP_LEVEL);
tuple6_eq.register_builtin_impl( tuple6_eq.register_builtin_impl(
"__eq__", "__eq__",
fn1_met( fn1_met(
@ -1020,11 +1046,12 @@ impl Context {
PS::t_nd("G"), PS::t_nd("G"),
], ],
None, None,
None,
Self::TOP_LEVEL, Self::TOP_LEVEL,
); );
tuple7.register_superclass(builtin_mono("Tuple"), &tuple_); tuple7.register_superclass(builtin_mono("Tuple"), &tuple_);
tuple7.register_superclass(Obj, &obj); tuple7.register_superclass(Obj, &obj);
let mut tuple7_eq = Self::methods("Eq", None, Self::TOP_LEVEL); let mut tuple7_eq = Self::methods("Eq", None, None, Self::TOP_LEVEL);
tuple7_eq.register_builtin_impl( tuple7_eq.register_builtin_impl(
"__eq__", "__eq__",
fn1_met( fn1_met(
@ -1100,11 +1127,12 @@ impl Context {
PS::t_nd("H"), PS::t_nd("H"),
], ],
None, None,
None,
Self::TOP_LEVEL, Self::TOP_LEVEL,
); );
tuple8.register_superclass(builtin_mono("Tuple"), &tuple_); tuple8.register_superclass(builtin_mono("Tuple"), &tuple_);
tuple8.register_superclass(Obj, &obj); tuple8.register_superclass(Obj, &obj);
let mut tuple8_eq = Self::methods("Eq", None, Self::TOP_LEVEL); let mut tuple8_eq = Self::methods("Eq", None, None, Self::TOP_LEVEL);
tuple8_eq.register_builtin_impl( tuple8_eq.register_builtin_impl(
"__eq__", "__eq__",
fn1_met( fn1_met(
@ -1171,16 +1199,16 @@ impl Context {
), ),
tuple8_eq, tuple8_eq,
); );
let mut record = Self::mono_class("Record", None, Self::TOP_LEVEL); let mut record = Self::mono_class("Record", None, None, Self::TOP_LEVEL);
record.register_superclass(Obj, &obj); record.register_superclass(Obj, &obj);
let mut record_type = Self::mono_class("RecordType", None, Self::TOP_LEVEL); let mut record_type = Self::mono_class("RecordType", None, None, Self::TOP_LEVEL);
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_);
record_type.register_superclass(Obj, &obj); record_type.register_superclass(Obj, &obj);
let mut float_mut = Self::mono_class("Float!", None, Self::TOP_LEVEL); let mut float_mut = Self::mono_class("Float!", None, None, Self::TOP_LEVEL);
float_mut.register_superclass(Float, &float); float_mut.register_superclass(Float, &float);
float_mut.register_superclass(Obj, &obj); float_mut.register_superclass(Obj, &obj);
let mut float_mut_mutable = Self::methods("Mutable", None, Self::TOP_LEVEL); let mut float_mut_mutable = Self::methods("Mutable", None, None, Self::TOP_LEVEL);
float_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Float)); float_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Float));
let f_t = param_t("f", func(vec![param_t("old", Float)], None, vec![], Float)); let f_t = param_t("f", func(vec![param_t("old", Float)], None, vec![], Float));
let t = pr_met( let t = pr_met(
@ -1196,10 +1224,10 @@ impl Context {
builtin_mono("Mutable"), builtin_mono("Mutable"),
float_mut_mutable, float_mut_mutable,
); );
let mut ratio_mut = Self::mono_class("Ratio!", None, Self::TOP_LEVEL); let mut ratio_mut = Self::mono_class("Ratio!", None, None, Self::TOP_LEVEL);
ratio_mut.register_superclass(Ratio, &ratio); ratio_mut.register_superclass(Ratio, &ratio);
ratio_mut.register_superclass(Obj, &obj); ratio_mut.register_superclass(Obj, &obj);
let mut ratio_mut_mutable = Self::methods("Mutable", None, Self::TOP_LEVEL); let mut ratio_mut_mutable = Self::methods("Mutable", None, None, Self::TOP_LEVEL);
ratio_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Ratio)); ratio_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Ratio));
let f_t = param_t( let f_t = param_t(
"f", "f",
@ -1223,11 +1251,11 @@ impl Context {
builtin_mono("Mutable"), builtin_mono("Mutable"),
ratio_mut_mutable, ratio_mut_mutable,
); );
let mut int_mut = Self::mono_class("Int!", None, Self::TOP_LEVEL); let mut int_mut = Self::mono_class("Int!", None, None, Self::TOP_LEVEL);
int_mut.register_superclass(Int, &int); int_mut.register_superclass(Int, &int);
int_mut.register_superclass(builtin_mono("Float!"), &float_mut); int_mut.register_superclass(builtin_mono("Float!"), &float_mut);
int_mut.register_superclass(Obj, &obj); int_mut.register_superclass(Obj, &obj);
let mut int_mut_mutable = Self::methods("Mutable", None, Self::TOP_LEVEL); let mut int_mut_mutable = Self::methods("Mutable", None, None, Self::TOP_LEVEL);
int_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Int)); int_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Int));
let f_t = param_t("f", func(vec![param_t("old", Int)], None, vec![], Int)); let f_t = param_t("f", func(vec![param_t("old", Int)], None, vec![], Int));
let t = pr_met( let t = pr_met(
@ -1243,12 +1271,12 @@ impl Context {
builtin_mono("Mutable"), builtin_mono("Mutable"),
int_mut_mutable, int_mut_mutable,
); );
let mut nat_mut = Self::mono_class("Nat!", None, Self::TOP_LEVEL); let mut nat_mut = Self::mono_class("Nat!", None, None, Self::TOP_LEVEL);
nat_mut.register_superclass(Nat, &nat); nat_mut.register_superclass(Nat, &nat);
nat_mut.register_superclass(builtin_mono("Int!"), &int_mut); nat_mut.register_superclass(builtin_mono("Int!"), &int_mut);
nat_mut.register_superclass(builtin_mono("Float!"), &float_mut); nat_mut.register_superclass(builtin_mono("Float!"), &float_mut);
nat_mut.register_superclass(Obj, &obj); nat_mut.register_superclass(Obj, &obj);
let mut nat_mut_mutable = Self::methods("Mutable", None, Self::TOP_LEVEL); let mut nat_mut_mutable = Self::methods("Mutable", None, None, Self::TOP_LEVEL);
nat_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Nat)); nat_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Nat));
let f_t = param_t("f", func(vec![param_t("old", Nat)], None, vec![], Nat)); let f_t = param_t("f", func(vec![param_t("old", Nat)], None, vec![], Nat));
let t = pr_met( let t = pr_met(
@ -1264,13 +1292,13 @@ impl Context {
builtin_mono("Mutable"), builtin_mono("Mutable"),
nat_mut_mutable, nat_mut_mutable,
); );
let mut bool_mut = Self::mono_class("Bool!", None, Self::TOP_LEVEL); let mut bool_mut = Self::mono_class("Bool!", None, None, Self::TOP_LEVEL);
bool_mut.register_superclass(Bool, &bool_); bool_mut.register_superclass(Bool, &bool_);
bool_mut.register_superclass(builtin_mono("Nat!"), &nat_mut); bool_mut.register_superclass(builtin_mono("Nat!"), &nat_mut);
bool_mut.register_superclass(builtin_mono("Int!"), &int_mut); bool_mut.register_superclass(builtin_mono("Int!"), &int_mut);
bool_mut.register_superclass(builtin_mono("Float!"), &float_mut); bool_mut.register_superclass(builtin_mono("Float!"), &float_mut);
bool_mut.register_superclass(Obj, &obj); bool_mut.register_superclass(Obj, &obj);
let mut bool_mut_mutable = Self::methods("Mutable", None, Self::TOP_LEVEL); let mut bool_mut_mutable = Self::methods("Mutable", None, None, Self::TOP_LEVEL);
bool_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Bool)); bool_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Bool));
let f_t = param_t("f", func(vec![param_t("old", Bool)], None, vec![], Bool)); let f_t = param_t("f", func(vec![param_t("old", Bool)], None, vec![], Bool));
let t = pr_met( let t = pr_met(
@ -1286,10 +1314,10 @@ impl Context {
builtin_mono("Mutable"), builtin_mono("Mutable"),
bool_mut_mutable, bool_mut_mutable,
); );
let mut str_mut = Self::mono_class("Str!", None, Self::TOP_LEVEL); let mut str_mut = Self::mono_class("Str!", None, None, Self::TOP_LEVEL);
str_mut.register_superclass(Str, &str_); str_mut.register_superclass(Str, &str_);
str_mut.register_superclass(Obj, &obj); str_mut.register_superclass(Obj, &obj);
let mut str_mut_mutable = Self::methods("Mutable", None, Self::TOP_LEVEL); let mut str_mut_mutable = Self::methods("Mutable", None, None, Self::TOP_LEVEL);
str_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Str)); str_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Str));
let f_t = param_t("f", func(vec![param_t("old", Str)], None, vec![], Str)); let f_t = param_t("f", func(vec![param_t("old", Str)], None, vec![], Str));
let t = pr_met( let t = pr_met(
@ -1311,6 +1339,7 @@ impl Context {
"Array!", "Array!",
vec![PS::t_nd("T"), PS::named_nd("N", builtin_mono("Nat!"))], vec![PS::t_nd("T"), PS::named_nd("N", builtin_mono("Nat!"))],
None, None,
None,
Self::TOP_LEVEL, Self::TOP_LEVEL,
); );
array_mut_.register_superclass(array_t.clone(), &array_); array_mut_.register_superclass(array_t.clone(), &array_);
@ -1364,7 +1393,7 @@ impl Context {
vec![], vec![],
NoneType, NoneType,
); );
let mut array_mut_mutable = Self::methods("Mutable", None, Self::TOP_LEVEL); let mut array_mut_mutable = Self::methods("Mutable", None, None, Self::TOP_LEVEL);
array_mut_mutable.register_builtin_impl("update!", t, Immutable, Public); array_mut_mutable.register_builtin_impl("update!", t, Immutable, Public);
array_mut_.register_trait( array_mut_.register_trait(
array_mut_t.clone(), array_mut_t.clone(),
@ -1372,10 +1401,10 @@ impl Context {
array_mut_mutable, array_mut_mutable,
); );
let range_t = poly("Range", vec![TyParam::t(mono_q("T"))]); let range_t = poly("Range", vec![TyParam::t(mono_q("T"))]);
let mut range = Self::poly_class("Range", vec![PS::t_nd("T")], None, Self::TOP_LEVEL); let mut range = Self::poly_class("Range", vec![PS::t_nd("T")], None, None, Self::TOP_LEVEL);
range.register_superclass(Obj, &obj); range.register_superclass(Obj, &obj);
range.register_marker_trait(poly("Output", vec![ty_tp(mono_q("T"))])); range.register_marker_trait(poly("Output", vec![ty_tp(mono_q("T"))]));
let mut range_eq = Self::methods("Eq", None, Self::TOP_LEVEL); let mut range_eq = Self::methods("Eq", None, None, Self::TOP_LEVEL);
range_eq.register_builtin_impl( range_eq.register_builtin_impl(
"__eq__", "__eq__",
fn1_met(range_t.clone(), range_t.clone(), Bool), fn1_met(range_t.clone(), range_t.clone(), Bool),
@ -1387,16 +1416,16 @@ impl Context {
poly("Eq", vec![ty_tp(range_t.clone())]), poly("Eq", vec![ty_tp(range_t.clone())]),
range_eq, range_eq,
); );
let mut proc = Self::mono_class("Proc", None, Self::TOP_LEVEL); let mut proc = Self::mono_class("Proc", None, None, Self::TOP_LEVEL);
proc.register_superclass(Obj, &obj); proc.register_superclass(Obj, &obj);
// TODO: lambda // TODO: lambda
proc.register_marker_trait(builtin_mono("Named")); proc.register_marker_trait(builtin_mono("Named"));
let mut func = Self::mono_class("Func", None, Self::TOP_LEVEL); let mut func = Self::mono_class("Func", None, None, Self::TOP_LEVEL);
func.register_superclass(builtin_mono("Proc"), &proc); func.register_superclass(builtin_mono("Proc"), &proc);
func.register_superclass(Obj, &obj); func.register_superclass(Obj, &obj);
// TODO: lambda // TODO: lambda
func.register_marker_trait(builtin_mono("Named")); func.register_marker_trait(builtin_mono("Named"));
let mut qfunc = Self::mono_class("QuantifiedFunc", None, Self::TOP_LEVEL); let mut qfunc = Self::mono_class("QuantifiedFunc", None, None, Self::TOP_LEVEL);
qfunc.register_superclass(builtin_mono("Func"), &func); qfunc.register_superclass(builtin_mono("Func"), &func);
qfunc.register_superclass(Obj, &obj); qfunc.register_superclass(Obj, &obj);
self.register_builtin_type(Obj, obj, Const); self.register_builtin_type(Obj, obj, Const);
@ -1780,6 +1809,7 @@ impl Context {
params, params,
// super: vec![Type::from(&m..=&n)], // super: vec![Type::from(&m..=&n)],
None, None,
None,
Self::TOP_LEVEL, Self::TOP_LEVEL,
); );
let op_t = fn1_met( let op_t = fn1_met(
@ -1787,7 +1817,7 @@ impl Context {
Type::from(&o..=&p), Type::from(&o..=&p),
Type::from(m.clone() + o.clone()..=n.clone() + p.clone()), Type::from(m.clone() + o.clone()..=n.clone() + p.clone()),
); );
let mut interval_add = Self::methods("Add", None, Self::TOP_LEVEL); let mut interval_add = Self::methods("Add", None, None, Self::TOP_LEVEL);
interval_add.register_builtin_impl("__add__", op_t, Const, Public); interval_add.register_builtin_impl("__add__", op_t, Const, Public);
interval_add.register_builtin_const( interval_add.register_builtin_const(
"Output", "Output",
@ -1798,7 +1828,7 @@ impl Context {
poly("Add", vec![TyParam::from(&o..=&p)]), poly("Add", vec![TyParam::from(&o..=&p)]),
interval_add, interval_add,
); );
let mut interval_sub = Self::methods("Sub", None, Self::TOP_LEVEL); let mut interval_sub = Self::methods("Sub", None, None, Self::TOP_LEVEL);
let op_t = fn1_met( let op_t = fn1_met(
Type::from(&m..=&n), Type::from(&m..=&n),
Type::from(&o..=&p), Type::from(&o..=&p),
@ -1823,7 +1853,7 @@ impl Context {
pub(crate) fn init_builtins(mod_cache: &SharedModuleCache) { pub(crate) fn init_builtins(mod_cache: &SharedModuleCache) {
// TODO: capacityを正確に把握する // TODO: capacityを正確に把握する
let mut ctx = Context::module("<builtins>".into(), None, 40); let mut ctx = Context::module("<builtins>".into(), None, None, 40);
ctx.init_builtin_funcs(); ctx.init_builtin_funcs();
ctx.init_builtin_const_funcs(); ctx.init_builtin_const_funcs();
ctx.init_builtin_procs(); ctx.init_builtin_procs();
@ -1834,13 +1864,18 @@ impl Context {
mod_cache.register(VarName::from_static("<builtins>"), None, ctx); mod_cache.register(VarName::from_static("<builtins>"), None, ctx);
} }
pub fn new_module<S: Into<Str>>(name: S, mod_cache: SharedModuleCache) -> Self { pub fn new_module<S: Into<Str>>(
name: S,
mod_cache: SharedModuleCache,
py_mod_cache: SharedModuleCache,
) -> Self {
Context::new( Context::new(
name.into(), name.into(),
ContextKind::Module, ContextKind::Module,
vec![], vec![],
None, None,
Some(mod_cache), Some(mod_cache),
Some(py_mod_cache),
Context::TOP_LEVEL, Context::TOP_LEVEL,
) )
} }

View file

@ -11,7 +11,7 @@ use Visibility::*;
impl Context { impl Context {
pub(crate) fn init_py_importlib_mod() -> Self { pub(crate) fn init_py_importlib_mod() -> Self {
let mut importlib = Context::module("importlib".into(), None, 15); let mut importlib = Context::module("importlib".into(), None, None, 15);
importlib.register_builtin_impl("reload!", proc1(Module, NoneType), Immutable, Public); importlib.register_builtin_impl("reload!", proc1(Module, NoneType), Immutable, Public);
importlib importlib
} }

View file

@ -12,8 +12,8 @@ use Visibility::*;
impl Context { impl Context {
pub(crate) fn init_py_io_mod() -> Self { pub(crate) fn init_py_io_mod() -> Self {
let mut io = Context::module("io".into(), None, 15); let mut io = Context::module("io".into(), None, None, 15);
let mut string_io = Context::mono_class(Str::ever("StringIO!"), None, 0); let mut string_io = Context::mono_class(Str::ever("StringIO!"), None, None, 0);
// FIXME: include Obj (pass main_ctx as a param) // FIXME: include Obj (pass main_ctx as a param)
// string_io.register_superclass(Obj, obj); // string_io.register_superclass(Obj, obj);
string_io.register_builtin_impl( string_io.register_builtin_impl(

View file

@ -11,7 +11,7 @@ use Visibility::*;
impl Context { impl Context {
pub(crate) fn init_py_math_mod() -> Self { pub(crate) fn init_py_math_mod() -> Self {
let mut math = Context::module("math".into(), None, 10); let mut math = Context::module("math".into(), None, None, 10);
math.register_builtin_impl("pi", Float, Immutable, Public); math.register_builtin_impl("pi", Float, Immutable, Public);
math.register_builtin_impl("tau", Float, Immutable, Public); math.register_builtin_impl("tau", Float, Immutable, Public);
math.register_builtin_impl("e", Float, Immutable, Public); math.register_builtin_impl("e", Float, Immutable, Public);

View file

@ -14,7 +14,7 @@ use Visibility::*;
impl Context { impl Context {
pub(crate) fn init_py_random_mod() -> Self { pub(crate) fn init_py_random_mod() -> Self {
let mut random = Context::module("random".into(), None, 10); let mut random = Context::module("random".into(), None, None, 10);
random.register_builtin_impl( random.register_builtin_impl(
"seed!", "seed!",
proc( proc(

View file

@ -12,8 +12,8 @@ use Visibility::*;
impl Context { impl Context {
pub(crate) fn init_py_socket_mod() -> Self { pub(crate) fn init_py_socket_mod() -> Self {
let mut socket = Context::module("socket".into(), None, 15); let mut socket = Context::module("socket".into(), None, None, 15);
let mut sock = Context::mono_class(Str::ever("Socket!"), None, 0); let mut sock = Context::mono_class(Str::ever("Socket!"), None, None, 0);
// FIXME: include Obj (pass main_ctx as a param) // FIXME: include Obj (pass main_ctx as a param)
// sock.register_superclass(Obj, obj); // sock.register_superclass(Obj, obj);
sock.register_builtin_impl( sock.register_builtin_impl(

View file

@ -12,7 +12,7 @@ use Visibility::*;
impl Context { impl Context {
pub(crate) fn init_py_sys_mod() -> Self { pub(crate) fn init_py_sys_mod() -> Self {
let mut sys = Context::module("sys".into(), None, 15); let mut sys = Context::module("sys".into(), None, None, 15);
sys.register_builtin_impl("argv", array(Str, TyParam::erased(Nat)), Immutable, Public); sys.register_builtin_impl("argv", array(Str, TyParam::erased(Nat)), Immutable, Public);
sys.register_builtin_impl("byteorder", Str, Immutable, Public); sys.register_builtin_impl("byteorder", Str, Immutable, Public);
sys.register_builtin_impl( sys.register_builtin_impl(

View file

@ -11,7 +11,7 @@ use Visibility::*;
impl Context { impl Context {
pub(crate) fn init_py_time_mod() -> Self { pub(crate) fn init_py_time_mod() -> Self {
let mut time = Context::module("time".into(), None, 15); let mut time = Context::module("time".into(), None, None, 15);
time.register_builtin_impl("sleep!", proc1(Float, NoneType), Immutable, Public); time.register_builtin_impl("sleep!", proc1(Float, NoneType), Immutable, Public);
time.register_builtin_impl("time!", proc0(Float), Immutable, Public); time.register_builtin_impl("time!", proc0(Float), Immutable, Public);
time time

View file

@ -2,7 +2,7 @@
use std::option::Option; // conflicting to Type::Option use std::option::Option; // conflicting to Type::Option
use erg_common::error::{ErrorCore, ErrorKind, Location}; use erg_common::error::{ErrorCore, ErrorKind, Location};
use erg_common::levenshtein::levenshtein; use erg_common::levenshtein::get_similar_name;
use erg_common::set::Set; use erg_common::set::Set;
use erg_common::traits::Locational; use erg_common::traits::Locational;
use erg_common::vis::{Field, Visibility}; use erg_common::vis::{Field, Visibility};
@ -897,33 +897,23 @@ impl Context {
} }
} }
pub(crate) fn get_similar_name(&self, name: &str) -> Option<&Str> { pub(crate) fn get_similar_name(&self, name: &str) -> Option<&str> {
let name = readable_name(name); let name = readable_name(name);
if name.len() <= 1 { // TODO: add decls
return None; get_similar_name(
} self.params
// TODO: add `.decls` .iter()
let most_similar_name = self .filter_map(|(opt_name, _)| opt_name.as_ref().map(|n| &n.inspect()[..]))
.params .chain(self.locals.keys().map(|name| &name.inspect()[..])),
.iter() name,
.filter_map(|(opt_name, _)| opt_name.as_ref()) )
.chain(self.locals.keys())
.min_by_key(|v| levenshtein(readable_name(v.inspect()), name))?
.inspect();
let len = most_similar_name.len();
if levenshtein(most_similar_name, name) >= len / 2 {
let outer = self.get_outer().or_else(|| self.get_builtins())?;
outer.get_similar_name(name)
} else {
Some(most_similar_name)
}
} }
pub(crate) fn get_similar_attr_from_singular<'a>( pub(crate) fn get_similar_attr_from_singular<'a>(
&'a self, &'a self,
obj: &hir::Expr, obj: &hir::Expr,
name: &str, name: &str,
) -> Option<&'a Str> { ) -> Option<&'a str> {
if let Ok(ctx) = self.get_singular_ctx(obj, &self.name) { if let Ok(ctx) = self.get_singular_ctx(obj, &self.name) {
if let Some(name) = ctx.get_similar_name(name) { if let Some(name) = ctx.get_similar_name(name) {
return Some(name); return Some(name);
@ -932,7 +922,7 @@ impl Context {
None None
} }
pub(crate) fn get_similar_attr<'a>(&'a self, self_t: &'a Type, name: &str) -> Option<&'a Str> { pub(crate) fn get_similar_attr<'a>(&'a self, self_t: &'a Type, name: &str) -> Option<&'a str> {
for (_, ctx) in self.get_nominal_super_type_ctxs(self_t)? { for (_, ctx) in self.get_nominal_super_type_ctxs(self_t)? {
if let Some(name) = ctx.get_similar_name(name) { if let Some(name) = ctx.get_similar_name(name) {
return Some(name); return Some(name);
@ -1148,12 +1138,16 @@ impl Context {
.rec_get_mono_type("Record"); .rec_get_mono_type("Record");
} }
Type::Mono { path, name } => { Type::Mono { path, name } => {
if let Some(ctx) = self.mod_cache.as_ref().unwrap().ref_ctx(path) { if self.mod_name() == path {
if let Some((t, ctx)) = ctx.rec_get_mono_type(name) { if let Some((t, ctx)) = self.rec_get_mono_type(name) {
return Some((t, ctx)); return Some((t, ctx));
} }
} else if self.mod_name() == path { } else if let Some(ctx) = self
if let Some((t, ctx)) = self.rec_get_mono_type(name) { .mod_cache
.as_ref()
.and_then(|cache| cache.ref_ctx(path))
{
if let Some((t, ctx)) = ctx.rec_get_mono_type(name) {
return Some((t, ctx)); return Some((t, ctx));
} }
} }
@ -1265,6 +1259,11 @@ impl Context {
self.mod_cache self.mod_cache
.as_ref() .as_ref()
.and_then(|cache| cache.ref_ctx(name)) .and_then(|cache| cache.ref_ctx(name))
.or_else(|| {
self.py_mod_cache
.as_ref()
.and_then(|cache| cache.ref_ctx(name))
})
} }
// rec_get_const_localとは違い、位置情報を持たないしエラーとならない // rec_get_const_localとは違い、位置情報を持たないしエラーとならない
@ -1423,14 +1422,12 @@ impl Context {
let insts = self.rec_get_trait_impls(&sup.name()); let insts = self.rec_get_trait_impls(&sup.name());
let candidates = insts.into_iter().filter_map(move |inst| { let candidates = insts.into_iter().filter_map(move |inst| {
if self.supertype_of(&inst.sup_trait, &sup) { if self.supertype_of(&inst.sup_trait, &sup) {
Some( self.eval_t_params(
self.eval_t_params( mono_proj(inst.sub_type, rhs),
mono_proj(inst.sub_type, rhs), self.level,
self.level, Location::Unknown,
Location::Unknown,
)
.unwrap(),
) )
.ok()
} else { } else {
None None
} }

View file

@ -113,15 +113,7 @@ impl TyVarContext {
if defined_params_len < given_params_len { if defined_params_len < given_params_len {
panic!() panic!()
} }
let inst_non_defaults = params let inst_non_defaults = self.instantiate_params(params);
.into_iter()
.map(|tp| {
let name = tp.tvar_name().unwrap();
let tp = self.instantiate_qtp(tp);
self.push_or_init_typaram(&name, &tp);
tp
})
.collect();
let mut inst_defaults = vec![]; let mut inst_defaults = vec![];
for template in temp_defaults for template in temp_defaults
.iter() .iter()
@ -133,41 +125,45 @@ impl TyVarContext {
} }
poly(name, [inst_non_defaults, inst_defaults].concat()) poly(name, [inst_non_defaults, inst_defaults].concat())
} else { } else {
poly( poly(name, self.instantiate_params(params))
name, }
params }
.into_iter()
.map(|p| { fn instantiate_params(&mut self, params: Vec<TyParam>) -> Vec<TyParam> {
if let Some(name) = p.tvar_name() { params
let tp = self.instantiate_qtp(p); .into_iter()
self.push_or_init_typaram(&name, &tp); .map(|p| {
tp if let Some(name) = p.tvar_name() {
} else { let tp = self.instantiate_qtp(p);
p self.push_or_init_typaram(&name, &tp);
} tp
}) } else {
.collect(), p
) }
})
.collect()
}
fn instantiate_bound_type(&mut self, mid: &Type, sub_or_sup: Type, ctx: &Context) -> Type {
match sub_or_sup {
Type::Poly { name, params } => self.instantiate_poly(mid.name(), &name, params, ctx),
Type::MonoProj { lhs, rhs } => {
let lhs = if lhs.has_qvar() {
self.instantiate_qvar(*lhs)
} else {
*lhs
};
mono_proj(lhs, rhs)
}
other => other,
} }
} }
fn instantiate_bound(&mut self, bound: TyBound, ctx: &Context) { fn instantiate_bound(&mut self, bound: TyBound, ctx: &Context) {
match bound { match bound {
TyBound::Sandwiched { sub, mid, sup } => { TyBound::Sandwiched { sub, mid, sup } => {
let sub_instance = match sub { let sub_instance = self.instantiate_bound_type(&mid, sub, ctx);
Type::Poly { name, params } => { let sup_instance = self.instantiate_bound_type(&mid, sup, ctx);
self.instantiate_poly(mid.name(), &name, params, ctx)
}
Type::MonoProj { lhs, rhs } => mono_proj(self.instantiate_qvar(*lhs), rhs),
sub => sub,
};
let sup_instance = match sup {
Type::Poly { name, params } => {
self.instantiate_poly(mid.name(), &name, params, ctx)
}
Type::MonoProj { lhs, rhs } => mono_proj(self.instantiate_qvar(*lhs), rhs),
sup => sup,
};
let name = mid.name(); let name = mid.name();
let constraint = let constraint =
Constraint::new_sandwiched(sub_instance, sup_instance, Cyclicity::Not); Constraint::new_sandwiched(sub_instance, sup_instance, Cyclicity::Not);
@ -247,7 +243,7 @@ impl TyVarContext {
} }
} }
TyParam::Type(t) => { TyParam::Type(t) => {
if let Type::MonoQVar(n) = *t { if let Some(n) = t.as_ref().tvar_name() {
if let Some(t) = self.get_typaram(&n) { if let Some(t) = self.get_typaram(&n) {
t.clone() t.clone()
} else if let Some(t) = self.get_tyvar(&n) { } else if let Some(t) = self.get_tyvar(&n) {
@ -258,7 +254,7 @@ impl TyVarContext {
TyParam::t(tv) TyParam::t(tv)
} }
} else { } else {
todo!("{t}") unreachable!("{t}")
} }
} }
TyParam::UnaryOp { op, val } => { TyParam::UnaryOp { op, val } => {
@ -340,6 +336,7 @@ impl TyVarContext {
} }
} }
/// TODO: this struct will be removed when const functions are implemented.
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum ConstTemplate { pub enum ConstTemplate {
Obj(ValueObj), Obj(ValueObj),
@ -393,22 +390,16 @@ impl Context {
.map(|t| enum_unwrap!(t, Type::Subr)); .map(|t| enum_unwrap!(t, Type::Subr));
let bounds = self.instantiate_ty_bounds(&sig.bounds, PreRegister)?; let bounds = self.instantiate_ty_bounds(&sig.bounds, PreRegister)?;
let mut tv_ctx = TyVarContext::new(self.level, bounds, self); let mut tv_ctx = TyVarContext::new(self.level, bounds, self);
let non_defaults = sig let mut non_defaults = vec![];
.params for (n, p) in sig.params.non_defaults.iter().enumerate() {
.non_defaults let opt_decl_t = opt_decl_sig_t
.iter() .as_ref()
.enumerate() .and_then(|subr| subr.non_default_params.get(n));
.map(|(n, p)| { non_defaults.push(ParamTy::pos(
let opt_decl_t = opt_decl_sig_t p.inspect().cloned(),
.as_ref() self.instantiate_param_sig_t(p, opt_decl_t, &mut Some(&mut tv_ctx), mode)?,
.and_then(|subr| subr.non_default_params.get(n)); ));
ParamTy::pos( }
p.inspect().cloned(),
self.instantiate_param_sig_t(p, opt_decl_t, &mut Some(&mut tv_ctx), mode)
.unwrap(),
)
})
.collect::<Vec<_>>();
let var_args = if let Some(var_args) = sig.params.var_args.as_ref() { let var_args = if let Some(var_args) = sig.params.var_args.as_ref() {
let opt_decl_t = opt_decl_sig_t let opt_decl_t = opt_decl_sig_t
.as_ref() .as_ref()
@ -419,22 +410,16 @@ impl Context {
} else { } else {
None None
}; };
let defaults = sig let mut defaults = vec![];
.params for (n, p) in sig.params.defaults.iter().enumerate() {
.defaults let opt_decl_t = opt_decl_sig_t
.iter() .as_ref()
.enumerate() .and_then(|subr| subr.default_params.get(n));
.map(|(n, p)| { defaults.push(ParamTy::kw(
let opt_decl_t = opt_decl_sig_t p.inspect().unwrap().clone(),
.as_ref() self.instantiate_param_sig_t(p, opt_decl_t, &mut Some(&mut tv_ctx), mode)?,
.and_then(|subr| subr.default_params.get(n)); ));
ParamTy::kw( }
p.inspect().unwrap().clone(),
self.instantiate_param_sig_t(p, opt_decl_t, &mut Some(&mut tv_ctx), mode)
.unwrap(),
)
})
.collect();
let spec_return_t = if let Some(s) = sig.return_t_spec.as_ref() { let spec_return_t = if let Some(s) = sig.return_t_spec.as_ref() {
let opt_decl_t = opt_decl_sig_t let opt_decl_t = opt_decl_sig_t
.as_ref() .as_ref()
@ -544,8 +529,8 @@ impl Context {
Ok(decl_t.typ().clone()) Ok(decl_t.typ().clone())
} else { } else {
let typ = mono(self.mod_name(), Str::rc(other)); let typ = mono(self.mod_name(), Str::rc(other));
if self.get_nominal_type_ctx(&typ).is_some() { if let Some((defined_t, _)) = self.get_nominal_type_ctx(&typ) {
Ok(typ) Ok(defined_t.clone())
} else { } else {
Err(TyCheckError::no_var_error( Err(TyCheckError::no_var_error(
line!() as usize, line!() as usize,
@ -770,6 +755,9 @@ impl Context {
let t = Self::instantiate_t(*t, tv_ctx, loc)?; let t = Self::instantiate_t(*t, tv_ctx, loc)?;
Ok(TyParam::t(t)) Ok(TyParam::t(t))
} }
TyParam::FreeVar(fv) if fv.is_linked() => {
Self::instantiate_tp(fv.crack().clone(), tv_ctx, loc)
}
p @ (TyParam::Value(_) | TyParam::Mono(_) | TyParam::FreeVar(_)) => Ok(p), p @ (TyParam::Value(_) | TyParam::Mono(_) | TyParam::FreeVar(_)) => Ok(p),
other => todo!("{other}"), other => todo!("{other}"),
} }
@ -871,6 +859,15 @@ impl Context {
Quantified(_) => { Quantified(_) => {
panic!("a quantified type should not be instantiated, instantiate the inner type") panic!("a quantified type should not be instantiated, instantiate the inner type")
} }
FreeVar(fv) if fv.is_linked() => Self::instantiate_t(fv.crack().clone(), tv_ctx, loc),
FreeVar(fv) => {
let (sub, sup) = fv.get_bound_types().unwrap();
let sub = Self::instantiate_t(sub, tv_ctx, loc)?;
let sup = Self::instantiate_t(sup, tv_ctx, loc)?;
let new_constraint = Constraint::new_sandwiched(sub, sup, fv.cyclicity());
fv.update_constraint(new_constraint);
Ok(FreeVar(fv))
}
other if other.is_monomorphic() => Ok(other), other if other.is_monomorphic() => Ok(other),
other => todo!("{other}"), other => todo!("{other}"),
} }

View file

@ -19,6 +19,7 @@ use std::option::Option; // conflicting to Type::Option
use erg_common::astr::AtomicStr; use erg_common::astr::AtomicStr;
use erg_common::dict::Dict; use erg_common::dict::Dict;
use erg_common::error::Location;
use erg_common::impl_display_from_debug; use erg_common::impl_display_from_debug;
use erg_common::traits::{Locational, Stream}; use erg_common::traits::{Locational, Stream};
use erg_common::vis::Visibility; use erg_common::vis::Visibility;
@ -238,7 +239,7 @@ impl From<DefKind> for ContextKind {
DefKind::Class | DefKind::Inherit => Self::Class, DefKind::Class | DefKind::Inherit => Self::Class,
DefKind::Trait | DefKind::Subsume => Self::Trait, DefKind::Trait | DefKind::Subsume => Self::Trait,
DefKind::StructuralTrait => Self::StructuralTrait, DefKind::StructuralTrait => Self::StructuralTrait,
DefKind::Module => Self::Module, DefKind::ErgImport | DefKind::PyImport => Self::Module,
DefKind::Other => Self::Instant, DefKind::Other => Self::Instant,
} }
} }
@ -271,6 +272,21 @@ pub enum RegistrationMode {
Normal, Normal,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ImportKind {
ErgImport,
PyImport,
}
impl ImportKind {
pub const fn is_erg_import(&self) -> bool {
matches!(self, Self::ErgImport)
}
pub const fn is_py_import(&self) -> bool {
matches!(self, Self::PyImport)
}
}
/// Represents the context of the current scope /// Represents the context of the current scope
/// ///
/// Recursive functions/methods are highlighted with the prefix `rec_`, as performance may be significantly degraded. /// Recursive functions/methods are highlighted with the prefix `rec_`, as performance may be significantly degraded.
@ -325,6 +341,7 @@ pub struct Context {
// but when used as a fallback to a type, values are traversed instead of accessing by keys // but when used as a fallback to a type, values are traversed instead of accessing by keys
pub(crate) patches: Dict<VarName, Context>, pub(crate) patches: Dict<VarName, Context>,
pub(crate) mod_cache: Option<SharedModuleCache>, pub(crate) mod_cache: Option<SharedModuleCache>,
pub(crate) py_mod_cache: Option<SharedModuleCache>,
pub(crate) level: usize, pub(crate) level: usize,
} }
@ -337,6 +354,7 @@ impl Default for Context {
vec![], vec![],
None, None,
None, None,
None,
Self::TOP_LEVEL, Self::TOP_LEVEL,
) )
} }
@ -368,9 +386,10 @@ impl Context {
params: Vec<ParamSpec>, params: Vec<ParamSpec>,
outer: Option<Context>, outer: Option<Context>,
mod_cache: Option<SharedModuleCache>, mod_cache: Option<SharedModuleCache>,
py_mod_cache: Option<SharedModuleCache>,
level: usize, level: usize,
) -> Self { ) -> Self {
Self::with_capacity(name, kind, params, outer, 0, mod_cache, level) Self::with_capacity(name, kind, params, outer, 0, mod_cache, py_mod_cache, level)
} }
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
@ -381,6 +400,7 @@ impl Context {
outer: Option<Context>, outer: Option<Context>,
capacity: usize, capacity: usize,
mod_cache: Option<SharedModuleCache>, mod_cache: Option<SharedModuleCache>,
py_mod_cache: Option<SharedModuleCache>,
level: usize, level: usize,
) -> Self { ) -> Self {
let mut params_ = Vec::new(); let mut params_ = Vec::new();
@ -419,6 +439,7 @@ impl Context {
mono_types: Dict::default(), mono_types: Dict::default(),
poly_types: Dict::default(), poly_types: Dict::default(),
mod_cache, mod_cache,
py_mod_cache,
patches: Dict::default(), patches: Dict::default(),
level, level,
} }
@ -430,9 +451,10 @@ impl Context {
kind: ContextKind, kind: ContextKind,
outer: Option<Context>, outer: Option<Context>,
mod_cache: Option<SharedModuleCache>, mod_cache: Option<SharedModuleCache>,
py_mod_cache: Option<SharedModuleCache>,
level: usize, level: usize,
) -> Self { ) -> Self {
Self::with_capacity(name, kind, vec![], outer, 0, mod_cache, level) Self::with_capacity(name, kind, vec![], outer, 0, mod_cache, py_mod_cache, level)
} }
#[inline] #[inline]
@ -442,53 +464,75 @@ impl Context {
params: Vec<ParamSpec>, params: Vec<ParamSpec>,
outer: Option<Context>, outer: Option<Context>,
mod_cache: Option<SharedModuleCache>, mod_cache: Option<SharedModuleCache>,
py_mod_cache: Option<SharedModuleCache>,
level: usize, level: usize,
) -> Self { ) -> Self {
Self::with_capacity(name, kind, params, outer, 0, mod_cache, level) Self::with_capacity(name, kind, params, outer, 0, mod_cache, py_mod_cache, level)
} }
pub fn poly_trait<S: Into<Str>>( pub fn poly_trait<S: Into<Str>>(
name: S, name: S,
params: Vec<ParamSpec>, params: Vec<ParamSpec>,
mod_cache: Option<SharedModuleCache>, mod_cache: Option<SharedModuleCache>,
py_mod_cache: Option<SharedModuleCache>,
level: usize, level: usize,
) -> Self { ) -> Self {
let name = name.into(); let name = name.into();
Self::poly(name, ContextKind::Trait, params, None, mod_cache, level) Self::poly(
name,
ContextKind::Trait,
params,
None,
mod_cache,
py_mod_cache,
level,
)
} }
pub fn poly_class<S: Into<Str>>( pub fn poly_class<S: Into<Str>>(
name: S, name: S,
params: Vec<ParamSpec>, params: Vec<ParamSpec>,
mod_cache: Option<SharedModuleCache>, mod_cache: Option<SharedModuleCache>,
py_mod_cache: Option<SharedModuleCache>,
level: usize, level: usize,
) -> Self { ) -> Self {
let name = name.into(); let name = name.into();
Self::poly(name, ContextKind::Class, params, None, mod_cache, level) Self::poly(
name,
ContextKind::Class,
params,
None,
mod_cache,
py_mod_cache,
level,
)
} }
#[inline] #[inline]
pub fn mono_trait<S: Into<Str>>( pub fn mono_trait<S: Into<Str>>(
name: S, name: S,
mod_cache: Option<SharedModuleCache>, mod_cache: Option<SharedModuleCache>,
py_mod_cache: Option<SharedModuleCache>,
level: usize, level: usize,
) -> Self { ) -> Self {
Self::poly_trait(name, vec![], mod_cache, level) Self::poly_trait(name, vec![], mod_cache, py_mod_cache, level)
} }
#[inline] #[inline]
pub fn mono_class<S: Into<Str>>( pub fn mono_class<S: Into<Str>>(
name: S, name: S,
mod_cache: Option<SharedModuleCache>, mod_cache: Option<SharedModuleCache>,
py_mod_cache: Option<SharedModuleCache>,
level: usize, level: usize,
) -> Self { ) -> Self {
Self::poly_class(name, vec![], mod_cache, level) Self::poly_class(name, vec![], mod_cache, py_mod_cache, level)
} }
#[inline] #[inline]
pub fn methods<S: Into<Str>>( pub fn methods<S: Into<Str>>(
name: S, name: S,
mod_cache: Option<SharedModuleCache>, mod_cache: Option<SharedModuleCache>,
py_mod_cache: Option<SharedModuleCache>,
level: usize, level: usize,
) -> Self { ) -> Self {
Self::with_capacity( Self::with_capacity(
@ -498,6 +542,7 @@ impl Context {
None, None,
2, 2,
mod_cache, mod_cache,
py_mod_cache,
level, level,
) )
} }
@ -507,6 +552,7 @@ impl Context {
name: S, name: S,
params: Vec<ParamSpec>, params: Vec<ParamSpec>,
mod_cache: Option<SharedModuleCache>, mod_cache: Option<SharedModuleCache>,
py_mod_cache: Option<SharedModuleCache>,
level: usize, level: usize,
) -> Self { ) -> Self {
Self::poly( Self::poly(
@ -515,12 +561,18 @@ impl Context {
params, params,
None, None,
mod_cache, mod_cache,
py_mod_cache,
level, level,
) )
} }
#[inline] #[inline]
pub fn module(name: Str, mod_cache: Option<SharedModuleCache>, capacity: usize) -> Self { pub fn module(
name: Str,
mod_cache: Option<SharedModuleCache>,
py_mod_cache: Option<SharedModuleCache>,
capacity: usize,
) -> Self {
Self::with_capacity( Self::with_capacity(
name, name,
ContextKind::Module, ContextKind::Module,
@ -528,6 +580,7 @@ impl Context {
None, None,
capacity, capacity,
mod_cache, mod_cache,
py_mod_cache,
Self::TOP_LEVEL, Self::TOP_LEVEL,
) )
} }
@ -537,6 +590,7 @@ impl Context {
name: Str, name: Str,
capacity: usize, capacity: usize,
mod_cache: Option<SharedModuleCache>, mod_cache: Option<SharedModuleCache>,
py_mod_cache: Option<SharedModuleCache>,
outer: Context, outer: Context,
) -> Self { ) -> Self {
Self::with_capacity( Self::with_capacity(
@ -546,6 +600,7 @@ impl Context {
Some(outer), Some(outer),
capacity, capacity,
mod_cache, mod_cache,
py_mod_cache,
Self::TOP_LEVEL, Self::TOP_LEVEL,
) )
} }
@ -596,6 +651,7 @@ impl Context {
log!(info "{}: current namespace: {name}", fn_name!()); log!(info "{}: current namespace: {name}", fn_name!());
self.outer = Some(Box::new(mem::take(self))); self.outer = Some(Box::new(mem::take(self)));
self.mod_cache = self.get_outer().unwrap().mod_cache.clone(); self.mod_cache = self.get_outer().unwrap().mod_cache.clone();
self.py_mod_cache = self.get_outer().unwrap().py_mod_cache.clone();
self.name = name.into(); self.name = name.into();
self.kind = kind; self.kind = kind;
Ok(()) Ok(())
@ -637,3 +693,33 @@ impl Context {
} }
} }
} }
/// for language server
impl Context {
pub fn dir(&self) -> Vec<(&VarName, &VarInfo)> {
let mut vars: Vec<_> = self.locals.iter().collect();
if let Some(outer) = self.get_outer() {
vars.extend(outer.dir());
} else {
vars.extend(self.get_builtins().unwrap().locals.iter());
}
vars
}
pub fn get_var_info(&self, name: &str) -> TyCheckResult<(&VarName, &VarInfo)> {
if let Some(info) = self.get_local_kv(name) {
Ok(info)
} else {
if let Some(parent) = self.get_outer().or_else(|| self.get_builtins()) {
return parent.get_var_info(name);
}
Err(TyCheckError::no_var_error(
line!() as usize,
Location::Unknown,
self.caused_by(),
name,
self.get_similar_name(name),
))
}
}
}

View file

@ -3,6 +3,7 @@ use std::path::PathBuf; // conflicting to Type::Option
use erg_common::config::{ErgConfig, Input}; use erg_common::config::{ErgConfig, Input};
use erg_common::error::MultiErrorDisplay; use erg_common::error::MultiErrorDisplay;
use erg_common::levenshtein::get_similar_name;
use erg_common::traits::{Locational, Stream}; use erg_common::traits::{Locational, Stream};
use erg_common::vis::Visibility; use erg_common::vis::Visibility;
use erg_common::Str; use erg_common::Str;
@ -29,6 +30,7 @@ use RegistrationMode::*;
use Visibility::*; use Visibility::*;
use super::instantiate::TyVarContext; use super::instantiate::TyVarContext;
use super::ImportKind;
impl Context { impl Context {
/// If it is a constant that is defined, there must be no variable of the same name defined across all scopes /// If it is a constant that is defined, there must be no variable of the same name defined across all scopes
@ -611,10 +613,18 @@ impl Context {
TypeKind::Class => { TypeKind::Class => {
if gen.t.is_monomorphic() { if gen.t.is_monomorphic() {
// let super_traits = gen.impls.iter().map(|to| to.typ().clone()).collect(); // let super_traits = gen.impls.iter().map(|to| to.typ().clone()).collect();
let mut ctx = let mut ctx = Self::mono_class(
Self::mono_class(gen.t.name(), self.mod_cache.clone(), self.level); gen.t.name(),
let mut methods = self.mod_cache.clone(),
Self::methods(gen.t.name(), self.mod_cache.clone(), self.level); self.py_mod_cache.clone(),
self.level,
);
let mut methods = Self::methods(
gen.t.name(),
self.mod_cache.clone(),
self.py_mod_cache.clone(),
self.level,
);
let require = gen.require_or_sup.typ().clone(); let require = gen.require_or_sup.typ().clone();
let new_t = func1(require, gen.t.clone()); let new_t = func1(require, gen.t.clone());
methods.register_fixed_auto_impl("__new__", new_t.clone(), Immutable, Private); methods.register_fixed_auto_impl("__new__", new_t.clone(), Immutable, Private);
@ -624,21 +634,29 @@ impl Context {
.push((ClassDefType::Simple(gen.t.clone()), methods)); .push((ClassDefType::Simple(gen.t.clone()), methods));
self.register_gen_mono_type(ident, gen, ctx, Const); self.register_gen_mono_type(ident, gen, ctx, Const);
} else { } else {
todo!() todo!("polymorphic type definition is not supported yet");
} }
} }
TypeKind::Subclass => { TypeKind::Subclass => {
if gen.t.is_monomorphic() { if gen.t.is_monomorphic() {
let super_classes = vec![gen.require_or_sup.typ().clone()]; let super_classes = vec![gen.require_or_sup.typ().clone()];
// let super_traits = gen.impls.iter().map(|to| to.typ().clone()).collect(); // let super_traits = gen.impls.iter().map(|to| to.typ().clone()).collect();
let mut ctx = let mut ctx = Self::mono_class(
Self::mono_class(gen.t.name(), self.mod_cache.clone(), self.level); gen.t.name(),
self.mod_cache.clone(),
self.py_mod_cache.clone(),
self.level,
);
for sup in super_classes.into_iter() { for sup in super_classes.into_iter() {
let (_, sup_ctx) = self.get_nominal_type_ctx(&sup).unwrap(); let (_, sup_ctx) = self.get_nominal_type_ctx(&sup).unwrap();
ctx.register_superclass(sup, sup_ctx); ctx.register_superclass(sup, sup_ctx);
} }
let mut methods = let mut methods = Self::methods(
Self::methods(gen.t.name(), self.mod_cache.clone(), self.level); gen.t.name(),
self.mod_cache.clone(),
self.py_mod_cache.clone(),
self.level,
);
if let Some(sup) = self.rec_get_const_obj(&gen.require_or_sup.typ().name()) { if let Some(sup) = self.rec_get_const_obj(&gen.require_or_sup.typ().name()) {
let sup = enum_unwrap!(sup, ValueObj::Type); let sup = enum_unwrap!(sup, ValueObj::Type);
let param_t = match sup { let param_t = match sup {
@ -668,13 +686,17 @@ impl Context {
todo!("super class not found") todo!("super class not found")
} }
} else { } else {
todo!() todo!("polymorphic type definition is not supported yet");
} }
} }
TypeKind::Trait => { TypeKind::Trait => {
if gen.t.is_monomorphic() { if gen.t.is_monomorphic() {
let mut ctx = let mut ctx = Self::mono_trait(
Self::mono_trait(gen.t.name(), self.mod_cache.clone(), self.level); gen.t.name(),
self.mod_cache.clone(),
self.py_mod_cache.clone(),
self.level,
);
let require = enum_unwrap!(gen.require_or_sup.as_ref(), TypeObj::Builtin:(Type::Record:(_))); let require = enum_unwrap!(gen.require_or_sup.as_ref(), TypeObj::Builtin:(Type::Record:(_)));
for (field, t) in require.iter() { for (field, t) in require.iter() {
let muty = if field.is_const() { let muty = if field.is_const() {
@ -688,15 +710,19 @@ impl Context {
} }
self.register_gen_mono_type(ident, gen, ctx, Const); self.register_gen_mono_type(ident, gen, ctx, Const);
} else { } else {
todo!() todo!("polymorphic type definition is not supported yet");
} }
} }
TypeKind::Subtrait => { TypeKind::Subtrait => {
if gen.t.is_monomorphic() { if gen.t.is_monomorphic() {
let super_classes = vec![gen.require_or_sup.typ().clone()]; let super_classes = vec![gen.require_or_sup.typ().clone()];
// let super_traits = gen.impls.iter().map(|to| to.typ().clone()).collect(); // let super_traits = gen.impls.iter().map(|to| to.typ().clone()).collect();
let mut ctx = let mut ctx = Self::mono_trait(
Self::mono_trait(gen.t.name(), self.mod_cache.clone(), self.level); gen.t.name(),
self.mod_cache.clone(),
self.py_mod_cache.clone(),
self.level,
);
let additional = gen.additional.as_ref().map(|additional| enum_unwrap!(additional.as_ref(), TypeObj::Builtin:(Type::Record:(_)))); let additional = gen.additional.as_ref().map(|additional| enum_unwrap!(additional.as_ref(), TypeObj::Builtin:(Type::Record:(_))));
if let Some(additional) = additional { if let Some(additional) = additional {
for (field, t) in additional.iter() { for (field, t) in additional.iter() {
@ -717,7 +743,7 @@ impl Context {
} }
self.register_gen_mono_type(ident, gen, ctx, Const); self.register_gen_mono_type(ident, gen, ctx, Const);
} else { } else {
todo!() todo!("polymorphic type definition is not supported yet");
} }
} }
other => todo!("{other:?}"), other => todo!("{other:?}"),
@ -764,6 +790,7 @@ impl Context {
pub(crate) fn import_mod( pub(crate) fn import_mod(
&mut self, &mut self,
kind: ImportKind,
current_input: Input, current_input: Input,
var_name: &VarName, var_name: &VarName,
mod_name: &hir::Expr, mod_name: &hir::Expr,
@ -771,61 +798,10 @@ impl Context {
match mod_name { match mod_name {
hir::Expr::Lit(lit) => { hir::Expr::Lit(lit) => {
if self.subtype_of(&lit.value.class(), &Str) { if self.subtype_of(&lit.value.class(), &Str) {
let __name__ = enum_unwrap!(lit.value.clone(), ValueObj::Str); if kind.is_erg_import() {
if let Some(mod_cache) = self.mod_cache.as_ref() { self.import_erg_mod(current_input, var_name, lit)?;
match &__name__[..] {
"importlib" => {
mod_cache.register(
var_name.clone(),
None,
Self::init_py_importlib_mod(),
);
}
"io" => {
mod_cache.register(var_name.clone(), None, Self::init_py_io_mod());
}
"math" => {
mod_cache.register(
var_name.clone(),
None,
Self::init_py_math_mod(),
);
}
"random" => {
mod_cache.register(
var_name.clone(),
None,
Self::init_py_random_mod(),
);
}
"socket" => {
mod_cache.register(
var_name.clone(),
None,
Self::init_py_socket_mod(),
);
}
"sys" => {
mod_cache.register(var_name.clone(), None, Self::init_py_sys_mod());
}
"time" => {
mod_cache.register(
var_name.clone(),
None,
Self::init_py_time_mod(),
);
}
_ => self.import_user_module(
current_input,
var_name,
__name__,
lit,
mod_cache,
)?,
}
} else { } else {
// maybe unreachable self.import_py_mod(current_input, var_name, lit)?;
todo!("importing {__name__} in the builtin module")
} }
} else { } else {
return Err(TyCheckError::type_mismatch_error( return Err(TyCheckError::type_mismatch_error(
@ -852,14 +828,43 @@ impl Context {
Ok(()) Ok(())
} }
fn import_user_module( fn import_erg_mod(
&mut self,
current_input: Input,
var_name: &VarName,
lit: &Literal,
) -> TyCheckResult<()> {
let __name__ = enum_unwrap!(lit.value.clone(), ValueObj::Str);
let mod_cache = self.mod_cache.as_ref().unwrap();
let py_mod_cache = self.py_mod_cache.as_ref().unwrap();
#[allow(clippy::match_single_binding)]
match &__name__[..] {
// TODO: erg builtin modules
_ => self.import_user_erg_mod(
current_input,
var_name,
__name__,
lit,
mod_cache,
py_mod_cache,
)?,
}
Ok(())
}
fn import_user_erg_mod(
&self, &self,
current_input: Input, current_input: Input,
var_name: &VarName, var_name: &VarName,
__name__: Str, __name__: Str,
name_lit: &Literal, name_lit: &Literal,
mod_cache: &SharedModuleCache, mod_cache: &SharedModuleCache,
py_mod_cache: &SharedModuleCache,
) -> TyCheckResult<()> { ) -> TyCheckResult<()> {
if let Some((_, entry)) = mod_cache.get_by_name(&__name__) {
mod_cache.register_alias(var_name.clone(), entry);
return Ok(());
}
let mut dir = if let Input::File(mut path) = current_input { let mut dir = if let Input::File(mut path) = current_input {
path.pop(); path.pop();
path path
@ -867,24 +872,32 @@ impl Context {
PathBuf::new() PathBuf::new()
}; };
dir.push(format!("{__name__}.er")); dir.push(format!("{__name__}.er"));
// TODO: returns an error
let path = match dir.canonicalize() { let path = match dir.canonicalize() {
Ok(path) => path, Ok(path) => path,
Err(err) => { Err(err) => {
return Err(TyCheckError::file_error( return Err(TyCheckError::import_error(
line!() as usize, line!() as usize,
err.to_string(), err.to_string(),
name_lit.loc(), name_lit.loc(),
self.caused_by(), self.caused_by(),
self.mod_cache.as_ref().unwrap().get_similar_name(&__name__),
self.similar_builtin_py_mod_name(&__name__).or_else(|| {
self.py_mod_cache
.as_ref()
.unwrap()
.get_similar_name(&__name__)
}),
)); ));
} }
}; };
let cfg = ErgConfig { let cfg = ErgConfig::with_path(path);
input: Input::File(path),
..ErgConfig::default()
};
let src = cfg.input.read(); let src = cfg.input.read();
let mut builder = HIRBuilder::new_with_cache(cfg, var_name.inspect(), mod_cache.clone()); let mut builder = HIRBuilder::new_with_cache(
cfg,
var_name.inspect(),
mod_cache.clone(),
py_mod_cache.clone(),
);
match builder.build(src, "exec") { match builder.build(src, "exec") {
Ok(hir) => { Ok(hir) => {
mod_cache.register(var_name.clone(), Some(hir), builder.pop_ctx()); mod_cache.register(var_name.clone(), Some(hir), builder.pop_ctx());
@ -896,6 +909,105 @@ impl Context {
Ok(()) Ok(())
} }
fn import_py_mod(
&mut self,
current_input: Input,
var_name: &VarName,
lit: &Literal,
) -> TyCheckResult<()> {
let __name__ = enum_unwrap!(lit.value.clone(), ValueObj::Str);
let mod_cache = self.mod_cache.as_ref().unwrap();
match &__name__[..] {
"importlib" => {
mod_cache.register(var_name.clone(), None, Self::init_py_importlib_mod());
}
"io" => {
mod_cache.register(var_name.clone(), None, Self::init_py_io_mod());
}
"math" => {
mod_cache.register(var_name.clone(), None, Self::init_py_math_mod());
}
"random" => {
mod_cache.register(var_name.clone(), None, Self::init_py_random_mod());
}
"socket" => {
mod_cache.register(var_name.clone(), None, Self::init_py_socket_mod());
}
"sys" => {
mod_cache.register(var_name.clone(), None, Self::init_py_sys_mod());
}
"time" => {
mod_cache.register(var_name.clone(), None, Self::init_py_time_mod());
}
_ => self.import_user_py_mod(current_input, var_name, lit)?,
}
Ok(())
}
fn similar_builtin_py_mod_name(&self, name: &Str) -> Option<Str> {
get_similar_name(
["importlib", "io", "math", "random", "socket", "sys", "time"].into_iter(),
name,
)
.map(Str::rc)
}
fn import_user_py_mod(
&self,
current_input: Input,
var_name: &VarName,
lit: &Literal,
) -> TyCheckResult<()> {
let __name__ = enum_unwrap!(lit.value.clone(), ValueObj::Str);
let py_mod_cache = self.py_mod_cache.as_ref().unwrap();
if let Some((_, entry)) = py_mod_cache.get_by_name(&__name__) {
py_mod_cache.register_alias(var_name.clone(), entry);
return Ok(());
}
let mut dir = if let Input::File(mut path) = current_input {
path.pop();
path
} else {
PathBuf::new()
};
dir.push(format!("{__name__}.d.er"));
let path = match dir.canonicalize() {
Ok(path) => path,
Err(err) => {
return Err(TyCheckError::import_error(
line!() as usize,
err.to_string(),
lit.loc(),
self.caused_by(),
self.mod_cache.as_ref().unwrap().get_similar_name(&__name__),
self.similar_builtin_py_mod_name(&__name__).or_else(|| {
self.py_mod_cache
.as_ref()
.unwrap()
.get_similar_name(&__name__)
}),
));
}
};
let cfg = ErgConfig::with_path(path);
let src = cfg.input.read();
let mut builder = HIRBuilder::new_with_cache(
cfg,
var_name.inspect(),
py_mod_cache.clone(),
py_mod_cache.clone(),
);
match builder.build(src, "declare") {
Ok(hir) => {
py_mod_cache.register(var_name.clone(), Some(hir), builder.pop_ctx());
}
Err(errs) => {
errs.fmt_all_stderr();
}
}
Ok(())
}
pub(crate) fn _push_subtype_bound(&mut self, sub: Type, sup: Type) { pub(crate) fn _push_subtype_bound(&mut self, sub: Type, sup: Type) {
self.bounds.push(TyBound::subtype_of(sub, sup)); self.bounds.push(TyBound::subtype_of(sub, sup));
} }

View file

@ -166,6 +166,10 @@ impl Context {
.collect::<Vec<_>>(); .collect::<Vec<_>>();
poly(name, params) poly(name, params)
} }
MonoProj { lhs, rhs } => {
let lhs = self.generalize_t_inner(*lhs, bounds, lazy_inits);
mono_proj(lhs, rhs)
}
// REVIEW: その他何でもそのまま通していいのか? // REVIEW: その他何でもそのまま通していいのか?
other => other, other => other,
} }
@ -489,6 +493,7 @@ impl Context {
} }
Ok(()) Ok(())
} }
hir::Expr::TypeAsc(tasc) => self.resolve_expr_t(&mut tasc.expr),
hir::Expr::Code(chunks) | hir::Expr::Compound(chunks) => { hir::Expr::Code(chunks) | hir::Expr::Compound(chunks) => {
for chunk in chunks.iter_mut() { for chunk in chunks.iter_mut() {
self.resolve_expr_t(chunk)?; self.resolve_expr_t(chunk)?;

View file

@ -58,7 +58,7 @@ impl SideEffectChecker {
/// ///
/// However, it is not permitted to cause side effects within an instant block in a function /// However, it is not permitted to cause side effects within an instant block in a function
/// (side effects are allowed in instant blocks in procedures and modules) /// (side effects are allowed in instant blocks in procedures and modules)
fn in_context_se_allowed(&self) -> bool { fn in_context_effects_allowed(&self) -> bool {
// if toplevel // if toplevel
if self.block_stack.len() == 1 { if self.block_stack.len() == 1 {
return true; return true;
@ -137,6 +137,9 @@ impl SideEffectChecker {
self.path_stack.pop(); self.path_stack.pop();
self.block_stack.pop(); self.block_stack.pop();
} }
Expr::TypeAsc(tasc) => {
self.check_expr(&tasc.expr);
}
other => todo!("{other}"), other => todo!("{other}"),
} }
} }
@ -255,7 +258,7 @@ impl SideEffectChecker {
.as_ref() .as_ref()
.map(|name| name.is_procedural()) .map(|name| name.is_procedural())
.unwrap_or(false)) .unwrap_or(false))
&& !self.in_context_se_allowed() && !self.in_context_effects_allowed()
{ {
self.errs.push(EffectError::has_effect( self.errs.push(EffectError::has_effect(
line!() as usize, line!() as usize,
@ -292,6 +295,9 @@ impl SideEffectChecker {
self.path_stack.pop(); self.path_stack.pop();
self.block_stack.pop(); self.block_stack.pop();
} }
Expr::TypeAsc(type_asc) => {
self.check_expr(&type_asc.expr);
}
_ => {} _ => {}
} }
} }
@ -306,6 +312,7 @@ impl SideEffectChecker {
// !procedural: !x.y // !procedural: !x.y
Expr::Accessor(Accessor::Attr(attr)) => attr.ident.is_procedural(), Expr::Accessor(Accessor::Attr(attr)) => attr.ident.is_procedural(),
Expr::Accessor(_) => todo!(), Expr::Accessor(_) => todo!(),
Expr::TypeAsc(tasc) => self.is_procedural(&tasc.expr),
_ => false, _ => false,
} }
} }

View file

@ -8,7 +8,10 @@ use erg_common::error::{ErrorCore, ErrorDisplay, ErrorKind::*, Location, MultiEr
use erg_common::set::Set; use erg_common::set::Set;
use erg_common::traits::{Locational, Stream}; use erg_common::traits::{Locational, Stream};
use erg_common::vis::Visibility; use erg_common::vis::Visibility;
use erg_common::{fmt_iter, fmt_option_map, fmt_vec, impl_stream_for_wrapper, switch_lang, Str}; use erg_common::{
fmt_iter, fmt_option_map, fmt_vec, impl_display_and_error, impl_stream_for_wrapper,
switch_lang, Str,
};
use erg_parser::error::{ParserRunnerError, ParserRunnerErrors}; use erg_parser::error::{ParserRunnerError, ParserRunnerErrors};
@ -100,6 +103,8 @@ pub struct CompileError {
pub caused_by: AtomicStr, pub caused_by: AtomicStr,
} }
impl_display_and_error!(CompileError);
impl From<ParserRunnerError> for CompileError { impl From<ParserRunnerError> for CompileError {
fn from(err: ParserRunnerError) -> Self { fn from(err: ParserRunnerError) -> Self {
Self { Self {
@ -411,7 +416,7 @@ impl TyCheckError {
loc: Location, loc: Location,
caused_by: AtomicStr, caused_by: AtomicStr,
name: &str, name: &str,
similar_name: Option<&Str>, similar_name: Option<&str>,
) -> Self { ) -> Self {
let name = readable_name(name); let name = readable_name(name);
let hint = similar_name.map(|n| { let hint = similar_name.map(|n| {
@ -447,7 +452,7 @@ impl TyCheckError {
caused_by: AtomicStr, caused_by: AtomicStr,
obj_t: &Type, obj_t: &Type,
name: &str, name: &str,
similar_name: Option<&Str>, similar_name: Option<&str>,
) -> Self { ) -> Self {
let hint = similar_name.map(|n| { let hint = similar_name.map(|n| {
let n = readable_name(n); let n = readable_name(n);
@ -483,7 +488,7 @@ impl TyCheckError {
obj_name: &str, obj_name: &str,
obj_t: &Type, obj_t: &Type,
name: &str, name: &str,
similar_name: Option<&Str>, similar_name: Option<&str>,
) -> Self { ) -> Self {
let hint = similar_name.map(|n| { let hint = similar_name.map(|n| {
let n = readable_name(n); let n = readable_name(n);
@ -995,19 +1000,19 @@ passed keyword args: {RED}{kw_args_len}{RESET}"
switch_lang!( switch_lang!(
"japanese" => format!( "japanese" => format!(
"{RED}{name}{RESET}は{}行目ですでに移動されています", "{RED}{name}{RESET}は{}行目ですでに移動されています",
moved_loc.ln_begin().unwrap() moved_loc.ln_begin().unwrap_or(0)
), ),
"simplified_chinese" => format!( "simplified_chinese" => format!(
"{RED}{name}{RESET}已移至第{}行", "{RED}{name}{RESET}已移至第{}行",
moved_loc.ln_begin().unwrap() moved_loc.ln_begin().unwrap_or(0)
), ),
"traditional_chinese" => format!( "traditional_chinese" => format!(
"{RED}{name}{RESET}已移至第{}行", "{RED}{name}{RESET}已移至第{}行",
moved_loc.ln_begin().unwrap() moved_loc.ln_begin().unwrap_or(0)
), ),
"english" => format!( "english" => format!(
"{RED}{name}{RESET} was moved in line {}", "{RED}{name}{RESET} was moved in line {}",
moved_loc.ln_begin().unwrap() moved_loc.ln_begin().unwrap_or(0)
), ),
), ),
None, None,
@ -1293,8 +1298,70 @@ passed keyword args: {RED}{kw_args_len}{RESET}"
) )
} }
pub fn file_error(errno: usize, desc: String, loc: Location, caused_by: AtomicStr) -> Self { pub fn file_error(
Self::new(ErrorCore::new(errno, IoError, loc, desc, None), caused_by) errno: usize,
desc: String,
loc: Location,
caused_by: AtomicStr,
hint: Option<AtomicStr>,
) -> Self {
Self::new(ErrorCore::new(errno, IoError, loc, desc, hint), caused_by)
}
pub fn import_error(
errno: usize,
desc: String,
loc: Location,
caused_by: AtomicStr,
similar_erg_mod: Option<Str>,
similar_py_mod: Option<Str>,
) -> Self {
let hint = match (similar_erg_mod, similar_py_mod) {
(Some(erg), Some(py)) => Some(format!(
"similar name erg module {YELLOW}{erg}{RESET} and python module {YELLOW}{py}{RESET} exists (to import python modules, use `pyimport`)",
)),
(Some(erg), None) => Some(format!("similar name erg module exists: {YELLOW}{erg}{RESET}")),
(None, Some(py)) => Some(format!("similar name python module exists: {YELLOW}{py}{RESET} (to import python modules, use `pyimport`)")),
(None, None) => None,
};
let hint = hint.map(AtomicStr::from);
Self::file_error(errno, desc, loc, caused_by, hint)
}
pub fn inner_typedef_error(errno: usize, loc: Location, caused_by: AtomicStr) -> Self {
Self::new(
ErrorCore::new(
errno,
TypeError,
loc,
switch_lang!(
"japanese" => format!("型はトップレベルで定義されなければなりません"),
"simplified_chinese" => format!("类型必须在顶层定义"),
"traditional_chinese" => format!("類型必須在頂層定義"),
"english" => format!("types must be defined at the top level"),
),
None,
),
caused_by,
)
}
pub fn declare_error(errno: usize, loc: Location, caused_by: AtomicStr) -> Self {
Self::new(
ErrorCore::new(
errno,
SyntaxError,
loc,
switch_lang!(
"japanese" => format!("d.erファイル内では宣言、別名定義のみが許可されています"),
"simplified_chinese" => format!("在d.er文件中只允许声明和别名定义"),
"traditional_chinese" => format!("在d.er文件中只允許聲明和別名定義"),
"english" => format!("declarations and alias definitions are only allowed in d.er files"),
),
None,
),
caused_by,
)
} }
} }

View file

@ -20,6 +20,7 @@ use erg_type::value::{TypeKind, ValueObj};
use erg_type::{impl_t, impl_t_for_enum, HasType, Type}; use erg_type::{impl_t, impl_t_for_enum, HasType, Type};
use crate::context::eval::type_from_token_kind; use crate::context::eval::type_from_token_kind;
use crate::context::ImportKind;
use crate::error::readable_name; use crate::error::readable_name;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -1006,11 +1007,12 @@ impl Call {
} }
} }
pub fn is_import_call(&self) -> bool { pub fn import_kind(&self) -> Option<ImportKind> {
self.obj self.obj.show_acc().and_then(|s| match &s[..] {
.show_acc() "import" => Some(ImportKind::ErgImport),
.map(|s| &s[..] == "import" || &s[..] == "pyimport" || &s[..] == "py") "pyimport" | "py" => Some(ImportKind::PyImport),
.unwrap_or(false) _ => None,
})
} }
} }
@ -1332,7 +1334,8 @@ impl Def {
DefKind::Other DefKind::Other
} }
} }
Some("import") => DefKind::Module, Some("import") => DefKind::ErgImport,
Some("pyimport") | Some("py") => DefKind::PyImport,
_ => DefKind::Other, _ => DefKind::Other,
}, },
_ => DefKind::Other, _ => DefKind::Other,
@ -1485,6 +1488,49 @@ impl AttrDef {
} }
} }
#[derive(Debug, Clone)]
pub struct TypeAscription {
pub expr: Box<Expr>,
pub spec: TypeSpec,
}
impl NestedDisplay for TypeAscription {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
writeln!(f, "{}: {}", self.expr, self.spec)
}
}
impl_display_from_nested!(TypeAscription);
impl_locational!(TypeAscription, expr, spec);
impl HasType for TypeAscription {
#[inline]
fn ref_t(&self) -> &Type {
self.expr.ref_t()
}
#[inline]
fn ref_mut_t(&mut self) -> &mut Type {
self.expr.ref_mut_t()
}
#[inline]
fn signature_t(&self) -> Option<&Type> {
self.expr.signature_t()
}
#[inline]
fn signature_mut_t(&mut self) -> Option<&mut Type> {
self.expr.signature_mut_t()
}
}
impl TypeAscription {
pub fn new(expr: Expr, spec: TypeSpec) -> Self {
Self {
expr: Box::new(expr),
spec,
}
}
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Expr { pub enum Expr {
Lit(Literal), Lit(Literal),
@ -1502,14 +1548,15 @@ pub enum Expr {
Def(Def), Def(Def),
ClassDef(ClassDef), ClassDef(ClassDef),
AttrDef(AttrDef), AttrDef(AttrDef),
TypeAsc(TypeAscription),
Code(Block), // code object Code(Block), // code object
Compound(Block), // compound statement Compound(Block), // compound statement
} }
impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, ClassDef, AttrDef, Code, Compound); impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, ClassDef, AttrDef, Code, Compound, TypeAsc);
impl_display_from_nested!(Expr); impl_display_from_nested!(Expr);
impl_locational_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, ClassDef, AttrDef, Code, Compound); impl_locational_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, ClassDef, AttrDef, Code, Compound, TypeAsc);
impl_t_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, ClassDef, AttrDef, Code, Compound); impl_t_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def, ClassDef, AttrDef, Code, Compound, TypeAsc);
impl Expr { impl Expr {
pub fn receiver_t(&self) -> Option<&Type> { pub fn receiver_t(&self) -> Option<&Type> {
@ -1533,6 +1580,10 @@ impl Expr {
_ => None, _ => None,
} }
} }
pub fn is_type_asc(&self) -> bool {
matches!(self, Expr::TypeAsc(_))
}
} }
/// Toplevel grammar unit /// Toplevel grammar unit

View file

@ -1,19 +1,26 @@
use erg_common::config::ErgConfig; use std::mem;
use std::path::PathBuf;
use erg_common::config::{ErgConfig, Input};
use erg_common::traits::{Locational, Stream}; use erg_common::traits::{Locational, Stream};
use erg_common::Str; use erg_common::Str;
use erg_common::{enum_unwrap, log}; use erg_common::{enum_unwrap, log};
use erg_parser::ast::DefId; use erg_parser::ast::DefId;
use erg_parser::token::Token; use erg_parser::token::{Token, TokenKind};
use erg_type::value::ValueObj;
use erg_type::Type; use erg_type::Type;
use crate::hir::{Accessor, Args, Block, Call, Def, DefBody, Expr, Identifier, PosArg, HIR}; use crate::hir::{
Accessor, Args, Block, Call, Def, DefBody, Expr, Identifier, Literal, PosArg, HIR,
};
use crate::mod_cache::SharedModuleCache; use crate::mod_cache::SharedModuleCache;
pub struct Linker {} pub struct Linker {}
impl Linker { impl Linker {
#[allow(deprecated)]
pub fn link(cfg: ErgConfig, mut main: HIR, mod_cache: SharedModuleCache) -> HIR { pub fn link(cfg: ErgConfig, mut main: HIR, mod_cache: SharedModuleCache) -> HIR {
log!(info "the linking process has started."); log!(info "the linking process has started.");
for chunk in main.module.iter_mut() { for chunk in main.module.iter_mut() {
@ -22,7 +29,7 @@ impl Linker {
// ↓ // ↓
// x = ModuleType("mod") // x = ModuleType("mod")
// exec(code, x.__dict__) # `code` is the mod's content // exec(code, x.__dict__) # `code` is the mod's content
Expr::Def(ref def) if def.def_kind().is_module() => { Expr::Def(ref def) if def.def_kind().is_erg_import() => {
// In the case of REPL, entries cannot be used up // In the case of REPL, entries cannot be used up
let hir = if cfg.input.is_repl() { let hir = if cfg.input.is_repl() {
mod_cache mod_cache
@ -43,7 +50,7 @@ impl Linker {
let code = Expr::Code(Block::new(Vec::from(hir.module))); let code = Expr::Code(Block::new(Vec::from(hir.module)));
let module_type = Expr::Accessor(Accessor::private_with_line( let module_type = Expr::Accessor(Accessor::private_with_line(
Str::ever("#ModuleType"), Str::ever("#ModuleType"),
def.ln_begin().unwrap(), def.ln_begin().unwrap_or(0),
)); ));
let args = let args =
Args::new(vec![PosArg::new(mod_name.clone())], None, vec![], None); Args::new(vec![PosArg::new(mod_name.clone())], None, vec![], None);
@ -59,7 +66,7 @@ impl Linker {
)); ));
let exec = Expr::Accessor(Accessor::public_with_line( let exec = Expr::Accessor(Accessor::public_with_line(
Str::ever("exec"), Str::ever("exec"),
mod_def.ln_begin().unwrap(), mod_def.ln_begin().unwrap_or(0),
)); ));
let module = Expr::Accessor(Accessor::Ident(def.sig.ident().clone())); let module = Expr::Accessor(Accessor::Ident(def.sig.ident().clone()));
let __dict__ = Identifier::public("__dict__"); let __dict__ = Identifier::public("__dict__");
@ -76,6 +83,53 @@ impl Linker {
*chunk = Expr::Compound(compound); *chunk = Expr::Compound(compound);
} }
} }
// x = pyimport "x" (called from dir "a")
// ↓
// x = __import__("a.x").x
Expr::Def(def) if def.def_kind().is_py_import() => {
let mut dir = if let Input::File(mut path) = cfg.input.clone() {
path.pop();
path
} else {
PathBuf::new()
};
let args =
&mut enum_unwrap!(def.body.block.first_mut().unwrap(), Expr::Call).args;
let mod_name_lit =
enum_unwrap!(args.remove_left_or_key("path").unwrap(), Expr::Lit);
let mod_name_str = enum_unwrap!(mod_name_lit.value.clone(), ValueObj::Str);
let mod_name_str = if let Some(stripped) = mod_name_str.strip_prefix("./") {
stripped
} else {
&mod_name_str
};
dir.push(mod_name_str);
let mut comps = dir.components();
let _first = comps.next().unwrap();
let path = dir.to_string_lossy().replace('/', ".").replace('\\', ".");
let token = Token::new(
TokenKind::StrLit,
path,
mod_name_lit.ln_begin().unwrap(),
mod_name_lit.col_begin().unwrap(),
);
let mod_name = Expr::Lit(Literal::from(token));
args.insert_pos(0, PosArg::new(mod_name));
let expr = def.body.block.first_mut().unwrap();
let line = expr.ln_begin().unwrap_or(0);
for attr in comps {
*expr = Expr::Accessor(Accessor::attr(
// instead of mem::take(),
mem::replace(expr, Expr::Code(Block::empty())),
Identifier::public_with_line(
Token::dummy(),
Str::rc(attr.as_os_str().to_str().unwrap()),
line,
),
Type::Uninited,
));
}
}
_ => {} _ => {}
} }
} }

View file

@ -30,6 +30,7 @@ use crate::error::{
use crate::hir; use crate::hir;
use crate::hir::HIR; use crate::hir::HIR;
use crate::mod_cache::SharedModuleCache; use crate::mod_cache::SharedModuleCache;
use crate::reorder::Reorderer;
use crate::varinfo::VarKind; use crate::varinfo::VarKind;
use Visibility::*; use Visibility::*;
@ -48,6 +49,7 @@ impl Default for ASTLowerer {
ErgConfig::default(), ErgConfig::default(),
Str::ever("<module>"), Str::ever("<module>"),
SharedModuleCache::new(), SharedModuleCache::new(),
SharedModuleCache::new(),
) )
} }
} }
@ -63,7 +65,12 @@ impl Runnable for ASTLowerer {
} }
fn new(cfg: ErgConfig) -> Self { fn new(cfg: ErgConfig) -> Self {
Self::new_with_cache(cfg, Str::ever("<module>"), SharedModuleCache::new()) Self::new_with_cache(
cfg,
Str::ever("<module>"),
SharedModuleCache::new(),
SharedModuleCache::new(),
)
} }
#[inline] #[inline]
@ -86,7 +93,7 @@ impl Runnable for ASTLowerer {
Ok(()) Ok(())
} }
fn eval(&mut self, src: String) -> Result<String, CompileErrors> { fn eval(&mut self, src: String) -> Result<String, Self::Errs> {
let mut ast_builder = ASTBuilder::new(self.cfg.copy()); let mut ast_builder = ASTBuilder::new(self.cfg.copy());
let ast = ast_builder.build(src)?; let ast = ast_builder.build(src)?;
let (hir, ..) = self.lower(ast, "eval").map_err(|errs| self.convert(errs))?; let (hir, ..) = self.lower(ast, "eval").map_err(|errs| self.convert(errs))?;
@ -99,10 +106,11 @@ impl ASTLowerer {
cfg: ErgConfig, cfg: ErgConfig,
mod_name: S, mod_name: S,
mod_cache: SharedModuleCache, mod_cache: SharedModuleCache,
py_mod_cache: SharedModuleCache,
) -> Self { ) -> Self {
Self { Self {
cfg, cfg,
ctx: Context::new_module(mod_name, mod_cache), ctx: Context::new_module(mod_name, mod_cache, py_mod_cache),
errs: LowerErrors::empty(), errs: LowerErrors::empty(),
warns: LowerWarnings::empty(), warns: LowerWarnings::empty(),
} }
@ -138,8 +146,12 @@ impl ASTLowerer {
}) })
} }
/// OK: exec `i: Int`
/// OK: exec `i: Int = 1`
/// NG: exec `1 + 2`
/// OK: exec `None`
fn use_check(&self, expr: &hir::Expr, mode: &str) -> LowerResult<()> { fn use_check(&self, expr: &hir::Expr, mode: &str) -> LowerResult<()> {
if mode != "eval" && !expr.ref_t().is_nonelike() { if mode != "eval" && !expr.ref_t().is_nonelike() && !expr.is_type_asc() {
Err(LowerError::syntax_error( Err(LowerError::syntax_error(
0, 0,
expr.loc(), expr.loc(),
@ -533,27 +545,41 @@ impl ASTLowerer {
fn lower_def(&mut self, def: ast::Def) -> LowerResult<hir::Def> { fn lower_def(&mut self, def: ast::Def) -> LowerResult<hir::Def> {
log!(info "entered {}({})", fn_name!(), def.sig); log!(info "entered {}({})", fn_name!(), def.sig);
if def.def_kind().is_class_or_trait() && self.ctx.kind != ContextKind::Module {
self.ctx.decls.remove(def.sig.ident().unwrap().inspect());
return Err(LowerError::inner_typedef_error(
line!() as usize,
def.loc(),
self.ctx.caused_by(),
));
}
let name = if let Some(name) = def.sig.name_as_str() { let name = if let Some(name) = def.sig.name_as_str() {
name name.clone()
} else { } else {
"<lambda>" Str::ever("<lambda>")
}; };
if self.ctx.registered_info(name, def.sig.is_const()).is_some() { if self
.ctx
.registered_info(&name, def.sig.is_const())
.is_some()
{
return Err(LowerError::reassign_error( return Err(LowerError::reassign_error(
line!() as usize, line!() as usize,
def.sig.loc(), def.sig.loc(),
self.ctx.caused_by(), self.ctx.caused_by(),
name, &name,
)); ));
} }
let kind = ContextKind::from(def.def_kind()); let kind = ContextKind::from(def.def_kind());
self.ctx.grow(name, kind, def.sig.vis())?; self.ctx.grow(&name, kind, def.sig.vis())?;
let res = match def.sig { let res = match def.sig {
ast::Signature::Subr(sig) => self.lower_subr_def(sig, def.body), ast::Signature::Subr(sig) => self.lower_subr_def(sig, def.body),
ast::Signature::Var(sig) => self.lower_var_def(sig, def.body), ast::Signature::Var(sig) => self.lower_var_def(sig, def.body),
}; };
// TODO: Context上の関数に型境界情報を追加 // TODO: Context上の関数に型境界情報を追加
self.pop_append_errs(); self.pop_append_errs();
// remove from decls regardless of success or failure to lower
self.ctx.decls.remove(&name);
res res
} }
@ -589,7 +615,6 @@ impl ASTLowerer {
} }
} }
let id = body.id; let id = body.id;
// TODO: cover all VarPatterns
self.ctx self.ctx
.outer .outer
.as_mut() .as_mut()
@ -597,9 +622,10 @@ impl ASTLowerer {
.assign_var_sig(&sig, found_body_t, id)?; .assign_var_sig(&sig, found_body_t, id)?;
match block.first().unwrap() { match block.first().unwrap() {
hir::Expr::Call(call) => { hir::Expr::Call(call) => {
if call.is_import_call() { if let Some(kind) = call.import_kind() {
let current_input = self.input().clone(); let current_input = self.input().clone();
self.ctx.outer.as_mut().unwrap().import_mod( self.ctx.outer.as_mut().unwrap().import_mod(
kind,
current_input, current_input,
&ident.name, &ident.name,
&call.args.pos_args.first().unwrap().expr, &call.args.pos_args.first().unwrap().expr,
@ -960,6 +986,25 @@ impl ASTLowerer {
} }
} }
fn lower_type_asc(&mut self, tasc: ast::TypeAscription) -> LowerResult<hir::TypeAscription> {
log!(info "entered {}({tasc})", fn_name!());
let t = self.ctx.instantiate_typespec(
&tasc.t_spec,
None,
&mut None,
RegistrationMode::Normal,
)?;
let expr = self.lower_expr(*tasc.expr)?;
self.ctx.sub_unify(
expr.ref_t(),
&t,
Some(expr.loc()),
None,
Some(&Str::from(expr.to_string())),
)?;
Ok(hir::TypeAscription::new(expr, tasc.t_spec))
}
// Call.obj == Accessor cannot be type inferred by itself (it can only be inferred with arguments) // Call.obj == Accessor cannot be type inferred by itself (it can only be inferred with arguments)
// so turn off type checking (check=false) // so turn off type checking (check=false)
fn lower_expr(&mut self, expr: ast::Expr) -> LowerResult<hir::Expr> { fn lower_expr(&mut self, expr: ast::Expr) -> LowerResult<hir::Expr> {
@ -977,6 +1022,7 @@ impl ASTLowerer {
ast::Expr::Lambda(lambda) => Ok(hir::Expr::Lambda(self.lower_lambda(lambda)?)), ast::Expr::Lambda(lambda) => Ok(hir::Expr::Lambda(self.lower_lambda(lambda)?)),
ast::Expr::Def(def) => Ok(hir::Expr::Def(self.lower_def(def)?)), ast::Expr::Def(def) => Ok(hir::Expr::Def(self.lower_def(def)?)),
ast::Expr::ClassDef(defs) => Ok(hir::Expr::ClassDef(self.lower_class_def(defs)?)), ast::Expr::ClassDef(defs) => Ok(hir::Expr::ClassDef(self.lower_class_def(defs)?)),
ast::Expr::TypeAsc(tasc) => Ok(hir::Expr::TypeAsc(self.lower_type_asc(tasc)?)),
other => todo!("{other}"), other => todo!("{other}"),
} }
} }
@ -991,9 +1037,138 @@ impl ASTLowerer {
Ok(hir::Block::new(hir_block)) Ok(hir::Block::new(hir_block))
} }
fn declare_var_alias(
&mut self,
sig: ast::VarSignature,
mut body: ast::DefBody,
) -> LowerResult<hir::Def> {
log!(info "entered {}({sig})", fn_name!());
if body.block.len() > 1 {
return Err(LowerError::declare_error(
line!() as usize,
body.block.loc(),
self.ctx.caused_by(),
));
}
let block = hir::Block::new(vec![self.declare_chunk(body.block.remove(0))?]);
let found_body_t = block.ref_t();
let ident = match &sig.pat {
ast::VarPattern::Ident(ident) => ident,
_ => unreachable!(),
};
let id = body.id;
self.ctx.assign_var_sig(&sig, found_body_t, id)?;
let ident = hir::Identifier::bare(ident.dot.clone(), ident.name.clone());
let sig = hir::VarSignature::new(ident, found_body_t.clone());
let body = hir::DefBody::new(body.op, block, body.id);
Ok(hir::Def::new(hir::Signature::Var(sig), body))
}
fn declare_alias(&mut self, def: ast::Def) -> LowerResult<hir::Def> {
log!(info "entered {}({})", fn_name!(), def.sig);
let name = if let Some(name) = def.sig.name_as_str() {
name.clone()
} else {
Str::ever("<lambda>")
};
if self
.ctx
.registered_info(&name, def.sig.is_const())
.is_some()
{
return Err(LowerError::reassign_error(
line!() as usize,
def.sig.loc(),
self.ctx.caused_by(),
&name,
));
}
let res = match def.sig {
ast::Signature::Subr(_sig) => todo!(),
ast::Signature::Var(sig) => self.declare_var_alias(sig, def.body),
};
self.pop_append_errs();
res
}
fn declare_type(&mut self, tasc: ast::TypeAscription) -> LowerResult<hir::TypeAscription> {
log!(info "entered {}({})", fn_name!(), tasc);
match *tasc.expr {
ast::Expr::Accessor(ast::Accessor::Ident(ident)) => {
let t = self.ctx.instantiate_typespec(
&tasc.t_spec,
None,
&mut None,
RegistrationMode::Normal,
)?;
self.ctx.assign_var_sig(
&ast::VarSignature::new(ast::VarPattern::Ident(ident.clone()), None),
&t,
ast::DefId(0),
)?;
let ident = hir::Identifier::new(ident.dot, ident.name, None, t);
Ok(hir::TypeAscription::new(
hir::Expr::Accessor(hir::Accessor::Ident(ident)),
tasc.t_spec,
))
}
other => Err(LowerError::declare_error(
line!() as usize,
other.loc(),
self.ctx.caused_by(),
)),
}
}
fn declare_chunk(&mut self, expr: ast::Expr) -> LowerResult<hir::Expr> {
log!(info "entered {}", fn_name!());
match expr {
ast::Expr::Def(def) => Ok(hir::Expr::Def(self.declare_alias(def)?)),
ast::Expr::ClassDef(defs) => Err(LowerError::feature_error(
line!() as usize,
defs.loc(),
"class declaration",
self.ctx.caused_by(),
)),
ast::Expr::TypeAsc(tasc) => Ok(hir::Expr::TypeAsc(self.declare_type(tasc)?)),
other => Err(LowerError::declare_error(
line!() as usize,
other.loc(),
self.ctx.caused_by(),
)),
}
}
fn declare_module(&mut self, ast: AST) -> HIR {
let mut module = hir::Module::with_capacity(ast.module.len());
for chunk in ast.module.into_iter() {
match self.declare_chunk(chunk) {
Ok(chunk) => {
module.push(chunk);
}
Err(e) => {
self.errs.push(e);
}
}
}
HIR::new(ast.name, module)
}
pub fn lower(&mut self, ast: AST, mode: &str) -> Result<(HIR, LowerWarnings), LowerErrors> { pub fn lower(&mut self, ast: AST, mode: &str) -> Result<(HIR, LowerWarnings), LowerErrors> {
log!(info "the AST lowering process has started."); log!(info "the AST lowering process has started.");
log!(info "the type-checking process has started."); log!(info "the type-checking process has started.");
let ast = Reorderer::new().reorder(ast)?;
if mode == "declare" {
let hir = self.declare_module(ast);
if self.errs.is_empty() {
log!(info "HIR:\n{hir}");
log!(info "the declaring process has completed.");
return Ok((hir, LowerWarnings::from(self.warns.take_all())));
} else {
log!(err "the declaring process has failed.");
return Err(LowerErrors::from(self.errs.take_all()));
}
}
let mut module = hir::Module::with_capacity(ast.module.len()); let mut module = hir::Module::with_capacity(ast.module.len());
self.ctx.preregister(ast.module.block())?; self.ctx.preregister(ast.module.block())?;
for chunk in ast.module.into_iter() { for chunk in ast.module.into_iter() {
@ -1006,10 +1181,19 @@ impl ASTLowerer {
} }
} }
} }
self.ctx.check_decls()?; self.ctx.check_decls().unwrap_or_else(|mut errs| {
self.errs.append(&mut errs);
});
let hir = HIR::new(ast.name, module); let hir = HIR::new(ast.name, module);
log!(info "HIR (not resolved, current errs: {}):\n{hir}", self.errs.len()); log!(info "HIR (not resolved, current errs: {}):\n{hir}", self.errs.len());
let hir = self.ctx.resolve(hir)?; let hir = match self.ctx.resolve(hir) {
Ok(hir) => hir,
Err(err) => {
self.errs.push(err);
log!(err "the AST lowering process has failed.");
return Err(LowerErrors::from(self.errs.take_all()));
}
};
// TODO: recursive check // TODO: recursive check
for chunk in hir.module.iter() { for chunk in hir.module.iter() {
if let Err(e) = self.use_check(chunk, mode) { if let Err(e) = self.use_check(chunk, mode) {

View file

@ -4,7 +4,9 @@ use std::hash::Hash;
use std::rc::Rc; use std::rc::Rc;
use erg_common::dict::Dict; use erg_common::dict::Dict;
use erg_common::levenshtein::get_similar_name;
use erg_common::shared::Shared; use erg_common::shared::Shared;
use erg_common::Str;
use erg_parser::ast::VarName; use erg_parser::ast::VarName;
@ -26,7 +28,7 @@ impl ModId {
} }
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct ModuleEntry { pub struct ModuleEntry {
id: ModId, // builtin == 0, __main__ == 1 id: ModId, // builtin == 0, __main__ == 1
pub hir: Option<HIR>, pub hir: Option<HIR>,
@ -88,6 +90,12 @@ impl ModuleCache {
self.cache.get(name) self.cache.get(name)
} }
pub fn get_by_name(&self, __name__: &str) -> Option<(&VarName, &ModuleEntry)> {
self.cache
.iter()
.find(|(_, ent)| &ent.ctx.name[..] == __name__)
}
pub fn get_mut<Q: Eq + Hash + ?Sized>(&mut self, name: &Q) -> Option<&mut ModuleEntry> pub fn get_mut<Q: Eq + Hash + ?Sized>(&mut self, name: &Q) -> Option<&mut ModuleEntry>
where where
VarName: Borrow<Q>, VarName: Borrow<Q>,
@ -102,6 +110,10 @@ impl ModuleCache {
self.cache.insert(name, entry); self.cache.insert(name, entry);
} }
pub fn register_alias(&mut self, name: VarName, entry: &ModuleEntry) {
self.cache.insert(name, entry.clone());
}
pub fn remove<Q: Eq + Hash + ?Sized>(&mut self, name: &Q) -> Option<ModuleEntry> pub fn remove<Q: Eq + Hash + ?Sized>(&mut self, name: &Q) -> Option<ModuleEntry>
where where
VarName: Borrow<Q>, VarName: Borrow<Q>,
@ -122,6 +134,10 @@ impl ModuleCache {
None None
} }
} }
pub fn get_similar_name(&self, name: &str) -> Option<Str> {
get_similar_name(self.cache.iter().map(|(v, _)| &v.inspect()[..]), name).map(Str::rc)
}
} }
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
@ -148,6 +164,11 @@ impl SharedModuleCache {
ref_.get(name) ref_.get(name)
} }
pub fn get_by_name(&self, __name__: &str) -> Option<(&VarName, &ModuleEntry)> {
let ref_ = unsafe { self.0.as_ptr().as_ref().unwrap() };
ref_.get_by_name(__name__)
}
pub fn get_mut<Q: Eq + Hash + ?Sized>(&self, name: &Q) -> Option<&mut ModuleEntry> pub fn get_mut<Q: Eq + Hash + ?Sized>(&self, name: &Q) -> Option<&mut ModuleEntry>
where where
VarName: Borrow<Q>, VarName: Borrow<Q>,
@ -175,6 +196,10 @@ impl SharedModuleCache {
self.0.borrow_mut().register(name, hir, ctx); self.0.borrow_mut().register(name, hir, ctx);
} }
pub fn register_alias(&self, name: VarName, entry: &ModuleEntry) {
self.0.borrow_mut().register_alias(name, entry);
}
pub fn remove<Q: Eq + Hash + ?Sized>(&self, name: &Q) -> Option<ModuleEntry> pub fn remove<Q: Eq + Hash + ?Sized>(&self, name: &Q) -> Option<ModuleEntry>
where where
VarName: Borrow<Q>, VarName: Borrow<Q>,
@ -185,4 +210,8 @@ impl SharedModuleCache {
pub fn remove_by_id(&self, id: ModId) -> Option<ModuleEntry> { pub fn remove_by_id(&self, id: ModId) -> Option<ModuleEntry> {
self.0.borrow_mut().remove_by_id(id) self.0.borrow_mut().remove_by_id(id)
} }
pub fn get_similar_name(&self, name: &str) -> Option<Str> {
self.0.borrow().get_similar_name(name)
}
} }

View file

@ -187,6 +187,9 @@ impl OwnershipChecker {
self.check_block(&lambda.body); self.check_block(&lambda.body);
self.path_stack.pop(); self.path_stack.pop();
} }
Expr::TypeAsc(asc) => {
self.check_expr(&asc.expr, ownership, chunk);
}
_ => {} _ => {}
} }
} }

View file

@ -3,14 +3,22 @@ use erg_compiler::mod_cache::SharedModuleCache;
#[test] #[test]
fn test_subtyping() -> Result<(), ()> { fn test_subtyping() -> Result<(), ()> {
let context = Context::new_module("<module>", SharedModuleCache::new()); let context = Context::new_module(
"<module>",
SharedModuleCache::new(),
SharedModuleCache::new(),
);
context.test_refinement_subtyping()?; context.test_refinement_subtyping()?;
Ok(()) Ok(())
} }
#[test] #[test]
fn test_instantiation_and_generalization() -> Result<(), ()> { fn test_instantiation_and_generalization() -> Result<(), ()> {
let context = Context::new_module("<module>", SharedModuleCache::new()); let context = Context::new_module(
"<module>",
SharedModuleCache::new(),
SharedModuleCache::new(),
);
context.test_instantiation_and_generalization()?; context.test_instantiation_and_generalization()?;
Ok(()) Ok(())
} }
@ -30,3 +38,17 @@ fn test_resolve_trait_inner1() -> Result<(), ()> {
Ok(()) Ok(())
} }
*/ */
#[test]
fn test_dir() -> Result<(), ()> {
let context = Context::new_module(
"<module>",
SharedModuleCache::new(),
SharedModuleCache::new(),
);
let vars = context.dir();
for (name, vi) in vars.into_iter() {
println!("{name}: {vi}");
}
Ok(())
}

View file

@ -1,6 +1,6 @@
[package] [package]
name = "erg_parser" name = "erg_parser"
version = "0.5.1" version = "0.5.5-nightly.1"
description = "The Erg parser" description = "The Erg parser"
authors = ["erg-lang team <moderation.erglang@gmail.com>"] authors = ["erg-lang team <moderation.erglang@gmail.com>"]
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
@ -16,7 +16,7 @@ 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.1", path = "../erg_common" } erg_common = { version = "0.5.5-nightly.1", path = "../erg_common" }
[lib] [lib]
path = "lib.rs" path = "lib.rs"

View file

@ -1511,6 +1511,7 @@ impl ParamTySpec {
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct SubrTypeSpec { pub struct SubrTypeSpec {
pub bounds: TypeBoundSpecs,
pub lparen: Option<Token>, pub lparen: Option<Token>,
pub non_defaults: Vec<ParamTySpec>, pub non_defaults: Vec<ParamTySpec>,
pub var_args: Option<Box<ParamTySpec>>, pub var_args: Option<Box<ParamTySpec>>,
@ -1521,9 +1522,12 @@ pub struct SubrTypeSpec {
impl fmt::Display for SubrTypeSpec { impl fmt::Display for SubrTypeSpec {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if !self.bounds.is_empty() {
write!(f, "|{}|", self.bounds)?;
}
write!( write!(
f, f,
"({}, {}, := {}) {} {}", "({}, {}, {}) {} {}",
fmt_vec(&self.non_defaults), fmt_vec(&self.non_defaults),
fmt_option!(pre "...", &self.var_args), fmt_option!(pre "...", &self.var_args),
fmt_vec(&self.defaults), fmt_vec(&self.defaults),
@ -1535,7 +1539,9 @@ impl fmt::Display for SubrTypeSpec {
impl Locational for SubrTypeSpec { impl Locational for SubrTypeSpec {
fn loc(&self) -> Location { fn loc(&self) -> Location {
if let Some(lparen) = &self.lparen { if !self.bounds.is_empty() {
Location::concat(&self.bounds[0], self.return_t.as_ref())
} else if let Some(lparen) = &self.lparen {
Location::concat(lparen, self.return_t.as_ref()) Location::concat(lparen, self.return_t.as_ref())
} else { } else {
// FIXME: only default subrs // FIXME: only default subrs
@ -1546,6 +1552,7 @@ impl Locational for SubrTypeSpec {
impl SubrTypeSpec { impl SubrTypeSpec {
pub fn new( pub fn new(
bounds: TypeBoundSpecs,
lparen: Option<Token>, lparen: Option<Token>,
non_defaults: Vec<ParamTySpec>, non_defaults: Vec<ParamTySpec>,
var_args: Option<ParamTySpec>, var_args: Option<ParamTySpec>,
@ -1554,6 +1561,7 @@ impl SubrTypeSpec {
return_t: TypeSpec, return_t: TypeSpec,
) -> Self { ) -> Self {
Self { Self {
bounds,
lparen, lparen,
non_defaults, non_defaults,
var_args: var_args.map(Box::new), var_args: var_args.map(Box::new),
@ -2841,7 +2849,9 @@ pub enum DefKind {
Trait, Trait,
Subsume, Subsume,
StructuralTrait, StructuralTrait,
Module, ErgImport,
PyImport,
/// type alias included
Other, Other,
} }
@ -2850,8 +2860,20 @@ impl DefKind {
matches!(self, Self::Trait | Self::Subsume | Self::StructuralTrait) matches!(self, Self::Trait | Self::Subsume | Self::StructuralTrait)
} }
pub fn is_module(&self) -> bool { pub const fn is_class(&self) -> bool {
matches!(self, Self::Module) matches!(self, Self::Class | Self::Inherit)
}
pub const fn is_class_or_trait(&self) -> bool {
self.is_class() || self.is_trait()
}
pub fn is_erg_import(&self) -> bool {
matches!(self, Self::ErgImport)
}
pub fn is_py_import(&self) -> bool {
matches!(self, Self::PyImport)
} }
} }
@ -2868,6 +2890,32 @@ impl DefBody {
pub const fn new(op: Token, block: Block, id: DefId) -> Self { pub const fn new(op: Token, block: Block, id: DefId) -> Self {
Self { op, block, id } Self { op, block, id }
} }
pub fn def_kind(&self) -> DefKind {
match self.block.first().unwrap() {
Expr::Call(call) => match call.obj.get_name().map(|n| &n[..]) {
Some("Class") => DefKind::Class,
Some("Inherit") => DefKind::Inherit,
Some("Trait") => DefKind::Trait,
Some("Subsume") => DefKind::Subsume,
Some("Inheritable") => {
if let Some(Expr::Call(inner)) = call.args.get_left_or_key("Class") {
match inner.obj.get_name().map(|n| &n[..]) {
Some("Class") => DefKind::Class,
Some("Inherit") => DefKind::Inherit,
_ => DefKind::Other,
}
} else {
DefKind::Other
}
}
Some("import") => DefKind::ErgImport,
Some("pyimport") | Some("py") => DefKind::PyImport,
_ => DefKind::Other,
},
_ => DefKind::Other,
}
}
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@ -2901,28 +2949,7 @@ impl Def {
} }
pub fn def_kind(&self) -> DefKind { pub fn def_kind(&self) -> DefKind {
match self.body.block.first().unwrap() { self.body.def_kind()
Expr::Call(call) => match call.obj.get_name().map(|n| &n[..]) {
Some("Class") => DefKind::Class,
Some("Inherit") => DefKind::Inherit,
Some("Trait") => DefKind::Trait,
Some("Subsume") => DefKind::Subsume,
Some("Inheritable") => {
if let Some(Expr::Call(inner)) = call.args.get_left_or_key("Class") {
match inner.obj.get_name().map(|n| &n[..]) {
Some("Class") => DefKind::Class,
Some("Inherit") => DefKind::Inherit,
_ => DefKind::Other,
}
} else {
DefKind::Other
}
}
Some("import") => DefKind::Module,
_ => DefKind::Other,
},
_ => DefKind::Other,
}
} }
} }

View file

@ -6,7 +6,7 @@ use erg_common::color::{RED, RESET};
use erg_common::config::Input; use erg_common::config::Input;
use erg_common::error::{ErrorCore, ErrorDisplay, ErrorKind::*, Location, MultiErrorDisplay}; use erg_common::error::{ErrorCore, ErrorDisplay, ErrorKind::*, Location, MultiErrorDisplay};
use erg_common::traits::Stream; use erg_common::traits::Stream;
use erg_common::{impl_stream_for_wrapper, switch_lang}; use erg_common::{impl_display_and_error, impl_stream_for_wrapper, switch_lang};
#[derive(Debug)] #[derive(Debug)]
pub struct LexError(ErrorCore); pub struct LexError(ErrorCore);
@ -144,6 +144,8 @@ pub struct ParserRunnerError {
pub input: Input, pub input: Input,
} }
impl_display_and_error!(ParserRunnerError);
impl ErrorDisplay for ParserRunnerError { impl ErrorDisplay for ParserRunnerError {
fn core(&self) -> &ErrorCore { fn core(&self) -> &ErrorCore {
&self.core &self.core

View file

@ -362,7 +362,10 @@ impl Parser {
if self.cur_is(Newline) { if self.cur_is(Newline) {
self.skip(); self.skip();
} else { } else {
todo!() self.level -= 1;
let err = self.skip_and_throw_syntax_err(caused_by!());
self.errs.push(err);
return Err(());
} }
} }
self.level -= 1; self.level -= 1;
@ -863,13 +866,24 @@ impl Parser {
if self.cur_is(Indent) { if self.cur_is(Indent) {
self.skip(); self.skip();
} else { } else {
todo!() self.level -= 1;
let err = self.skip_and_throw_syntax_err(caused_by!());
self.errs.push(err);
return Err(());
} }
while self.cur_is(Newline) { while self.cur_is(Newline) {
self.skip(); self.skip();
} }
let first = self.try_reduce_chunk(false).map_err(|_| self.stack_dec())?; let first = self.try_reduce_chunk(false).map_err(|_| self.stack_dec())?;
let first = option_enum_unwrap!(first, Expr::Def).unwrap_or_else(|| todo!()); let first = if let Some(fst) = option_enum_unwrap!(first, Expr::Def) {
fst
} else {
// self.restore();
self.level -= 1;
let err = self.skip_and_throw_syntax_err(caused_by!());
self.errs.push(err);
return Err(());
};
let mut defs = vec![first]; let mut defs = vec![first];
loop { loop {
match self.peek() { match self.peek() {
@ -894,7 +908,12 @@ impl Parser {
} }
} }
} }
_ => todo!(), _ => {
self.level -= 1;
let err = self.skip_and_throw_syntax_err(caused_by!());
self.errs.push(err);
return Err(());
}
} }
} }
let defs = RecordAttrs::from(defs); let defs = RecordAttrs::from(defs);
@ -912,7 +931,7 @@ impl Parser {
let op = match &do_symbol.inspect()[..] { let op = match &do_symbol.inspect()[..] {
"do" => Token::from_str(FuncArrow, "->"), "do" => Token::from_str(FuncArrow, "->"),
"do!" => Token::from_str(ProcArrow, "=>"), "do!" => Token::from_str(ProcArrow, "=>"),
_ => todo!(), _ => unreachable!(),
}; };
if self.cur_is(Colon) { if self.cur_is(Colon) {
self.lpop(); self.lpop();
@ -1058,8 +1077,13 @@ impl Parser {
let pack = DataPack::new(maybe_class, vis, args); let pack = DataPack::new(maybe_class, vis, args);
stack.push(ExprOrOp::Expr(Expr::DataPack(pack))); stack.push(ExprOrOp::Expr(Expr::DataPack(pack)));
} }
BraceContainer::Dict(dict) => todo!("{dict}"), BraceContainer::Dict(_) | BraceContainer::Set(_) => {
BraceContainer::Set(set) => todo!("{set}"), // self.restore(other);
self.level -= 1;
let err = self.skip_and_throw_syntax_err(caused_by!());
self.errs.push(err);
return Err(());
}
} }
} }
other => { other => {
@ -1344,7 +1368,15 @@ impl Parser {
Some(t) if t.is(AtSign) => { Some(t) if t.is(AtSign) => {
let decos = self.opt_reduce_decorators()?; let decos = self.opt_reduce_decorators()?;
let expr = self.try_reduce_chunk(false)?; let expr = self.try_reduce_chunk(false)?;
let mut def = option_enum_unwrap!(expr, Expr::Def).unwrap_or_else(|| todo!()); let mut def = if let Some(def) = option_enum_unwrap!(expr, Expr::Def) {
def
} else {
// self.restore(other);
self.level -= 1;
let err = self.skip_and_throw_syntax_err(caused_by!());
self.errs.push(err);
return Err(());
};
match def.sig { match def.sig {
Signature::Subr(mut subr) => { Signature::Subr(mut subr) => {
subr.decorators = decos; subr.decorators = decos;
@ -1509,7 +1541,15 @@ impl Parser {
ArrayInner::WithLength(elem, len) => { ArrayInner::WithLength(elem, len) => {
Array::WithLength(ArrayWithLength::new(l_sqbr, r_sqbr, elem, len)) Array::WithLength(ArrayWithLength::new(l_sqbr, r_sqbr, elem, len))
} }
ArrayInner::Comprehension { .. } => todo!(), ArrayInner::Comprehension { .. } => {
self.level -= 1;
self.errs.push(ParseError::feature_error(
line!() as usize,
Location::concat(&l_sqbr, &r_sqbr),
"array comprehension",
));
return Err(());
}
}; };
self.level -= 1; self.level -= 1;
Ok(arr) Ok(arr)
@ -1525,7 +1565,10 @@ impl Parser {
if self.cur_is(Indent) { if self.cur_is(Indent) {
self.skip(); self.skip();
} else { } else {
todo!() self.level -= 1;
let err = self.skip_and_throw_syntax_err(caused_by!());
self.errs.push(err);
return Err(());
} }
} }
let first = self.try_reduce_chunk(false).map_err(|_| self.stack_dec())?; let first = self.try_reduce_chunk(false).map_err(|_| self.stack_dec())?;
@ -1576,7 +1619,12 @@ impl Parser {
let attrs = RecordAttrs::from(attrs); let attrs = RecordAttrs::from(attrs);
return Ok(NormalRecord::new(l_brace, r_brace, attrs)); return Ok(NormalRecord::new(l_brace, r_brace, attrs));
} else { } else {
todo!() // TODO: not closed
// self.restore(other);
self.level -= 1;
let err = self.skip_and_throw_syntax_err(caused_by!());
self.errs.push(err);
return Err(());
} }
} }
Some(term) if term.is(RBrace) => { Some(term) if term.is(RBrace) => {
@ -1587,10 +1635,24 @@ impl Parser {
} }
Some(_) => { Some(_) => {
let def = self.try_reduce_chunk(false).map_err(|_| self.stack_dec())?; let def = self.try_reduce_chunk(false).map_err(|_| self.stack_dec())?;
let def = option_enum_unwrap!(def, Expr::Def).unwrap_or_else(|| todo!()); let def = if let Some(def) = option_enum_unwrap!(def, Expr::Def) {
def
} else {
// self.restore(other);
self.level -= 1;
let err = self.skip_and_throw_syntax_err(caused_by!());
self.errs.push(err);
return Err(());
};
attrs.push(def); attrs.push(def);
} }
_ => todo!(), _ => {
// self.restore(other);
self.level -= 1;
let err = self.skip_and_throw_syntax_err(caused_by!());
self.errs.push(err);
return Err(());
}
} }
} }
} }
@ -1603,7 +1665,12 @@ impl Parser {
debug_call_info!(self); debug_call_info!(self);
let first = match first { let first = match first {
Accessor::Ident(ident) => ident, Accessor::Ident(ident) => ident,
other => todo!("{other}"), // syntax error other => {
self.level -= 1;
let err = ParseError::simple_syntax_error(line!() as usize, other.loc());
self.errs.push(err);
return Err(());
}
}; };
let mut idents = vec![first]; let mut idents = vec![first];
loop { loop {
@ -1618,7 +1685,11 @@ impl Parser {
self.level -= 1; self.level -= 1;
return Ok(ShortenedRecord::new(l_brace, r_brace, idents)); return Ok(ShortenedRecord::new(l_brace, r_brace, idents));
} else { } else {
todo!() // self.restore(other);
self.level -= 1;
let err = self.skip_and_throw_syntax_err(caused_by!());
self.errs.push(err);
return Err(());
} }
} }
Some(term) if term.is(RBrace) => { Some(term) if term.is(RBrace) => {
@ -1630,11 +1701,22 @@ impl Parser {
let acc = self.try_reduce_acc(false).map_err(|_| self.stack_dec())?; let acc = self.try_reduce_acc(false).map_err(|_| self.stack_dec())?;
let acc = match acc { let acc = match acc {
Accessor::Ident(ident) => ident, Accessor::Ident(ident) => ident,
other => todo!("{other}"), // syntax error other => {
self.level -= 1;
let err =
ParseError::simple_syntax_error(line!() as usize, other.loc());
self.errs.push(err);
return Err(());
}
}; };
idents.push(acc); idents.push(acc);
} }
_ => todo!(), _ => {
self.level -= 1;
let err = self.skip_and_throw_syntax_err(caused_by!());
self.errs.push(err);
return Err(());
}
} }
} }
} }
@ -1669,7 +1751,12 @@ impl Parser {
args.push_pos(PosArg::new(other)); args.push_pos(PosArg::new(other));
} }
}, },
PosOrKwArg::Kw(_arg) => todo!(), PosOrKwArg::Kw(arg) => {
self.level -= 1;
let err = ParseError::simple_syntax_error(line!() as usize, arg.loc());
self.errs.push(err);
return Err(());
}
} }
} }
_ => { _ => {
@ -1808,7 +1895,22 @@ impl Parser {
self.level -= 1; self.level -= 1;
Ok(pat) Ok(pat)
} }
_ => todo!(), Array::Comprehension(arr) => {
self.level -= 1;
let err = ParseError::simple_syntax_error(line!() as usize, arr.loc());
self.errs.push(err);
Err(())
}
Array::WithLength(arr) => {
self.level -= 1;
let err = ParseError::feature_error(
line!() as usize,
arr.loc(),
"array-with-length pattern",
);
self.errs.push(err);
Err(())
}
} }
} }
@ -1876,7 +1978,13 @@ impl Parser {
Signature::Var(var) => { Signature::Var(var) => {
vars.push(var); vars.push(var);
} }
other => todo!("{other}"), other => {
self.level -= 1;
let err =
ParseError::simple_syntax_error(line!() as usize, other.loc());
self.errs.push(err);
return Err(());
}
} }
} }
let tuple = VarTuplePattern::new(paren, vars); let tuple = VarTuplePattern::new(paren, vars);
@ -1995,7 +2103,11 @@ impl Parser {
let bound = TypeBoundSpec::non_default(lhs.name.into_token(), spec_with_op); let bound = TypeBoundSpec::non_default(lhs.name.into_token(), spec_with_op);
Ok(bound) Ok(bound)
} }
other => todo!("{other}"), other => {
let err = ParseError::simple_syntax_error(line!() as usize, other.loc());
self.errs.push(err);
Err(())
}
} }
} }
@ -2150,7 +2262,12 @@ impl Parser {
self.level -= 1; self.level -= 1;
Ok(ParamArrayPattern::new(arr.l_sqbr, params, arr.r_sqbr)) Ok(ParamArrayPattern::new(arr.l_sqbr, params, arr.r_sqbr))
} }
_ => todo!(), other => {
self.level -= 1;
let err = ParseError::feature_error(line!() as usize, other.loc(), "?");
self.errs.push(err);
Err(())
}
} }
} }
@ -2368,7 +2485,12 @@ impl Parser {
self.level -= 1; self.level -= 1;
Ok(TypeSpec::Array(array)) Ok(TypeSpec::Array(array))
} }
other => todo!("{other}"), other => {
self.level -= 1;
let err = ParseError::simple_syntax_error(line!() as usize, other.loc());
self.errs.push(err);
Err(())
}
} }
} }
@ -2386,7 +2508,12 @@ impl Parser {
.map_err(|_| self.stack_dec())?; .map_err(|_| self.stack_dec())?;
TypeSpec::type_app(spec, tapp.type_args) TypeSpec::type_app(spec, tapp.type_args)
} }
other => todo!("{other}"), other => {
self.level -= 1;
let err = ParseError::simple_syntax_error(line!() as usize, other.loc());
self.errs.push(err);
return Err(());
}
}; };
self.level -= 1; self.level -= 1;
Ok(t_spec) Ok(t_spec)
@ -2397,9 +2524,66 @@ impl Parser {
todo!() todo!()
} }
fn convert_lambda_to_subr_type_spec(&mut self, _lambda: Lambda) -> ParseResult<SubrTypeSpec> { fn convert_lambda_to_subr_type_spec(
&mut self,
mut lambda: Lambda,
) -> ParseResult<SubrTypeSpec> {
debug_call_info!(self); debug_call_info!(self);
todo!() let bounds = lambda.sig.bounds;
let lparen = lambda.sig.params.parens.map(|(l, _)| l);
let mut non_defaults = vec![];
for param in lambda.sig.params.non_defaults.into_iter() {
let param = match (param.pat, param.t_spec) {
(ParamPattern::VarName(name), Some(t_spec_with_op)) => {
ParamTySpec::new(Some(name.into_token()), t_spec_with_op.t_spec)
}
(ParamPattern::VarName(name), None) => ParamTySpec::anonymous(TypeSpec::PreDeclTy(
PreDeclTypeSpec::Simple(SimpleTypeSpec::new(name, ConstArgs::empty())),
)),
_ => todo!(),
};
non_defaults.push(param);
}
let var_args =
lambda
.sig
.params
.var_args
.map(|var_args| match (var_args.pat, var_args.t_spec) {
(ParamPattern::VarName(name), Some(t_spec_with_op)) => {
ParamTySpec::new(Some(name.into_token()), t_spec_with_op.t_spec)
}
(ParamPattern::VarName(name), None) => {
ParamTySpec::anonymous(TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(
SimpleTypeSpec::new(name, ConstArgs::empty()),
)))
}
_ => todo!(),
});
let mut defaults = vec![];
for param in lambda.sig.params.defaults.into_iter() {
let param = match (param.pat, param.t_spec) {
(ParamPattern::VarName(name), Some(t_spec_with_op)) => {
ParamTySpec::new(Some(name.into_token()), t_spec_with_op.t_spec)
}
(ParamPattern::VarName(name), None) => ParamTySpec::anonymous(TypeSpec::PreDeclTy(
PreDeclTypeSpec::Simple(SimpleTypeSpec::new(name, ConstArgs::empty())),
)),
_ => todo!(),
};
defaults.push(param);
}
let return_t = self.convert_rhs_to_type_spec(lambda.body.remove(0))?;
self.level -= 1;
Ok(SubrTypeSpec::new(
bounds,
lparen,
non_defaults,
var_args,
defaults,
lambda.op,
return_t,
))
} }
fn convert_array_to_array_type_spec(&mut self, _array: Array) -> ParseResult<ArrayTypeSpec> { fn convert_array_to_array_type_spec(&mut self, _array: Array) -> ParseResult<ArrayTypeSpec> {

View file

@ -1,6 +1,6 @@
[package] [package]
name = "erg_type" name = "erg_type"
version = "0.5.1" version = "0.5.5-nightly.1"
description = "APIs for Erg types" description = "APIs for Erg types"
authors = ["erg-lang team <moderation.erglang@gmail.com>"] authors = ["erg-lang team <moderation.erglang@gmail.com>"]
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
@ -18,8 +18,8 @@ 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.1", path = "../erg_common" } erg_common = { version = "0.5.5-nightly.1", path = "../erg_common" }
erg_parser = { version = "0.5.1", path = "../erg_parser" } erg_parser = { version = "0.5.5-nightly.1", path = "../erg_parser" }
[lib] [lib]
path = "lib.rs" path = "lib.rs"

View file

@ -632,6 +632,7 @@ impl<T: Clone + HasLevel> Free<T> {
pub fn unbound_name(&self) -> Option<Str> { pub fn unbound_name(&self) -> Option<Str> {
match &*self.borrow() { match &*self.borrow() {
FreeKind::NamedUnbound { name, .. } => Some(name.clone()), FreeKind::NamedUnbound { name, .. } => Some(name.clone()),
FreeKind::Unbound { id, .. } => Some(Str::from(id.to_string())),
_ => None, _ => None,
} }
} }

View file

@ -1817,6 +1817,7 @@ impl Type {
pub fn tvar_name(&self) -> Option<Str> { pub fn tvar_name(&self) -> Option<Str> {
match self { match self {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().tvar_name(),
Self::FreeVar(fv) => fv.unbound_name(), Self::FreeVar(fv) => fv.unbound_name(),
Self::MonoQVar(name) => Some(name.clone()), Self::MonoQVar(name) => Some(name.clone()),
_ => None, _ => None,

View file

@ -509,6 +509,7 @@ impl TyParam {
pub fn name(&self) -> Option<Str> { pub fn name(&self) -> Option<Str> {
match self { match self {
Self::Type(t) => Some(t.name()), Self::Type(t) => Some(t.name()),
Self::FreeVar(fv) if fv.is_linked() => fv.crack().name(),
Self::Mono(name) => Some(name.clone()), Self::Mono(name) => Some(name.clone()),
Self::MonoQVar(name) => Some(name.clone()), Self::MonoQVar(name) => Some(name.clone()),
_ => None, _ => None,
@ -518,6 +519,7 @@ impl TyParam {
pub fn tvar_name(&self) -> Option<Str> { pub fn tvar_name(&self) -> Option<Str> {
match self { match self {
Self::Type(t) => t.tvar_name(), Self::Type(t) => t.tvar_name(),
Self::FreeVar(fv) if fv.is_linked() => fv.crack().tvar_name(),
Self::FreeVar(fv) => fv.unbound_name(), Self::FreeVar(fv) => fv.unbound_name(),
Self::MonoQVar(name) => Some(name.clone()), Self::MonoQVar(name) => Some(name.clone()),
_ => None, _ => None,

View file

@ -802,8 +802,12 @@ pub mod value_set {
// false -> SyntaxError // false -> SyntaxError
pub fn is_homogeneous(set: &Set<ValueObj>) -> bool { pub fn is_homogeneous(set: &Set<ValueObj>) -> bool {
let l_first = set.iter().next().unwrap().class(); if let Some(first) = set.iter().next() {
set.iter().all(|c| c.class() == l_first) let l_first = first.class();
set.iter().all(|c| c.class() == l_first)
} else {
true
}
} }
pub fn inner_class(set: &Set<ValueObj>) -> Type { pub fn inner_class(set: &Set<ValueObj>) -> Type {

View file

@ -3,11 +3,11 @@
> __Warning__: This document is incomplete. It has not been proofread (style, correct links, mistranslation, etc.). Also, Erg's syntax may be change destructively during version 0.*, and the documentation may not have been updated accordingly. Please be aware of this beforehand. > __Warning__: This document is incomplete. It has not been proofread (style, correct links, mistranslation, etc.). Also, Erg's syntax may be change destructively during version 0.*, and the documentation may not have been updated accordingly. Please be aware of this beforehand.
> If you find any errors in this document, please report then to [here form](https://forms.gle/HtLYRfYzWCAaeTGb6) or [GitHub repo](https://github.com/mtshiba/TheErgBook/issues/new). We would appreciate your suggestions. > If you find any errors in this document, please report then to [here form](https://forms.gle/HtLYRfYzWCAaeTGb6) or [GitHub repo](https://github.com/mtshiba/TheErgBook/issues/new). We would appreciate your suggestions.
> >
> [The Erg Book Japanese edition](https://erg-lang.github.io/the-erg-book/JA/) > [Erg Book 日本語訳](https://erg-lang.github.io/the-erg-book/JA/)
> >
> [The Erg Book simplified Chinese edition](https://erg-lang.github.io/the-erg-book/zh_CN/) > [Erg Book 繁體中文翻譯](https://erg-lang.github.io/the-erg-book/zh_CN/)
> >
> [The Erg Book traditional Chinese edition](https://erg-lang.github.io/the-erg-book/zh_TW/) > [Erg Book 简体中文翻译](https://erg-lang.github.io/the-erg-book/zh_TW/)
This document describes the basic syntax of Erg. The [Standard API](../API/index.md) and [internal documents for Erg contributors](../dev_guide/index.md) are located in another directory. This document describes the basic syntax of Erg. The [Standard API](../API/index.md) and [internal documents for Erg contributors](../dev_guide/index.md) are located in another directory.

View file

@ -22,20 +22,20 @@ print(foo.public)
print(foo.private) # AttributeError: print(foo.private) # AttributeError:
``` ```
## Import from Python ## import from Python
All objects imported from Python are by default of type `Object`. Since no comparisons can be made at this point, it is necessary to refine the type. By default, all objects imported from Python are of type `Object`. Since no comparison is possible with this type, it is necessary to narrow down the type.
## Type Specification in the Standard Library ## Type specification in the standard library
All APIs in the Python standard library are type specified by the Erg development team. All APIs in the Python standard library are type-specified by the Erg development team.
```python ```python
time = pyimport "time" time = pyimport "time"
time.sleep! 1 time.sleep! 1
``` ```
## Type Specification for User Scripts ## Type specification for user scripts
Create a `foo.d.er` file that types the Python `foo` module. Create a `foo.d.er` file that types the Python `foo` module.
Type hints on the Python side are ignored since they are not 100% guaranteed. Type hints on the Python side are ignored since they are not 100% guaranteed.
@ -47,30 +47,34 @@ def bar(x):
... ...
def baz(): def baz():
... ...
class C:
...
... ...
```
```python ````python
# foo.d.er # foo.d.er
foo = pyimport "foo" .X: Int
.X = declare foo.'X', Int .bar!: Int => Int
.bar = declare foo.'bar', Int -> Int .foo! = baz!: () => Int # aliasing
.baz! = declare foo.'baz', () => Int .C!: Class
``` ```
No syntax other than declarations and definitions (aliasing) are allowed in ``d.er``.
Note that all Python functions can only be registered as procedures, and all classes as variable classes.
```python ```python
foo = pyimport "foo" foo = pyimport "foo"
assert foo.bar(1) in Int assert foo.bar!(1) in Int
``` ```
This ensures type safety by performing type checking at runtime. The ``declare`` function works roughly as follows. This ensures type safety by performing type checking at runtime. The checking mechanism generally works as follows.
```python ```python
declare|S: Subroutine| sub!: S, T = decl_proc proc!: Proc, T =
# Actually, => can be cast to a function without block side effects
x => x =>
assert x in T.Input assert x in T.Input
y = sub!(x) y = proc!(x)
assert y in T.Output assert y in T.Output
y y
``` ```

View file

@ -1,6 +1,6 @@
# 基本事項 # 基本事項
[![badge](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fgezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com%2Fdefault%2Fsource_up_to_date%3Fowner%3Derg-lang%26repos%3Derg%26ref%3Dmain%26path%3Ddoc/EN/syntax/00_basic.md%26commit_hash%3D31ccb6924c3051f73458c69ca2c7f2cc5a93a694)](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/syntax/00_basic.md&commit_hash=31ccb6924c3051f73458c69ca2c7f2cc5a93a694) [![badge](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fgezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com%2Fdefault%2Fsource_up_to_date%3Fowner%3Derg-lang%26repos%3Derg%26ref%3Dmain%26path%3Ddoc/EN/syntax/00_basic.md%26commit_hash%3Df1b2fe99d667c75a71a7c69c9b8342c99353ca32)](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/syntax/00_basic.md&commit_hash=f1b2fe99d667c75a71a7c69c9b8342c99353ca32)
> __Warning__: 本ドキュメントは未完成です。校正(文体、正しいリンクが張られているか、など)がなされていません。また、Ergの文法はバージョン0.*の間に破壊的変更が加えられる可能性があり、それに伴うドキュメントの更新が追いついていない可能性があります。予めご了承ください。 > __Warning__: 本ドキュメントは未完成です。校正(文体、正しいリンクが張られているか、など)がなされていません。また、Ergの文法はバージョン0.*の間に破壊的変更が加えられる可能性があり、それに伴うドキュメントの更新が追いついていない可能性があります。予めご了承ください。
> また、本ドキュメントの誤りを見つけた場合は、[こちらのフォーム](https://forms.gle/HtLYRfYzWCAaeTGb6)または[GitHubリポジトリ](https://github.com/mtshiba/TheErgBook/issues/new)から修正の提案をしていただけると幸いです。 > また、本ドキュメントの誤りを見つけた場合は、[こちらのフォーム](https://forms.gle/HtLYRfYzWCAaeTGb6)または[GitHubリポジトリ](https://github.com/mtshiba/TheErgBook/issues/new)から修正の提案をしていただけると幸いです。

View file

@ -1,6 +1,6 @@
# Pythonとの連携 # Pythonとの連携
[![badge](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fgezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com%2Fdefault%2Fsource_up_to_date%3Fowner%3Derg-lang%26repos%3Derg%26ref%3Dmain%26path%3Ddoc/EN/syntax/32_integration_with_Python.md%26commit_hash%3D51de3c9d5a9074241f55c043b9951b384836b258)](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/syntax/32_integration_with_Python.md&commit_hash=51de3c9d5a9074241f55c043b9951b384836b258) [![badge](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fgezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com%2Fdefault%2Fsource_up_to_date%3Fowner%3Derg-lang%26repos%3Derg%26ref%3Dmain%26path%3Ddoc/EN/syntax/32_integration_with_Python.md%26commit_hash%3D0d05a715f8e9d5f70d64fbd5b35b4651eb6aa1d6)](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/syntax/32_integration_with_Python.md&commit_hash=0d05a715f8e9d5f70d64fbd5b35b4651eb6aa1d6)
## Pythonへのexport ## Pythonへのexport
@ -49,29 +49,34 @@ def bar(x):
... ...
def baz(): def baz():
... ...
class C:
...
``` ```
```python ```python
# foo.d.er # foo.d.er
foo = pyimport "foo" .X: Int
.X = declare foo.'X', Int .bar!: Int => Int
.bar = declare foo.'bar', Int -> Int .foo! = baz!: () => Int # aliasing
.baz! = declare foo.'baz', () => Int .C!: Class
``` ```
`d.er`内では宣言と定義(エイリアシング)以外の構文は使えません。
Pythonの関数はすべてプロシージャとして、クラスはすべて可変クラスとしてしか登録できないことに注意してください。
```python ```python
foo = pyimport "foo" foo = pyimport "foo"
assert foo.bar(1) in Int assert foo.bar!(1) in Int
``` ```
これは、実行時に型チェックを行うことで型安全性を担保しています。`declare`関数は概ね以下のように動作します。 これは、実行時に型チェックを行うことで型安全性を担保しています。チェック機構は概ね以下のように動作します。
```python ```python
declare|S: Subroutine| sub!: S, T = decl_proc proc!: Proc, T =
# 実は、=>はブロックの副作用がなければ関数にキャストできる
x => x =>
assert x in T.Input assert x in T.Input
y = sub!(x) y = proc!(x)
assert y in T.Output assert y in T.Output
y y
``` ```

View file

@ -1,6 +1,6 @@
# 基本 # 基本
[![badge](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fgezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com%2Fdefault%2Fsource_up_to_date%3Fowner%3Derg-lang%26repos%3Derg%26ref%3Dmain%26path%3Ddoc/EN/syntax/00_basic.md%26commit_hash%3D31ccb6924c3051f73458c69ca2c7f2cc5a93a694)](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/syntax/00_basic.md&commit_hash=31ccb6924c3051f73458c69ca2c7f2cc5a93a694) [![badge](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fgezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com%2Fdefault%2Fsource_up_to_date%3Fowner%3Derg-lang%26repos%3Derg%26ref%3Dmain%26path%3Ddoc/EN/syntax/00_basic.md%26commit_hash%3Df1b2fe99d667c75a71a7c69c9b8342c99353ca32)](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/syntax/00_basic.md&commit_hash=f1b2fe99d667c75a71a7c69c9b8342c99353ca32)
> __Warning__:本文档不完整。 它未经校对(样式、正确链接、误译等)。 此外Erg 的语法可能在版本 0.* 期间发生破坏性更改,并且文档可能没有相应更新。 请事先了解这一点。 > __Warning__:本文档不完整。 它未经校对(样式、正确链接、误译等)。 此外Erg 的语法可能在版本 0.* 期间发生破坏性更改,并且文档可能没有相应更新。 请事先了解这一点。
> 如果您在本文档中发现任何错误,请报告至 [此处的表单](https://forms.gle/HtLYRfYzWCAaeTGb6) 或 [GitHub repo](https://github.com/mtshiba/TheErgBook/issues/new )。 我们将不胜感激您的建议。 > 如果您在本文档中发现任何错误,请报告至 [此处的表单](https://forms.gle/HtLYRfYzWCAaeTGb6) 或 [GitHub repo](https://github.com/mtshiba/TheErgBook/issues/new )。 我们将不胜感激您的建议。

View file

@ -1,6 +1,6 @@
# 基本 # 基本
[![badge](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fgezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com%2Fdefault%2Fsource_up_to_date%3Fowner%3Derg-lang%26repos%3Derg%26ref%3Dmain%26path%3Ddoc/EN/syntax/00_basic.md%26commit_hash%3D31ccb6924c3051f73458c69ca2c7f2cc5a93a694)](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/syntax/00_basic.md&commit_hash=31ccb6924c3051f73458c69ca2c7f2cc5a93a694) [![badge](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fgezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com%2Fdefault%2Fsource_up_to_date%3Fowner%3Derg-lang%26repos%3Derg%26ref%3Dmain%26path%3Ddoc/EN/syntax/00_basic.md%26commit_hash%3Df1b2fe99d667c75a71a7c69c9b8342c99353ca32)](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/syntax/00_basic.md&commit_hash=f1b2fe99d667c75a71a7c69c9b8342c99353ca32)
> __Warning__:本文檔不完整。 它未經校對(樣式、正確鏈接、誤譯等)。 此外Erg 的語法可能在版本 0.* 期間發生破壞性更改,并且文檔可能沒有相應更新。 請事先了解這一點。 > __Warning__:本文檔不完整。 它未經校對(樣式、正確鏈接、誤譯等)。 此外Erg 的語法可能在版本 0.* 期間發生破壞性更改,并且文檔可能沒有相應更新。 請事先了解這一點。
> 如果您在本文檔中發現任何錯誤,請報告至 [此處的表單](https://forms.gle/HtLYRfYzWCAaeTGb6) 或 [GitHub repo](https://github.com/mtshiba/TheErgBook/issues/new )。 我們將不勝感激您的建議。 > 如果您在本文檔中發現任何錯誤,請報告至 [此處的表單](https://forms.gle/HtLYRfYzWCAaeTGb6) 或 [GitHub repo](https://github.com/mtshiba/TheErgBook/issues/new )。 我們將不勝感激您的建議。

View file

@ -18,7 +18,7 @@ sum = match a:
(i: Int) -> i (i: Int) -> i
_ -> panic "unknown object" _ -> panic "unknown object"
for! 0..1000, i => for! 0..<1000, i =>
print! "i = {i}" print! "i = {i}"
if i >= 100: if i >= 100:
do return break() do return break()

2
examples/declare.d.er Normal file
View file

@ -0,0 +1,2 @@
.x: Int
.f: Int -> Int

2
examples/declare.py Normal file
View file

@ -0,0 +1,2 @@
x = 0
def f(x: int) -> int: return x + 1

3
examples/use_py.er Normal file
View file

@ -0,0 +1,3 @@
declare = pyimport "declare"
print! declare.f(declare.x + 1)