mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-01 05:11:09 +00:00
Merge branch 'erg-lang:main' into fix/md_links
This commit is contained in:
commit
e8d731a652
53 changed files with 1492 additions and 494 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -15,7 +15,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "erg"
|
||||
version = "0.5.1"
|
||||
version = "0.5.5-nightly.1"
|
||||
dependencies = [
|
||||
"erg_common",
|
||||
"erg_compiler",
|
||||
|
@ -25,14 +25,14 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "erg_common"
|
||||
version = "0.5.1"
|
||||
version = "0.5.5-nightly.1"
|
||||
dependencies = [
|
||||
"atty",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "erg_compiler"
|
||||
version = "0.5.1"
|
||||
version = "0.5.5-nightly.1"
|
||||
dependencies = [
|
||||
"erg_common",
|
||||
"erg_parser",
|
||||
|
@ -41,14 +41,14 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "erg_parser"
|
||||
version = "0.5.1"
|
||||
version = "0.5.5-nightly.1"
|
||||
dependencies = [
|
||||
"erg_common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "erg_type"
|
||||
version = "0.5.1"
|
||||
version = "0.5.5-nightly.1"
|
||||
dependencies = [
|
||||
"erg_common",
|
||||
"erg_parser",
|
||||
|
|
12
Cargo.toml
12
Cargo.toml
|
@ -1,8 +1,8 @@
|
|||
[package]
|
||||
name = "erg"
|
||||
version = "0.5.1"
|
||||
version = "0.5.5-nightly.1"
|
||||
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"
|
||||
edition = "2021"
|
||||
repository = "https://github.com/erg-lang/erg"
|
||||
|
@ -46,10 +46,10 @@ traditional_chinese = [
|
|||
]
|
||||
|
||||
[dependencies]
|
||||
erg_common = { version = "0.5.1", path = "./compiler/erg_common" }
|
||||
erg_parser = { version = "0.5.1", path = "./compiler/erg_parser" }
|
||||
erg_compiler = { version = "0.5.1", path = "./compiler/erg_compiler" }
|
||||
erg_type = { version = "0.5.1", path = "./compiler/erg_type" }
|
||||
erg_common = { version = "0.5.5-nightly.1", path = "./compiler/erg_common" }
|
||||
erg_parser = { version = "0.5.5-nightly.1", path = "./compiler/erg_parser" }
|
||||
erg_compiler = { version = "0.5.5-nightly.1", path = "./compiler/erg_compiler" }
|
||||
erg_type = { version = "0.5.5-nightly.1", path = "./compiler/erg_type" }
|
||||
|
||||
# [workspace]
|
||||
# member = ["cm", "dyne"]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "erg_common"
|
||||
version = "0.5.1"
|
||||
version = "0.5.5-nightly.1"
|
||||
description = "A common components library of Erg"
|
||||
authors = ["erg-lang team <moderation.erglang@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
|
|
@ -148,14 +148,6 @@ pub struct ErgConfig {
|
|||
impl Default for ErgConfig {
|
||||
#[inline]
|
||||
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 {
|
||||
mode: "exec",
|
||||
opt_level: 1,
|
||||
|
@ -163,7 +155,7 @@ impl Default for ErgConfig {
|
|||
python_ver: None,
|
||||
py_server_timeout: 10,
|
||||
quiet_startup: false,
|
||||
input,
|
||||
input: Input::REPL,
|
||||
module: "<module>",
|
||||
verbose: 2,
|
||||
ps1: ">>> ",
|
||||
|
@ -173,6 +165,14 @@ impl Default for 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コストは低いので)
|
||||
#[inline]
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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> {
|
||||
fn fmt_all_stderr(&self) {
|
||||
for err in self.iter() {
|
||||
|
|
|
@ -33,3 +33,19 @@ pub fn levenshtein(lhs: &str, rhs: &str) -> usize {
|
|||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "erg_compiler"
|
||||
version = "0.5.1"
|
||||
version = "0.5.5-nightly.1"
|
||||
description = "Centimetre: the Erg compiler"
|
||||
authors = ["erg-lang team <moderation.erglang@gmail.com>"]
|
||||
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" ]
|
||||
|
||||
[dependencies]
|
||||
erg_common = { version = "0.5.1", path = "../erg_common" }
|
||||
erg_parser = { version = "0.5.1", path = "../erg_parser" }
|
||||
erg_type = { version = "0.5.1", path = "../erg_type" }
|
||||
erg_common = { version = "0.5.5-nightly.1", path = "../erg_common" }
|
||||
erg_parser = { version = "0.5.5-nightly.1", path = "../erg_parser" }
|
||||
erg_type = { version = "0.5.5-nightly.1", path = "../erg_type" }
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
|
|
@ -13,7 +13,6 @@ use crate::hir::HIR;
|
|||
use crate::lower::ASTLowerer;
|
||||
use crate::mod_cache::SharedModuleCache;
|
||||
use crate::ownercheck::OwnershipChecker;
|
||||
use crate::reorder::Reorderer;
|
||||
|
||||
/// Summarize lowering, side-effect checking, and ownership checking
|
||||
#[derive(Debug)]
|
||||
|
@ -28,7 +27,12 @@ impl Runnable for HIRBuilder {
|
|||
const NAME: &'static str = "Erg HIR builder";
|
||||
|
||||
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]
|
||||
|
@ -62,9 +66,10 @@ impl HIRBuilder {
|
|||
cfg: ErgConfig,
|
||||
mod_name: S,
|
||||
mod_cache: SharedModuleCache,
|
||||
py_mod_cache: SharedModuleCache,
|
||||
) -> 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(),
|
||||
}
|
||||
}
|
||||
|
@ -99,9 +104,6 @@ impl HIRBuilder {
|
|||
pub fn build(&mut self, src: String, mode: &str) -> Result<HIR, CompileErrors> {
|
||||
let mut ast_builder = ASTBuilder::new(self.cfg().copy());
|
||||
let ast = ast_builder.build(src)?;
|
||||
let ast = Reorderer::new()
|
||||
.reorder(ast)
|
||||
.map_err(|errs| self.convert(errs))?;
|
||||
let hir = self.check(ast, mode)?;
|
||||
Ok(hir)
|
||||
}
|
||||
|
|
|
@ -1619,7 +1619,10 @@ impl CodeGenerator {
|
|||
Expr::Compound(chunks) => {
|
||||
self.emit_frameless_block(chunks, vec![]);
|
||||
}
|
||||
// Dict, Decl
|
||||
Expr::TypeAsc(tasc) => {
|
||||
self.emit_expr(*tasc.expr);
|
||||
}
|
||||
// Dict,
|
||||
other => {
|
||||
self.errs.push(CompileError::feature_error(
|
||||
self.cfg.input.clone(),
|
||||
|
|
|
@ -103,8 +103,14 @@ impl Runnable for Compiler {
|
|||
|
||||
fn new(cfg: ErgConfig) -> Self {
|
||||
let mod_cache = SharedModuleCache::new();
|
||||
let py_mod_cache = SharedModuleCache::new();
|
||||
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()),
|
||||
mod_cache,
|
||||
cfg,
|
||||
|
|
|
@ -606,10 +606,10 @@ impl Context {
|
|||
self.poly_supertype_of(lhs, lparams, rparams)
|
||||
}
|
||||
(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, .. }) => {
|
||||
panic!("Not instantiated type variable: {name}, l: {l}")
|
||||
panic!("internal error: not instantiated type variable: '{name}, l: {l}")
|
||||
}
|
||||
(MonoProj { .. }, _) => todo!(),
|
||||
(_, MonoProj { .. }) => todo!(),
|
||||
|
@ -619,7 +619,11 @@ impl Context {
|
|||
|
||||
pub(crate) fn cyclic_supertype_of(&self, lhs: &FreeTyVar, rhs: &Type) -> bool {
|
||||
// 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) {
|
||||
for (sup_trait, _) in super_traits {
|
||||
if self.sup_conforms(lhs, defined_rhs, sup_trait) {
|
||||
|
@ -846,18 +850,25 @@ impl Context {
|
|||
| (Pred::GreaterEqual { .. }, Pred::LessEqual { .. })
|
||||
| (Pred::NotEqual { .. }, Pred::Equal { .. }) => false,
|
||||
(Pred::Equal { rhs, .. }, Pred::Equal { rhs: rhs2, .. })
|
||||
| (Pred::NotEqual { rhs, .. }, Pred::NotEqual { rhs: rhs2, .. }) => {
|
||||
self.try_cmp(rhs, rhs2).unwrap().is_eq()
|
||||
}
|
||||
| (Pred::NotEqual { rhs, .. }, Pred::NotEqual { rhs: rhs2, .. }) => self
|
||||
.try_cmp(rhs, rhs2)
|
||||
.map(|ord| ord.is_eq())
|
||||
.unwrap_or(false),
|
||||
// {T >= 0} :> {T >= 1}, {T >= 0} :> {T == 1}
|
||||
(
|
||||
Pred::GreaterEqual { rhs, .. },
|
||||
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: 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)) => {
|
||||
self.is_super_pred_of(lhs, l) || self.is_super_pred_of(lhs, r)
|
||||
}
|
||||
|
@ -900,7 +911,7 @@ impl Context {
|
|||
|
||||
#[inline]
|
||||
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を実装しない
|
||||
|
@ -915,7 +926,7 @@ impl Context {
|
|||
if lhs == &refine.var =>
|
||||
{
|
||||
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());
|
||||
}
|
||||
} else {
|
||||
|
@ -943,7 +954,7 @@ impl Context {
|
|||
if lhs == &refine.var =>
|
||||
{
|
||||
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());
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -353,6 +353,7 @@ impl Context {
|
|||
Str::ever("<unnamed record>"),
|
||||
2,
|
||||
self.mod_cache.clone(),
|
||||
self.py_mod_cache.clone(),
|
||||
self.clone(),
|
||||
);
|
||||
for attr in record.attrs.iter() {
|
||||
|
@ -424,6 +425,7 @@ impl Context {
|
|||
Str::ever("<lambda>"),
|
||||
0,
|
||||
self.mod_cache.clone(),
|
||||
self.py_mod_cache.clone(),
|
||||
self.clone(),
|
||||
);
|
||||
let return_t = lambda_ctx.eval_const_block(&lambda.body, None)?;
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::mem;
|
|||
use erg_common::Str;
|
||||
|
||||
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_type::constructors::{and, builtin_mono, mono};
|
||||
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(|| {
|
||||
ErrorCore::new(
|
||||
line!() as usize,
|
||||
ErrorKind::KeyError,
|
||||
ErrorKind::TypeError,
|
||||
Location::Unknown,
|
||||
AtomicStr::from(format!("{RED}Requirement{RESET} is not passed")),
|
||||
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 = impls.map(|v| v.as_type().unwrap());
|
||||
let t = mono(mod_name, __name__.unwrap_or(Str::ever("<Lambda>")));
|
||||
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(
|
||||
mut args: ValueArgs,
|
||||
mod_name: Str,
|
||||
|
@ -46,7 +58,19 @@ pub fn inherit_func(
|
|||
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 = impls.map(|v| v.as_type().unwrap());
|
||||
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(
|
||||
mut args: ValueArgs,
|
||||
mod_name: Str,
|
||||
|
@ -112,14 +136,26 @@ pub fn trait_func(
|
|||
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 = impls.map(|v| v.as_type().unwrap());
|
||||
let t = mono(mod_name, __name__.unwrap_or(Str::ever("<Lambda>")));
|
||||
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(
|
||||
mut args: ValueArgs,
|
||||
mod_name: Str,
|
||||
|
@ -134,7 +170,19 @@ pub fn subsume_func(
|
|||
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 = impls.map(|v| v.as_type().unwrap());
|
||||
let additional = args.remove_left_or_key("Additional");
|
||||
|
|
|
@ -180,10 +180,10 @@ impl Context {
|
|||
// 型境界はすべて各サブルーチンで定義する
|
||||
// push_subtype_boundなどはユーザー定義APIの型境界決定のために使用する
|
||||
fn init_builtin_traits(&mut self) {
|
||||
let unpack = Self::mono_trait("Unpack", None, Self::TOP_LEVEL);
|
||||
let inheritable_type = Self::mono_trait("InheritableType", None, Self::TOP_LEVEL);
|
||||
let named = Self::mono_trait("Named", None, Self::TOP_LEVEL);
|
||||
let mut mutable = Self::mono_trait("Mutable", None, Self::TOP_LEVEL);
|
||||
let unpack = Self::mono_trait("Unpack", None, None, Self::TOP_LEVEL);
|
||||
let inheritable_type = Self::mono_trait("InheritableType", None, None, Self::TOP_LEVEL);
|
||||
let named = Self::mono_trait("Named", None, 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 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);
|
||||
|
@ -193,16 +193,22 @@ impl Context {
|
|||
);
|
||||
mutable.register_builtin_decl("update!", t, Public);
|
||||
// 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_builtin_decl("ImmutType", Type, Public);
|
||||
// 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);
|
||||
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 input = Self::poly_trait("Input", params.clone(), None, Self::TOP_LEVEL);
|
||||
let output = Self::poly_trait("Output", params, 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, None, Self::TOP_LEVEL);
|
||||
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 = quant(
|
||||
|
@ -213,7 +219,13 @@ impl Context {
|
|||
// Erg does not have a trait equivalent to `PartialEq` in Rust
|
||||
// This means, Erg's `Float` cannot be compared with other `Float`
|
||||
// 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__: |Self <: Eq()| Self.(Self) -> Bool
|
||||
let op_t = fn1_met(mono_q("Self"), mono_q("R"), Bool);
|
||||
|
@ -229,6 +241,7 @@ impl Context {
|
|||
"PartialOrd",
|
||||
vec![PS::t("R", WithDefault)],
|
||||
None,
|
||||
None,
|
||||
Self::TOP_LEVEL,
|
||||
);
|
||||
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);
|
||||
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("PartialOrd", vec![ty_tp(builtin_mono("Self"))]),
|
||||
&partial_ord,
|
||||
);
|
||||
// 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![
|
||||
poly("Add", vec![]),
|
||||
poly("Sub", 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);
|
||||
let self_t = mono_q("Self");
|
||||
let t = fn0_met(self_t.clone(), Nat);
|
||||
|
@ -278,7 +297,7 @@ impl Context {
|
|||
let r_bound = static_instance("R", Type);
|
||||
let params = vec![PS::t("R", WithDefault)];
|
||||
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__の型とは関係ない)
|
||||
add.register_superclass(poly("Output", vec![ty_tp(mono_q("R"))]), &output);
|
||||
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});
|
||||
add.register_builtin_decl("__add__", op_t, 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);
|
||||
let op_t = fn1_met(
|
||||
mono_q("Self"),
|
||||
|
@ -301,7 +320,7 @@ impl Context {
|
|||
let op_t = quant(op_t, set! {r_bound.clone(), self_bound});
|
||||
sub.register_builtin_decl("__sub__", op_t, 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);
|
||||
let op_t = fn1_met(
|
||||
mono_q("Self"),
|
||||
|
@ -312,7 +331,7 @@ impl Context {
|
|||
let op_t = quant(op_t, set! {r_bound.clone(), self_bound});
|
||||
mul.register_builtin_decl("__mul__", op_t, 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);
|
||||
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()));
|
||||
|
@ -368,7 +387,7 @@ impl Context {
|
|||
}
|
||||
|
||||
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 = quant(t, set! {subtypeof(mono_q("Self"), builtin_mono("Obj"))});
|
||||
obj.register_builtin_impl("clone", t, Const, Public);
|
||||
|
@ -383,13 +402,13 @@ impl Context {
|
|||
Immutable,
|
||||
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.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.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);
|
||||
// TODO: support multi platform
|
||||
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_marker_trait(builtin_mono("Num"));
|
||||
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(
|
||||
"__cmp__",
|
||||
fn1_met(Float, Float, builtin_mono("Ordering")),
|
||||
|
@ -411,36 +430,36 @@ impl Context {
|
|||
);
|
||||
// Float doesn't have an `Eq` implementation
|
||||
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_const("Output", ValueObj::builtin_t(Float));
|
||||
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_const("Output", ValueObj::builtin_t(Float));
|
||||
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_const("Output", 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);
|
||||
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_const("Output", 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);
|
||||
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
|
||||
.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Float!")));
|
||||
float.register_trait(Float, builtin_mono("Mutizable"), float_mutizable);
|
||||
// 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_builtin_impl("Real", Ratio, Const, Public);
|
||||
ratio.register_builtin_impl("Imag", Ratio, Const, Public);
|
||||
ratio.register_marker_trait(builtin_mono("Num"));
|
||||
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(
|
||||
"__cmp__",
|
||||
fn1_met(Ratio, Ratio, builtin_mono("Ordering")),
|
||||
|
@ -452,33 +471,33 @@ impl Context {
|
|||
poly("PartialOrd", vec![ty_tp(Ratio)]),
|
||||
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.register_trait(Ratio, poly("Eq", vec![ty_tp(Ratio)]), ratio_eq);
|
||||
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_const("Output", ValueObj::builtin_t(Ratio));
|
||||
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_const("Output", ValueObj::builtin_t(Ratio));
|
||||
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_const("Output", 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);
|
||||
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_const("Output", 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);
|
||||
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
|
||||
.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Ratio!")));
|
||||
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(Obj, &obj);
|
||||
int.register_marker_trait(builtin_mono("Num"));
|
||||
|
@ -487,7 +506,7 @@ impl Context {
|
|||
// class("Rational"),
|
||||
// class("Integral"),
|
||||
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(
|
||||
"__partial_cmp__",
|
||||
fn1_met(Int, Int, option(builtin_mono("Ordering"))),
|
||||
|
@ -495,30 +514,30 @@ impl Context {
|
|||
Public,
|
||||
);
|
||||
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.register_trait(Int, poly("Eq", vec![ty_tp(Int)]), int_eq);
|
||||
// __div__ is not included in Int (cast to Ratio)
|
||||
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_const("Output", ValueObj::builtin_t(Int));
|
||||
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_const("Output", ValueObj::builtin_t(Int));
|
||||
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_const("Output", ValueObj::builtin_t(Int));
|
||||
int_mul.register_builtin_const("PowOutput", ValueObj::builtin_t(Nat));
|
||||
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.register_trait(Int, builtin_mono("Mutizable"), int_mutizable);
|
||||
int.register_builtin_impl("Real", 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(Float, &float); // TODO: Float -> Ratio
|
||||
nat.register_superclass(Obj, &obj);
|
||||
|
@ -538,10 +557,10 @@ impl Context {
|
|||
);
|
||||
nat.register_marker_trait(builtin_mono("Num"));
|
||||
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.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(
|
||||
"__cmp__",
|
||||
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);
|
||||
// __sub__, __div__ is not included in Nat (cast to Int/ Ratio)
|
||||
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_const("Output", ValueObj::builtin_t(Nat));
|
||||
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_const("Output", ValueObj::builtin_t(Nat));
|
||||
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.register_trait(Nat, builtin_mono("Mutizable"), nat_mutizable);
|
||||
nat.register_builtin_impl("Real", 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(Int, &int);
|
||||
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_marker_trait(builtin_mono("Num"));
|
||||
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(
|
||||
"__cmp__",
|
||||
fn1_met(Bool, Bool, builtin_mono("Ordering")),
|
||||
|
@ -588,18 +607,18 @@ impl Context {
|
|||
poly("PartialOrd", vec![ty_tp(Bool)]),
|
||||
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_.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_const("Output", ValueObj::builtin_t(Nat));
|
||||
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
|
||||
.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Bool!")));
|
||||
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_marker_trait(builtin_mono("Ord"));
|
||||
str_.register_builtin_impl(
|
||||
|
@ -626,48 +645,49 @@ impl Context {
|
|||
Immutable,
|
||||
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_.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("get", fn1_met(Str, Nat, Str), Const, Public);
|
||||
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_const("Output", ValueObj::builtin_t(Str));
|
||||
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_const("Output", ValueObj::builtin_t(Str));
|
||||
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_.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_builtin_impl("mro", array(Type, TyParam::erased(Nat)), Immutable, Public);
|
||||
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_.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(Obj, &obj);
|
||||
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_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_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.register_trait(Module, poly("Eq", vec![ty_tp(Module)]), module_eq);
|
||||
let mut array_ = Self::poly_class(
|
||||
"Array",
|
||||
vec![PS::t_nd("T"), PS::named_nd("N", Nat)],
|
||||
None,
|
||||
None,
|
||||
Self::TOP_LEVEL,
|
||||
);
|
||||
array_.register_superclass(Obj, &obj);
|
||||
|
@ -693,7 +713,7 @@ impl Context {
|
|||
));
|
||||
// [T; N].MutType! = [T; !N] (neither [T!; N] nor [T; N]!)
|
||||
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(
|
||||
"__eq__",
|
||||
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(poly("Seq", vec![ty_tp(mono_q("T"))]));
|
||||
// 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);
|
||||
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(
|
||||
"__eq__",
|
||||
fn1_met(builtin_mono("Tuple"), builtin_mono("Tuple"), Bool),
|
||||
|
@ -718,10 +738,11 @@ impl Context {
|
|||
poly("Eq", vec![ty_tp(builtin_mono("Tuple"))]),
|
||||
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(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(
|
||||
"__eq__",
|
||||
fn1_met(
|
||||
|
@ -741,11 +762,12 @@ impl Context {
|
|||
"Tuple2",
|
||||
vec![PS::t_nd("A"), PS::t_nd("B")],
|
||||
None,
|
||||
None,
|
||||
Self::TOP_LEVEL,
|
||||
);
|
||||
tuple2.register_superclass(builtin_mono("Tuple"), &tuple_);
|
||||
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(
|
||||
"__eq__",
|
||||
fn1_met(
|
||||
|
@ -771,11 +793,12 @@ impl Context {
|
|||
"Tuple3",
|
||||
vec![PS::t_nd("A"), PS::t_nd("B"), PS::t_nd("C")],
|
||||
None,
|
||||
None,
|
||||
Self::TOP_LEVEL,
|
||||
);
|
||||
tuple3.register_superclass(builtin_mono("Tuple"), &tuple_);
|
||||
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(
|
||||
"__eq__",
|
||||
fn1_met(
|
||||
|
@ -810,11 +833,12 @@ impl Context {
|
|||
"Tuple4",
|
||||
vec![PS::t_nd("A"), PS::t_nd("B"), PS::t_nd("C"), PS::t_nd("D")],
|
||||
None,
|
||||
None,
|
||||
Self::TOP_LEVEL,
|
||||
);
|
||||
tuple4.register_superclass(builtin_mono("Tuple"), &tuple_);
|
||||
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(
|
||||
"__eq__",
|
||||
fn1_met(
|
||||
|
@ -875,11 +899,12 @@ impl Context {
|
|||
PS::t_nd("E"),
|
||||
],
|
||||
None,
|
||||
None,
|
||||
Self::TOP_LEVEL,
|
||||
);
|
||||
tuple5.register_superclass(builtin_mono("Tuple"), &tuple_);
|
||||
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(
|
||||
"__eq__",
|
||||
fn1_met(
|
||||
|
@ -945,11 +970,12 @@ impl Context {
|
|||
PS::t_nd("F"),
|
||||
],
|
||||
None,
|
||||
None,
|
||||
Self::TOP_LEVEL,
|
||||
);
|
||||
tuple6.register_superclass(builtin_mono("Tuple"), &tuple_);
|
||||
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(
|
||||
"__eq__",
|
||||
fn1_met(
|
||||
|
@ -1020,11 +1046,12 @@ impl Context {
|
|||
PS::t_nd("G"),
|
||||
],
|
||||
None,
|
||||
None,
|
||||
Self::TOP_LEVEL,
|
||||
);
|
||||
tuple7.register_superclass(builtin_mono("Tuple"), &tuple_);
|
||||
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(
|
||||
"__eq__",
|
||||
fn1_met(
|
||||
|
@ -1100,11 +1127,12 @@ impl Context {
|
|||
PS::t_nd("H"),
|
||||
],
|
||||
None,
|
||||
None,
|
||||
Self::TOP_LEVEL,
|
||||
);
|
||||
tuple8.register_superclass(builtin_mono("Tuple"), &tuple_);
|
||||
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(
|
||||
"__eq__",
|
||||
fn1_met(
|
||||
|
@ -1171,16 +1199,16 @@ impl Context {
|
|||
),
|
||||
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);
|
||||
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("Type"), &type_);
|
||||
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(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));
|
||||
let f_t = param_t("f", func(vec![param_t("old", Float)], None, vec![], Float));
|
||||
let t = pr_met(
|
||||
|
@ -1196,10 +1224,10 @@ impl Context {
|
|||
builtin_mono("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(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));
|
||||
let f_t = param_t(
|
||||
"f",
|
||||
|
@ -1223,11 +1251,11 @@ impl Context {
|
|||
builtin_mono("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(builtin_mono("Float!"), &float_mut);
|
||||
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));
|
||||
let f_t = param_t("f", func(vec![param_t("old", Int)], None, vec![], Int));
|
||||
let t = pr_met(
|
||||
|
@ -1243,12 +1271,12 @@ impl Context {
|
|||
builtin_mono("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(builtin_mono("Int!"), &int_mut);
|
||||
nat_mut.register_superclass(builtin_mono("Float!"), &float_mut);
|
||||
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));
|
||||
let f_t = param_t("f", func(vec![param_t("old", Nat)], None, vec![], Nat));
|
||||
let t = pr_met(
|
||||
|
@ -1264,13 +1292,13 @@ impl Context {
|
|||
builtin_mono("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(builtin_mono("Nat!"), &nat_mut);
|
||||
bool_mut.register_superclass(builtin_mono("Int!"), &int_mut);
|
||||
bool_mut.register_superclass(builtin_mono("Float!"), &float_mut);
|
||||
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));
|
||||
let f_t = param_t("f", func(vec![param_t("old", Bool)], None, vec![], Bool));
|
||||
let t = pr_met(
|
||||
|
@ -1286,10 +1314,10 @@ impl Context {
|
|||
builtin_mono("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(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));
|
||||
let f_t = param_t("f", func(vec![param_t("old", Str)], None, vec![], Str));
|
||||
let t = pr_met(
|
||||
|
@ -1311,6 +1339,7 @@ impl Context {
|
|||
"Array!",
|
||||
vec![PS::t_nd("T"), PS::named_nd("N", builtin_mono("Nat!"))],
|
||||
None,
|
||||
None,
|
||||
Self::TOP_LEVEL,
|
||||
);
|
||||
array_mut_.register_superclass(array_t.clone(), &array_);
|
||||
|
@ -1364,7 +1393,7 @@ impl Context {
|
|||
vec![],
|
||||
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_.register_trait(
|
||||
array_mut_t.clone(),
|
||||
|
@ -1372,10 +1401,10 @@ impl Context {
|
|||
array_mut_mutable,
|
||||
);
|
||||
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_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(
|
||||
"__eq__",
|
||||
fn1_met(range_t.clone(), range_t.clone(), Bool),
|
||||
|
@ -1387,16 +1416,16 @@ impl Context {
|
|||
poly("Eq", vec![ty_tp(range_t.clone())]),
|
||||
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);
|
||||
// TODO: lambda
|
||||
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(Obj, &obj);
|
||||
// TODO: lambda
|
||||
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(Obj, &obj);
|
||||
self.register_builtin_type(Obj, obj, Const);
|
||||
|
@ -1780,6 +1809,7 @@ impl Context {
|
|||
params,
|
||||
// super: vec![Type::from(&m..=&n)],
|
||||
None,
|
||||
None,
|
||||
Self::TOP_LEVEL,
|
||||
);
|
||||
let op_t = fn1_met(
|
||||
|
@ -1787,7 +1817,7 @@ impl Context {
|
|||
Type::from(&o..=&p),
|
||||
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_const(
|
||||
"Output",
|
||||
|
@ -1798,7 +1828,7 @@ impl Context {
|
|||
poly("Add", vec![TyParam::from(&o..=&p)]),
|
||||
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(
|
||||
Type::from(&m..=&n),
|
||||
Type::from(&o..=&p),
|
||||
|
@ -1823,7 +1853,7 @@ impl Context {
|
|||
|
||||
pub(crate) fn init_builtins(mod_cache: &SharedModuleCache) {
|
||||
// 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_const_funcs();
|
||||
ctx.init_builtin_procs();
|
||||
|
@ -1834,13 +1864,18 @@ impl Context {
|
|||
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(
|
||||
name.into(),
|
||||
ContextKind::Module,
|
||||
vec![],
|
||||
None,
|
||||
Some(mod_cache),
|
||||
Some(py_mod_cache),
|
||||
Context::TOP_LEVEL,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ use Visibility::*;
|
|||
|
||||
impl Context {
|
||||
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
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@ use Visibility::*;
|
|||
|
||||
impl Context {
|
||||
pub(crate) fn init_py_io_mod() -> Self {
|
||||
let mut io = Context::module("io".into(), None, 15);
|
||||
let mut string_io = Context::mono_class(Str::ever("StringIO!"), None, 0);
|
||||
let mut io = Context::module("io".into(), None, None, 15);
|
||||
let mut string_io = Context::mono_class(Str::ever("StringIO!"), None, None, 0);
|
||||
// FIXME: include Obj (pass main_ctx as a param)
|
||||
// string_io.register_superclass(Obj, obj);
|
||||
string_io.register_builtin_impl(
|
||||
|
|
|
@ -11,7 +11,7 @@ use Visibility::*;
|
|||
|
||||
impl Context {
|
||||
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("tau", Float, Immutable, Public);
|
||||
math.register_builtin_impl("e", Float, Immutable, Public);
|
||||
|
|
|
@ -14,7 +14,7 @@ use Visibility::*;
|
|||
|
||||
impl Context {
|
||||
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(
|
||||
"seed!",
|
||||
proc(
|
||||
|
|
|
@ -12,8 +12,8 @@ use Visibility::*;
|
|||
|
||||
impl Context {
|
||||
pub(crate) fn init_py_socket_mod() -> Self {
|
||||
let mut socket = Context::module("socket".into(), None, 15);
|
||||
let mut sock = Context::mono_class(Str::ever("Socket!"), None, 0);
|
||||
let mut socket = Context::module("socket".into(), None, None, 15);
|
||||
let mut sock = Context::mono_class(Str::ever("Socket!"), None, None, 0);
|
||||
// FIXME: include Obj (pass main_ctx as a param)
|
||||
// sock.register_superclass(Obj, obj);
|
||||
sock.register_builtin_impl(
|
||||
|
|
|
@ -12,7 +12,7 @@ use Visibility::*;
|
|||
|
||||
impl Context {
|
||||
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("byteorder", Str, Immutable, Public);
|
||||
sys.register_builtin_impl(
|
||||
|
|
|
@ -11,7 +11,7 @@ use Visibility::*;
|
|||
|
||||
impl Context {
|
||||
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("time!", proc0(Float), Immutable, Public);
|
||||
time
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
use std::option::Option; // conflicting to Type::Option
|
||||
|
||||
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::traits::Locational;
|
||||
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);
|
||||
if name.len() <= 1 {
|
||||
return None;
|
||||
}
|
||||
// TODO: add `.decls`
|
||||
let most_similar_name = self
|
||||
.params
|
||||
.iter()
|
||||
.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)
|
||||
}
|
||||
// TODO: add decls
|
||||
get_similar_name(
|
||||
self.params
|
||||
.iter()
|
||||
.filter_map(|(opt_name, _)| opt_name.as_ref().map(|n| &n.inspect()[..]))
|
||||
.chain(self.locals.keys().map(|name| &name.inspect()[..])),
|
||||
name,
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn get_similar_attr_from_singular<'a>(
|
||||
&'a self,
|
||||
obj: &hir::Expr,
|
||||
name: &str,
|
||||
) -> Option<&'a Str> {
|
||||
) -> Option<&'a str> {
|
||||
if let Ok(ctx) = self.get_singular_ctx(obj, &self.name) {
|
||||
if let Some(name) = ctx.get_similar_name(name) {
|
||||
return Some(name);
|
||||
|
@ -932,7 +922,7 @@ impl Context {
|
|||
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)? {
|
||||
if let Some(name) = ctx.get_similar_name(name) {
|
||||
return Some(name);
|
||||
|
@ -1148,12 +1138,16 @@ impl Context {
|
|||
.rec_get_mono_type("Record");
|
||||
}
|
||||
Type::Mono { path, name } => {
|
||||
if let Some(ctx) = self.mod_cache.as_ref().unwrap().ref_ctx(path) {
|
||||
if let Some((t, ctx)) = ctx.rec_get_mono_type(name) {
|
||||
if self.mod_name() == path {
|
||||
if let Some((t, ctx)) = self.rec_get_mono_type(name) {
|
||||
return Some((t, ctx));
|
||||
}
|
||||
} else if self.mod_name() == path {
|
||||
if let Some((t, ctx)) = self.rec_get_mono_type(name) {
|
||||
} else if let Some(ctx) = self
|
||||
.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));
|
||||
}
|
||||
}
|
||||
|
@ -1265,6 +1259,11 @@ impl Context {
|
|||
self.mod_cache
|
||||
.as_ref()
|
||||
.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とは違い、位置情報を持たないしエラーとならない
|
||||
|
@ -1423,14 +1422,12 @@ impl Context {
|
|||
let insts = self.rec_get_trait_impls(&sup.name());
|
||||
let candidates = insts.into_iter().filter_map(move |inst| {
|
||||
if self.supertype_of(&inst.sup_trait, &sup) {
|
||||
Some(
|
||||
self.eval_t_params(
|
||||
mono_proj(inst.sub_type, rhs),
|
||||
self.level,
|
||||
Location::Unknown,
|
||||
)
|
||||
.unwrap(),
|
||||
self.eval_t_params(
|
||||
mono_proj(inst.sub_type, rhs),
|
||||
self.level,
|
||||
Location::Unknown,
|
||||
)
|
||||
.ok()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
|
@ -113,15 +113,7 @@ impl TyVarContext {
|
|||
if defined_params_len < given_params_len {
|
||||
panic!()
|
||||
}
|
||||
let inst_non_defaults = 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 inst_non_defaults = self.instantiate_params(params);
|
||||
let mut inst_defaults = vec![];
|
||||
for template in temp_defaults
|
||||
.iter()
|
||||
|
@ -133,41 +125,45 @@ impl TyVarContext {
|
|||
}
|
||||
poly(name, [inst_non_defaults, inst_defaults].concat())
|
||||
} else {
|
||||
poly(
|
||||
name,
|
||||
params
|
||||
.into_iter()
|
||||
.map(|p| {
|
||||
if let Some(name) = p.tvar_name() {
|
||||
let tp = self.instantiate_qtp(p);
|
||||
self.push_or_init_typaram(&name, &tp);
|
||||
tp
|
||||
} else {
|
||||
p
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
poly(name, self.instantiate_params(params))
|
||||
}
|
||||
}
|
||||
|
||||
fn instantiate_params(&mut self, params: Vec<TyParam>) -> Vec<TyParam> {
|
||||
params
|
||||
.into_iter()
|
||||
.map(|p| {
|
||||
if let Some(name) = p.tvar_name() {
|
||||
let tp = self.instantiate_qtp(p);
|
||||
self.push_or_init_typaram(&name, &tp);
|
||||
tp
|
||||
} else {
|
||||
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) {
|
||||
match bound {
|
||||
TyBound::Sandwiched { sub, mid, sup } => {
|
||||
let sub_instance = match sub {
|
||||
Type::Poly { name, params } => {
|
||||
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 sub_instance = self.instantiate_bound_type(&mid, sub, ctx);
|
||||
let sup_instance = self.instantiate_bound_type(&mid, sup, ctx);
|
||||
let name = mid.name();
|
||||
let constraint =
|
||||
Constraint::new_sandwiched(sub_instance, sup_instance, Cyclicity::Not);
|
||||
|
@ -247,7 +243,7 @@ impl TyVarContext {
|
|||
}
|
||||
}
|
||||
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) {
|
||||
t.clone()
|
||||
} else if let Some(t) = self.get_tyvar(&n) {
|
||||
|
@ -258,7 +254,7 @@ impl TyVarContext {
|
|||
TyParam::t(tv)
|
||||
}
|
||||
} else {
|
||||
todo!("{t}")
|
||||
unreachable!("{t}")
|
||||
}
|
||||
}
|
||||
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)]
|
||||
pub enum ConstTemplate {
|
||||
Obj(ValueObj),
|
||||
|
@ -393,22 +390,16 @@ impl Context {
|
|||
.map(|t| enum_unwrap!(t, Type::Subr));
|
||||
let bounds = self.instantiate_ty_bounds(&sig.bounds, PreRegister)?;
|
||||
let mut tv_ctx = TyVarContext::new(self.level, bounds, self);
|
||||
let non_defaults = sig
|
||||
.params
|
||||
.non_defaults
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(n, p)| {
|
||||
let opt_decl_t = opt_decl_sig_t
|
||||
.as_ref()
|
||||
.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 mut non_defaults = vec![];
|
||||
for (n, p) in sig.params.non_defaults.iter().enumerate() {
|
||||
let opt_decl_t = opt_decl_sig_t
|
||||
.as_ref()
|
||||
.and_then(|subr| subr.non_default_params.get(n));
|
||||
non_defaults.push(ParamTy::pos(
|
||||
p.inspect().cloned(),
|
||||
self.instantiate_param_sig_t(p, opt_decl_t, &mut Some(&mut tv_ctx), mode)?,
|
||||
));
|
||||
}
|
||||
let var_args = if let Some(var_args) = sig.params.var_args.as_ref() {
|
||||
let opt_decl_t = opt_decl_sig_t
|
||||
.as_ref()
|
||||
|
@ -419,22 +410,16 @@ impl Context {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
let defaults = sig
|
||||
.params
|
||||
.defaults
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(n, p)| {
|
||||
let opt_decl_t = opt_decl_sig_t
|
||||
.as_ref()
|
||||
.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 mut defaults = vec![];
|
||||
for (n, p) in sig.params.defaults.iter().enumerate() {
|
||||
let opt_decl_t = opt_decl_sig_t
|
||||
.as_ref()
|
||||
.and_then(|subr| subr.default_params.get(n));
|
||||
defaults.push(ParamTy::kw(
|
||||
p.inspect().unwrap().clone(),
|
||||
self.instantiate_param_sig_t(p, opt_decl_t, &mut Some(&mut tv_ctx), mode)?,
|
||||
));
|
||||
}
|
||||
let spec_return_t = if let Some(s) = sig.return_t_spec.as_ref() {
|
||||
let opt_decl_t = opt_decl_sig_t
|
||||
.as_ref()
|
||||
|
@ -544,8 +529,8 @@ impl Context {
|
|||
Ok(decl_t.typ().clone())
|
||||
} else {
|
||||
let typ = mono(self.mod_name(), Str::rc(other));
|
||||
if self.get_nominal_type_ctx(&typ).is_some() {
|
||||
Ok(typ)
|
||||
if let Some((defined_t, _)) = self.get_nominal_type_ctx(&typ) {
|
||||
Ok(defined_t.clone())
|
||||
} else {
|
||||
Err(TyCheckError::no_var_error(
|
||||
line!() as usize,
|
||||
|
@ -770,6 +755,9 @@ impl Context {
|
|||
let t = Self::instantiate_t(*t, tv_ctx, loc)?;
|
||||
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),
|
||||
other => todo!("{other}"),
|
||||
}
|
||||
|
@ -871,6 +859,15 @@ impl Context {
|
|||
Quantified(_) => {
|
||||
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 => todo!("{other}"),
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ use std::option::Option; // conflicting to Type::Option
|
|||
|
||||
use erg_common::astr::AtomicStr;
|
||||
use erg_common::dict::Dict;
|
||||
use erg_common::error::Location;
|
||||
use erg_common::impl_display_from_debug;
|
||||
use erg_common::traits::{Locational, Stream};
|
||||
use erg_common::vis::Visibility;
|
||||
|
@ -238,7 +239,7 @@ impl From<DefKind> for ContextKind {
|
|||
DefKind::Class | DefKind::Inherit => Self::Class,
|
||||
DefKind::Trait | DefKind::Subsume => Self::Trait,
|
||||
DefKind::StructuralTrait => Self::StructuralTrait,
|
||||
DefKind::Module => Self::Module,
|
||||
DefKind::ErgImport | DefKind::PyImport => Self::Module,
|
||||
DefKind::Other => Self::Instant,
|
||||
}
|
||||
}
|
||||
|
@ -271,6 +272,21 @@ pub enum RegistrationMode {
|
|||
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
|
||||
///
|
||||
/// 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
|
||||
pub(crate) patches: Dict<VarName, Context>,
|
||||
pub(crate) mod_cache: Option<SharedModuleCache>,
|
||||
pub(crate) py_mod_cache: Option<SharedModuleCache>,
|
||||
pub(crate) level: usize,
|
||||
}
|
||||
|
||||
|
@ -337,6 +354,7 @@ impl Default for Context {
|
|||
vec![],
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Self::TOP_LEVEL,
|
||||
)
|
||||
}
|
||||
|
@ -368,9 +386,10 @@ impl Context {
|
|||
params: Vec<ParamSpec>,
|
||||
outer: Option<Context>,
|
||||
mod_cache: Option<SharedModuleCache>,
|
||||
py_mod_cache: Option<SharedModuleCache>,
|
||||
level: usize,
|
||||
) -> 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)]
|
||||
|
@ -381,6 +400,7 @@ impl Context {
|
|||
outer: Option<Context>,
|
||||
capacity: usize,
|
||||
mod_cache: Option<SharedModuleCache>,
|
||||
py_mod_cache: Option<SharedModuleCache>,
|
||||
level: usize,
|
||||
) -> Self {
|
||||
let mut params_ = Vec::new();
|
||||
|
@ -419,6 +439,7 @@ impl Context {
|
|||
mono_types: Dict::default(),
|
||||
poly_types: Dict::default(),
|
||||
mod_cache,
|
||||
py_mod_cache,
|
||||
patches: Dict::default(),
|
||||
level,
|
||||
}
|
||||
|
@ -430,9 +451,10 @@ impl Context {
|
|||
kind: ContextKind,
|
||||
outer: Option<Context>,
|
||||
mod_cache: Option<SharedModuleCache>,
|
||||
py_mod_cache: Option<SharedModuleCache>,
|
||||
level: usize,
|
||||
) -> 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]
|
||||
|
@ -442,53 +464,75 @@ impl Context {
|
|||
params: Vec<ParamSpec>,
|
||||
outer: Option<Context>,
|
||||
mod_cache: Option<SharedModuleCache>,
|
||||
py_mod_cache: Option<SharedModuleCache>,
|
||||
level: usize,
|
||||
) -> 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>>(
|
||||
name: S,
|
||||
params: Vec<ParamSpec>,
|
||||
mod_cache: Option<SharedModuleCache>,
|
||||
py_mod_cache: Option<SharedModuleCache>,
|
||||
level: usize,
|
||||
) -> Self {
|
||||
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>>(
|
||||
name: S,
|
||||
params: Vec<ParamSpec>,
|
||||
mod_cache: Option<SharedModuleCache>,
|
||||
py_mod_cache: Option<SharedModuleCache>,
|
||||
level: usize,
|
||||
) -> Self {
|
||||
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]
|
||||
pub fn mono_trait<S: Into<Str>>(
|
||||
name: S,
|
||||
mod_cache: Option<SharedModuleCache>,
|
||||
py_mod_cache: Option<SharedModuleCache>,
|
||||
level: usize,
|
||||
) -> Self {
|
||||
Self::poly_trait(name, vec![], mod_cache, level)
|
||||
Self::poly_trait(name, vec![], mod_cache, py_mod_cache, level)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn mono_class<S: Into<Str>>(
|
||||
name: S,
|
||||
mod_cache: Option<SharedModuleCache>,
|
||||
py_mod_cache: Option<SharedModuleCache>,
|
||||
level: usize,
|
||||
) -> Self {
|
||||
Self::poly_class(name, vec![], mod_cache, level)
|
||||
Self::poly_class(name, vec![], mod_cache, py_mod_cache, level)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn methods<S: Into<Str>>(
|
||||
name: S,
|
||||
mod_cache: Option<SharedModuleCache>,
|
||||
py_mod_cache: Option<SharedModuleCache>,
|
||||
level: usize,
|
||||
) -> Self {
|
||||
Self::with_capacity(
|
||||
|
@ -498,6 +542,7 @@ impl Context {
|
|||
None,
|
||||
2,
|
||||
mod_cache,
|
||||
py_mod_cache,
|
||||
level,
|
||||
)
|
||||
}
|
||||
|
@ -507,6 +552,7 @@ impl Context {
|
|||
name: S,
|
||||
params: Vec<ParamSpec>,
|
||||
mod_cache: Option<SharedModuleCache>,
|
||||
py_mod_cache: Option<SharedModuleCache>,
|
||||
level: usize,
|
||||
) -> Self {
|
||||
Self::poly(
|
||||
|
@ -515,12 +561,18 @@ impl Context {
|
|||
params,
|
||||
None,
|
||||
mod_cache,
|
||||
py_mod_cache,
|
||||
level,
|
||||
)
|
||||
}
|
||||
|
||||
#[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(
|
||||
name,
|
||||
ContextKind::Module,
|
||||
|
@ -528,6 +580,7 @@ impl Context {
|
|||
None,
|
||||
capacity,
|
||||
mod_cache,
|
||||
py_mod_cache,
|
||||
Self::TOP_LEVEL,
|
||||
)
|
||||
}
|
||||
|
@ -537,6 +590,7 @@ impl Context {
|
|||
name: Str,
|
||||
capacity: usize,
|
||||
mod_cache: Option<SharedModuleCache>,
|
||||
py_mod_cache: Option<SharedModuleCache>,
|
||||
outer: Context,
|
||||
) -> Self {
|
||||
Self::with_capacity(
|
||||
|
@ -546,6 +600,7 @@ impl Context {
|
|||
Some(outer),
|
||||
capacity,
|
||||
mod_cache,
|
||||
py_mod_cache,
|
||||
Self::TOP_LEVEL,
|
||||
)
|
||||
}
|
||||
|
@ -596,6 +651,7 @@ impl Context {
|
|||
log!(info "{}: current namespace: {name}", fn_name!());
|
||||
self.outer = Some(Box::new(mem::take(self)));
|
||||
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.kind = kind;
|
||||
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),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::path::PathBuf; // conflicting to Type::Option
|
|||
|
||||
use erg_common::config::{ErgConfig, Input};
|
||||
use erg_common::error::MultiErrorDisplay;
|
||||
use erg_common::levenshtein::get_similar_name;
|
||||
use erg_common::traits::{Locational, Stream};
|
||||
use erg_common::vis::Visibility;
|
||||
use erg_common::Str;
|
||||
|
@ -29,6 +30,7 @@ use RegistrationMode::*;
|
|||
use Visibility::*;
|
||||
|
||||
use super::instantiate::TyVarContext;
|
||||
use super::ImportKind;
|
||||
|
||||
impl Context {
|
||||
/// 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 => {
|
||||
if gen.t.is_monomorphic() {
|
||||
// let super_traits = gen.impls.iter().map(|to| to.typ().clone()).collect();
|
||||
let mut ctx =
|
||||
Self::mono_class(gen.t.name(), self.mod_cache.clone(), self.level);
|
||||
let mut methods =
|
||||
Self::methods(gen.t.name(), self.mod_cache.clone(), self.level);
|
||||
let mut ctx = Self::mono_class(
|
||||
gen.t.name(),
|
||||
self.mod_cache.clone(),
|
||||
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 new_t = func1(require, gen.t.clone());
|
||||
methods.register_fixed_auto_impl("__new__", new_t.clone(), Immutable, Private);
|
||||
|
@ -624,21 +634,29 @@ impl Context {
|
|||
.push((ClassDefType::Simple(gen.t.clone()), methods));
|
||||
self.register_gen_mono_type(ident, gen, ctx, Const);
|
||||
} else {
|
||||
todo!()
|
||||
todo!("polymorphic type definition is not supported yet");
|
||||
}
|
||||
}
|
||||
TypeKind::Subclass => {
|
||||
if gen.t.is_monomorphic() {
|
||||
let super_classes = vec![gen.require_or_sup.typ().clone()];
|
||||
// let super_traits = gen.impls.iter().map(|to| to.typ().clone()).collect();
|
||||
let mut ctx =
|
||||
Self::mono_class(gen.t.name(), self.mod_cache.clone(), self.level);
|
||||
let mut ctx = Self::mono_class(
|
||||
gen.t.name(),
|
||||
self.mod_cache.clone(),
|
||||
self.py_mod_cache.clone(),
|
||||
self.level,
|
||||
);
|
||||
for sup in super_classes.into_iter() {
|
||||
let (_, sup_ctx) = self.get_nominal_type_ctx(&sup).unwrap();
|
||||
ctx.register_superclass(sup, sup_ctx);
|
||||
}
|
||||
let mut methods =
|
||||
Self::methods(gen.t.name(), self.mod_cache.clone(), self.level);
|
||||
let mut methods = Self::methods(
|
||||
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()) {
|
||||
let sup = enum_unwrap!(sup, ValueObj::Type);
|
||||
let param_t = match sup {
|
||||
|
@ -668,13 +686,17 @@ impl Context {
|
|||
todo!("super class not found")
|
||||
}
|
||||
} else {
|
||||
todo!()
|
||||
todo!("polymorphic type definition is not supported yet");
|
||||
}
|
||||
}
|
||||
TypeKind::Trait => {
|
||||
if gen.t.is_monomorphic() {
|
||||
let mut ctx =
|
||||
Self::mono_trait(gen.t.name(), self.mod_cache.clone(), self.level);
|
||||
let mut ctx = Self::mono_trait(
|
||||
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:(_)));
|
||||
for (field, t) in require.iter() {
|
||||
let muty = if field.is_const() {
|
||||
|
@ -688,15 +710,19 @@ impl Context {
|
|||
}
|
||||
self.register_gen_mono_type(ident, gen, ctx, Const);
|
||||
} else {
|
||||
todo!()
|
||||
todo!("polymorphic type definition is not supported yet");
|
||||
}
|
||||
}
|
||||
TypeKind::Subtrait => {
|
||||
if gen.t.is_monomorphic() {
|
||||
let super_classes = vec![gen.require_or_sup.typ().clone()];
|
||||
// let super_traits = gen.impls.iter().map(|to| to.typ().clone()).collect();
|
||||
let mut ctx =
|
||||
Self::mono_trait(gen.t.name(), self.mod_cache.clone(), self.level);
|
||||
let mut ctx = Self::mono_trait(
|
||||
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:(_))));
|
||||
if let Some(additional) = additional {
|
||||
for (field, t) in additional.iter() {
|
||||
|
@ -717,7 +743,7 @@ impl Context {
|
|||
}
|
||||
self.register_gen_mono_type(ident, gen, ctx, Const);
|
||||
} else {
|
||||
todo!()
|
||||
todo!("polymorphic type definition is not supported yet");
|
||||
}
|
||||
}
|
||||
other => todo!("{other:?}"),
|
||||
|
@ -764,6 +790,7 @@ impl Context {
|
|||
|
||||
pub(crate) fn import_mod(
|
||||
&mut self,
|
||||
kind: ImportKind,
|
||||
current_input: Input,
|
||||
var_name: &VarName,
|
||||
mod_name: &hir::Expr,
|
||||
|
@ -771,61 +798,10 @@ impl Context {
|
|||
match mod_name {
|
||||
hir::Expr::Lit(lit) => {
|
||||
if self.subtype_of(&lit.value.class(), &Str) {
|
||||
let __name__ = enum_unwrap!(lit.value.clone(), ValueObj::Str);
|
||||
if let Some(mod_cache) = self.mod_cache.as_ref() {
|
||||
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,
|
||||
)?,
|
||||
}
|
||||
if kind.is_erg_import() {
|
||||
self.import_erg_mod(current_input, var_name, lit)?;
|
||||
} else {
|
||||
// maybe unreachable
|
||||
todo!("importing {__name__} in the builtin module")
|
||||
self.import_py_mod(current_input, var_name, lit)?;
|
||||
}
|
||||
} else {
|
||||
return Err(TyCheckError::type_mismatch_error(
|
||||
|
@ -852,14 +828,43 @@ impl Context {
|
|||
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,
|
||||
current_input: Input,
|
||||
var_name: &VarName,
|
||||
__name__: Str,
|
||||
name_lit: &Literal,
|
||||
mod_cache: &SharedModuleCache,
|
||||
py_mod_cache: &SharedModuleCache,
|
||||
) -> 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 {
|
||||
path.pop();
|
||||
path
|
||||
|
@ -867,24 +872,32 @@ impl Context {
|
|||
PathBuf::new()
|
||||
};
|
||||
dir.push(format!("{__name__}.er"));
|
||||
// TODO: returns an error
|
||||
let path = match dir.canonicalize() {
|
||||
Ok(path) => path,
|
||||
Err(err) => {
|
||||
return Err(TyCheckError::file_error(
|
||||
return Err(TyCheckError::import_error(
|
||||
line!() as usize,
|
||||
err.to_string(),
|
||||
name_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 {
|
||||
input: Input::File(path),
|
||||
..ErgConfig::default()
|
||||
};
|
||||
let cfg = ErgConfig::with_path(path);
|
||||
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") {
|
||||
Ok(hir) => {
|
||||
mod_cache.register(var_name.clone(), Some(hir), builder.pop_ctx());
|
||||
|
@ -896,6 +909,105 @@ impl Context {
|
|||
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) {
|
||||
self.bounds.push(TyBound::subtype_of(sub, sup));
|
||||
}
|
||||
|
|
|
@ -166,6 +166,10 @@ impl Context {
|
|||
.collect::<Vec<_>>();
|
||||
poly(name, params)
|
||||
}
|
||||
MonoProj { lhs, rhs } => {
|
||||
let lhs = self.generalize_t_inner(*lhs, bounds, lazy_inits);
|
||||
mono_proj(lhs, rhs)
|
||||
}
|
||||
// REVIEW: その他何でもそのまま通していいのか?
|
||||
other => other,
|
||||
}
|
||||
|
@ -489,6 +493,7 @@ impl Context {
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
hir::Expr::TypeAsc(tasc) => self.resolve_expr_t(&mut tasc.expr),
|
||||
hir::Expr::Code(chunks) | hir::Expr::Compound(chunks) => {
|
||||
for chunk in chunks.iter_mut() {
|
||||
self.resolve_expr_t(chunk)?;
|
||||
|
|
|
@ -58,7 +58,7 @@ impl SideEffectChecker {
|
|||
///
|
||||
/// 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)
|
||||
fn in_context_se_allowed(&self) -> bool {
|
||||
fn in_context_effects_allowed(&self) -> bool {
|
||||
// if toplevel
|
||||
if self.block_stack.len() == 1 {
|
||||
return true;
|
||||
|
@ -137,6 +137,9 @@ impl SideEffectChecker {
|
|||
self.path_stack.pop();
|
||||
self.block_stack.pop();
|
||||
}
|
||||
Expr::TypeAsc(tasc) => {
|
||||
self.check_expr(&tasc.expr);
|
||||
}
|
||||
other => todo!("{other}"),
|
||||
}
|
||||
}
|
||||
|
@ -255,7 +258,7 @@ impl SideEffectChecker {
|
|||
.as_ref()
|
||||
.map(|name| name.is_procedural())
|
||||
.unwrap_or(false))
|
||||
&& !self.in_context_se_allowed()
|
||||
&& !self.in_context_effects_allowed()
|
||||
{
|
||||
self.errs.push(EffectError::has_effect(
|
||||
line!() as usize,
|
||||
|
@ -292,6 +295,9 @@ impl SideEffectChecker {
|
|||
self.path_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
|
||||
Expr::Accessor(Accessor::Attr(attr)) => attr.ident.is_procedural(),
|
||||
Expr::Accessor(_) => todo!(),
|
||||
Expr::TypeAsc(tasc) => self.is_procedural(&tasc.expr),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,10 @@ use erg_common::error::{ErrorCore, ErrorDisplay, ErrorKind::*, Location, MultiEr
|
|||
use erg_common::set::Set;
|
||||
use erg_common::traits::{Locational, Stream};
|
||||
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};
|
||||
|
||||
|
@ -100,6 +103,8 @@ pub struct CompileError {
|
|||
pub caused_by: AtomicStr,
|
||||
}
|
||||
|
||||
impl_display_and_error!(CompileError);
|
||||
|
||||
impl From<ParserRunnerError> for CompileError {
|
||||
fn from(err: ParserRunnerError) -> Self {
|
||||
Self {
|
||||
|
@ -411,7 +416,7 @@ impl TyCheckError {
|
|||
loc: Location,
|
||||
caused_by: AtomicStr,
|
||||
name: &str,
|
||||
similar_name: Option<&Str>,
|
||||
similar_name: Option<&str>,
|
||||
) -> Self {
|
||||
let name = readable_name(name);
|
||||
let hint = similar_name.map(|n| {
|
||||
|
@ -447,7 +452,7 @@ impl TyCheckError {
|
|||
caused_by: AtomicStr,
|
||||
obj_t: &Type,
|
||||
name: &str,
|
||||
similar_name: Option<&Str>,
|
||||
similar_name: Option<&str>,
|
||||
) -> Self {
|
||||
let hint = similar_name.map(|n| {
|
||||
let n = readable_name(n);
|
||||
|
@ -483,7 +488,7 @@ impl TyCheckError {
|
|||
obj_name: &str,
|
||||
obj_t: &Type,
|
||||
name: &str,
|
||||
similar_name: Option<&Str>,
|
||||
similar_name: Option<&str>,
|
||||
) -> Self {
|
||||
let hint = similar_name.map(|n| {
|
||||
let n = readable_name(n);
|
||||
|
@ -995,19 +1000,19 @@ passed keyword args: {RED}{kw_args_len}{RESET}"
|
|||
switch_lang!(
|
||||
"japanese" => format!(
|
||||
"{RED}{name}{RESET}は{}行目ですでに移動されています",
|
||||
moved_loc.ln_begin().unwrap()
|
||||
moved_loc.ln_begin().unwrap_or(0)
|
||||
),
|
||||
"simplified_chinese" => format!(
|
||||
"{RED}{name}{RESET}已移至第{}行",
|
||||
moved_loc.ln_begin().unwrap()
|
||||
moved_loc.ln_begin().unwrap_or(0)
|
||||
),
|
||||
"traditional_chinese" => format!(
|
||||
"{RED}{name}{RESET}已移至第{}行",
|
||||
moved_loc.ln_begin().unwrap()
|
||||
moved_loc.ln_begin().unwrap_or(0)
|
||||
),
|
||||
"english" => format!(
|
||||
"{RED}{name}{RESET} was moved in line {}",
|
||||
moved_loc.ln_begin().unwrap()
|
||||
moved_loc.ln_begin().unwrap_or(0)
|
||||
),
|
||||
),
|
||||
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 {
|
||||
Self::new(ErrorCore::new(errno, IoError, loc, desc, None), caused_by)
|
||||
pub fn file_error(
|
||||
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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ use erg_type::value::{TypeKind, ValueObj};
|
|||
use erg_type::{impl_t, impl_t_for_enum, HasType, Type};
|
||||
|
||||
use crate::context::eval::type_from_token_kind;
|
||||
use crate::context::ImportKind;
|
||||
use crate::error::readable_name;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -1006,11 +1007,12 @@ impl Call {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn is_import_call(&self) -> bool {
|
||||
self.obj
|
||||
.show_acc()
|
||||
.map(|s| &s[..] == "import" || &s[..] == "pyimport" || &s[..] == "py")
|
||||
.unwrap_or(false)
|
||||
pub fn import_kind(&self) -> Option<ImportKind> {
|
||||
self.obj.show_acc().and_then(|s| match &s[..] {
|
||||
"import" => Some(ImportKind::ErgImport),
|
||||
"pyimport" | "py" => Some(ImportKind::PyImport),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1332,7 +1334,8 @@ impl Def {
|
|||
DefKind::Other
|
||||
}
|
||||
}
|
||||
Some("import") => DefKind::Module,
|
||||
Some("import") => DefKind::ErgImport,
|
||||
Some("pyimport") | Some("py") => DefKind::PyImport,
|
||||
_ => 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)]
|
||||
pub enum Expr {
|
||||
Lit(Literal),
|
||||
|
@ -1502,14 +1548,15 @@ pub enum Expr {
|
|||
Def(Def),
|
||||
ClassDef(ClassDef),
|
||||
AttrDef(AttrDef),
|
||||
TypeAsc(TypeAscription),
|
||||
Code(Block), // code object
|
||||
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_locational_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);
|
||||
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, TypeAsc);
|
||||
|
||||
impl Expr {
|
||||
pub fn receiver_t(&self) -> Option<&Type> {
|
||||
|
@ -1533,6 +1580,10 @@ impl Expr {
|
|||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_type_asc(&self) -> bool {
|
||||
matches!(self, Expr::TypeAsc(_))
|
||||
}
|
||||
}
|
||||
|
||||
/// Toplevel grammar unit
|
||||
|
|
|
@ -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::Str;
|
||||
use erg_common::{enum_unwrap, log};
|
||||
|
||||
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 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;
|
||||
|
||||
pub struct Linker {}
|
||||
|
||||
impl Linker {
|
||||
#[allow(deprecated)]
|
||||
pub fn link(cfg: ErgConfig, mut main: HIR, mod_cache: SharedModuleCache) -> HIR {
|
||||
log!(info "the linking process has started.");
|
||||
for chunk in main.module.iter_mut() {
|
||||
|
@ -22,7 +29,7 @@ impl Linker {
|
|||
// ↓
|
||||
// x = ModuleType("mod")
|
||||
// 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
|
||||
let hir = if cfg.input.is_repl() {
|
||||
mod_cache
|
||||
|
@ -43,7 +50,7 @@ impl Linker {
|
|||
let code = Expr::Code(Block::new(Vec::from(hir.module)));
|
||||
let module_type = Expr::Accessor(Accessor::private_with_line(
|
||||
Str::ever("#ModuleType"),
|
||||
def.ln_begin().unwrap(),
|
||||
def.ln_begin().unwrap_or(0),
|
||||
));
|
||||
let args =
|
||||
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(
|
||||
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 __dict__ = Identifier::public("__dict__");
|
||||
|
@ -76,6 +83,53 @@ impl Linker {
|
|||
*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,
|
||||
));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ use crate::error::{
|
|||
use crate::hir;
|
||||
use crate::hir::HIR;
|
||||
use crate::mod_cache::SharedModuleCache;
|
||||
use crate::reorder::Reorderer;
|
||||
use crate::varinfo::VarKind;
|
||||
use Visibility::*;
|
||||
|
||||
|
@ -48,6 +49,7 @@ impl Default for ASTLowerer {
|
|||
ErgConfig::default(),
|
||||
Str::ever("<module>"),
|
||||
SharedModuleCache::new(),
|
||||
SharedModuleCache::new(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +65,12 @@ impl Runnable for ASTLowerer {
|
|||
}
|
||||
|
||||
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]
|
||||
|
@ -86,7 +93,7 @@ impl Runnable for ASTLowerer {
|
|||
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 ast = ast_builder.build(src)?;
|
||||
let (hir, ..) = self.lower(ast, "eval").map_err(|errs| self.convert(errs))?;
|
||||
|
@ -99,10 +106,11 @@ impl ASTLowerer {
|
|||
cfg: ErgConfig,
|
||||
mod_name: S,
|
||||
mod_cache: SharedModuleCache,
|
||||
py_mod_cache: SharedModuleCache,
|
||||
) -> Self {
|
||||
Self {
|
||||
cfg,
|
||||
ctx: Context::new_module(mod_name, mod_cache),
|
||||
ctx: Context::new_module(mod_name, mod_cache, py_mod_cache),
|
||||
errs: LowerErrors::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<()> {
|
||||
if mode != "eval" && !expr.ref_t().is_nonelike() {
|
||||
if mode != "eval" && !expr.ref_t().is_nonelike() && !expr.is_type_asc() {
|
||||
Err(LowerError::syntax_error(
|
||||
0,
|
||||
expr.loc(),
|
||||
|
@ -533,27 +545,41 @@ impl ASTLowerer {
|
|||
|
||||
fn lower_def(&mut self, def: ast::Def) -> LowerResult<hir::Def> {
|
||||
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() {
|
||||
name
|
||||
name.clone()
|
||||
} 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(
|
||||
line!() as usize,
|
||||
def.sig.loc(),
|
||||
self.ctx.caused_by(),
|
||||
name,
|
||||
&name,
|
||||
));
|
||||
}
|
||||
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 {
|
||||
ast::Signature::Subr(sig) => self.lower_subr_def(sig, def.body),
|
||||
ast::Signature::Var(sig) => self.lower_var_def(sig, def.body),
|
||||
};
|
||||
// TODO: Context上の関数に型境界情報を追加
|
||||
self.pop_append_errs();
|
||||
// remove from decls regardless of success or failure to lower
|
||||
self.ctx.decls.remove(&name);
|
||||
res
|
||||
}
|
||||
|
||||
|
@ -589,7 +615,6 @@ impl ASTLowerer {
|
|||
}
|
||||
}
|
||||
let id = body.id;
|
||||
// TODO: cover all VarPatterns
|
||||
self.ctx
|
||||
.outer
|
||||
.as_mut()
|
||||
|
@ -597,9 +622,10 @@ impl ASTLowerer {
|
|||
.assign_var_sig(&sig, found_body_t, id)?;
|
||||
match block.first().unwrap() {
|
||||
hir::Expr::Call(call) => {
|
||||
if call.is_import_call() {
|
||||
if let Some(kind) = call.import_kind() {
|
||||
let current_input = self.input().clone();
|
||||
self.ctx.outer.as_mut().unwrap().import_mod(
|
||||
kind,
|
||||
current_input,
|
||||
&ident.name,
|
||||
&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)
|
||||
// so turn off type checking (check=false)
|
||||
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::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::TypeAsc(tasc) => Ok(hir::Expr::TypeAsc(self.lower_type_asc(tasc)?)),
|
||||
other => todo!("{other}"),
|
||||
}
|
||||
}
|
||||
|
@ -991,9 +1037,138 @@ impl ASTLowerer {
|
|||
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> {
|
||||
log!(info "the AST lowering 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());
|
||||
self.ctx.preregister(ast.module.block())?;
|
||||
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);
|
||||
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
|
||||
for chunk in hir.module.iter() {
|
||||
if let Err(e) = self.use_check(chunk, mode) {
|
||||
|
|
|
@ -4,7 +4,9 @@ use std::hash::Hash;
|
|||
use std::rc::Rc;
|
||||
|
||||
use erg_common::dict::Dict;
|
||||
use erg_common::levenshtein::get_similar_name;
|
||||
use erg_common::shared::Shared;
|
||||
use erg_common::Str;
|
||||
|
||||
use erg_parser::ast::VarName;
|
||||
|
||||
|
@ -26,7 +28,7 @@ impl ModId {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ModuleEntry {
|
||||
id: ModId, // builtin == 0, __main__ == 1
|
||||
pub hir: Option<HIR>,
|
||||
|
@ -88,6 +90,12 @@ impl ModuleCache {
|
|||
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>
|
||||
where
|
||||
VarName: Borrow<Q>,
|
||||
|
@ -102,6 +110,10 @@ impl ModuleCache {
|
|||
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>
|
||||
where
|
||||
VarName: Borrow<Q>,
|
||||
|
@ -122,6 +134,10 @@ impl ModuleCache {
|
|||
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)]
|
||||
|
@ -148,6 +164,11 @@ impl SharedModuleCache {
|
|||
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>
|
||||
where
|
||||
VarName: Borrow<Q>,
|
||||
|
@ -175,6 +196,10 @@ impl SharedModuleCache {
|
|||
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>
|
||||
where
|
||||
VarName: Borrow<Q>,
|
||||
|
@ -185,4 +210,8 @@ impl SharedModuleCache {
|
|||
pub fn remove_by_id(&self, id: ModId) -> Option<ModuleEntry> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -187,6 +187,9 @@ impl OwnershipChecker {
|
|||
self.check_block(&lambda.body);
|
||||
self.path_stack.pop();
|
||||
}
|
||||
Expr::TypeAsc(asc) => {
|
||||
self.check_expr(&asc.expr, ownership, chunk);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,14 +3,22 @@ use erg_compiler::mod_cache::SharedModuleCache;
|
|||
|
||||
#[test]
|
||||
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()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
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()?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -30,3 +38,17 @@ fn test_resolve_trait_inner1() -> Result<(), ()> {
|
|||
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(())
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "erg_parser"
|
||||
version = "0.5.1"
|
||||
version = "0.5.5-nightly.1"
|
||||
description = "The Erg parser"
|
||||
authors = ["erg-lang team <moderation.erglang@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
@ -16,7 +16,7 @@ simplified_chinese = [ "erg_common/simplified_chinese" ]
|
|||
traditional_chinese = [ "erg_common/traditional_chinese" ]
|
||||
|
||||
[dependencies]
|
||||
erg_common = { version = "0.5.1", path = "../erg_common" }
|
||||
erg_common = { version = "0.5.5-nightly.1", path = "../erg_common" }
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
|
|
@ -1511,6 +1511,7 @@ impl ParamTySpec {
|
|||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct SubrTypeSpec {
|
||||
pub bounds: TypeBoundSpecs,
|
||||
pub lparen: Option<Token>,
|
||||
pub non_defaults: Vec<ParamTySpec>,
|
||||
pub var_args: Option<Box<ParamTySpec>>,
|
||||
|
@ -1521,9 +1522,12 @@ pub struct SubrTypeSpec {
|
|||
|
||||
impl fmt::Display for SubrTypeSpec {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if !self.bounds.is_empty() {
|
||||
write!(f, "|{}|", self.bounds)?;
|
||||
}
|
||||
write!(
|
||||
f,
|
||||
"({}, {}, := {}) {} {}",
|
||||
"({}, {}, {}) {} {}",
|
||||
fmt_vec(&self.non_defaults),
|
||||
fmt_option!(pre "...", &self.var_args),
|
||||
fmt_vec(&self.defaults),
|
||||
|
@ -1535,7 +1539,9 @@ impl fmt::Display for SubrTypeSpec {
|
|||
|
||||
impl Locational for SubrTypeSpec {
|
||||
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())
|
||||
} else {
|
||||
// FIXME: only default subrs
|
||||
|
@ -1546,6 +1552,7 @@ impl Locational for SubrTypeSpec {
|
|||
|
||||
impl SubrTypeSpec {
|
||||
pub fn new(
|
||||
bounds: TypeBoundSpecs,
|
||||
lparen: Option<Token>,
|
||||
non_defaults: Vec<ParamTySpec>,
|
||||
var_args: Option<ParamTySpec>,
|
||||
|
@ -1554,6 +1561,7 @@ impl SubrTypeSpec {
|
|||
return_t: TypeSpec,
|
||||
) -> Self {
|
||||
Self {
|
||||
bounds,
|
||||
lparen,
|
||||
non_defaults,
|
||||
var_args: var_args.map(Box::new),
|
||||
|
@ -2841,7 +2849,9 @@ pub enum DefKind {
|
|||
Trait,
|
||||
Subsume,
|
||||
StructuralTrait,
|
||||
Module,
|
||||
ErgImport,
|
||||
PyImport,
|
||||
/// type alias included
|
||||
Other,
|
||||
}
|
||||
|
||||
|
@ -2850,8 +2860,20 @@ impl DefKind {
|
|||
matches!(self, Self::Trait | Self::Subsume | Self::StructuralTrait)
|
||||
}
|
||||
|
||||
pub fn is_module(&self) -> bool {
|
||||
matches!(self, Self::Module)
|
||||
pub const fn is_class(&self) -> bool {
|
||||
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 {
|
||||
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)]
|
||||
|
@ -2901,28 +2949,7 @@ impl Def {
|
|||
}
|
||||
|
||||
pub fn def_kind(&self) -> DefKind {
|
||||
match self.body.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::Module,
|
||||
_ => DefKind::Other,
|
||||
},
|
||||
_ => DefKind::Other,
|
||||
}
|
||||
self.body.def_kind()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ use erg_common::color::{RED, RESET};
|
|||
use erg_common::config::Input;
|
||||
use erg_common::error::{ErrorCore, ErrorDisplay, ErrorKind::*, Location, MultiErrorDisplay};
|
||||
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)]
|
||||
pub struct LexError(ErrorCore);
|
||||
|
@ -144,6 +144,8 @@ pub struct ParserRunnerError {
|
|||
pub input: Input,
|
||||
}
|
||||
|
||||
impl_display_and_error!(ParserRunnerError);
|
||||
|
||||
impl ErrorDisplay for ParserRunnerError {
|
||||
fn core(&self) -> &ErrorCore {
|
||||
&self.core
|
||||
|
|
|
@ -362,7 +362,10 @@ impl Parser {
|
|||
if self.cur_is(Newline) {
|
||||
self.skip();
|
||||
} else {
|
||||
todo!()
|
||||
self.level -= 1;
|
||||
let err = self.skip_and_throw_syntax_err(caused_by!());
|
||||
self.errs.push(err);
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
self.level -= 1;
|
||||
|
@ -863,13 +866,24 @@ impl Parser {
|
|||
if self.cur_is(Indent) {
|
||||
self.skip();
|
||||
} 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) {
|
||||
self.skip();
|
||||
}
|
||||
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];
|
||||
loop {
|
||||
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);
|
||||
|
@ -912,7 +931,7 @@ impl Parser {
|
|||
let op = match &do_symbol.inspect()[..] {
|
||||
"do" => Token::from_str(FuncArrow, "->"),
|
||||
"do!" => Token::from_str(ProcArrow, "=>"),
|
||||
_ => todo!(),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
if self.cur_is(Colon) {
|
||||
self.lpop();
|
||||
|
@ -1058,8 +1077,13 @@ impl Parser {
|
|||
let pack = DataPack::new(maybe_class, vis, args);
|
||||
stack.push(ExprOrOp::Expr(Expr::DataPack(pack)));
|
||||
}
|
||||
BraceContainer::Dict(dict) => todo!("{dict}"),
|
||||
BraceContainer::Set(set) => todo!("{set}"),
|
||||
BraceContainer::Dict(_) | BraceContainer::Set(_) => {
|
||||
// self.restore(other);
|
||||
self.level -= 1;
|
||||
let err = self.skip_and_throw_syntax_err(caused_by!());
|
||||
self.errs.push(err);
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
}
|
||||
other => {
|
||||
|
@ -1344,7 +1368,15 @@ impl Parser {
|
|||
Some(t) if t.is(AtSign) => {
|
||||
let decos = self.opt_reduce_decorators()?;
|
||||
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 {
|
||||
Signature::Subr(mut subr) => {
|
||||
subr.decorators = decos;
|
||||
|
@ -1509,7 +1541,15 @@ impl Parser {
|
|||
ArrayInner::WithLength(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;
|
||||
Ok(arr)
|
||||
|
@ -1525,7 +1565,10 @@ impl Parser {
|
|||
if self.cur_is(Indent) {
|
||||
self.skip();
|
||||
} 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())?;
|
||||
|
@ -1576,7 +1619,12 @@ impl Parser {
|
|||
let attrs = RecordAttrs::from(attrs);
|
||||
return Ok(NormalRecord::new(l_brace, r_brace, attrs));
|
||||
} 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) => {
|
||||
|
@ -1587,10 +1635,24 @@ impl Parser {
|
|||
}
|
||||
Some(_) => {
|
||||
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);
|
||||
}
|
||||
_ => 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);
|
||||
let first = match first {
|
||||
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];
|
||||
loop {
|
||||
|
@ -1618,7 +1685,11 @@ impl Parser {
|
|||
self.level -= 1;
|
||||
return Ok(ShortenedRecord::new(l_brace, r_brace, idents));
|
||||
} 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) => {
|
||||
|
@ -1630,11 +1701,22 @@ impl Parser {
|
|||
let acc = self.try_reduce_acc(false).map_err(|_| self.stack_dec())?;
|
||||
let acc = match acc {
|
||||
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);
|
||||
}
|
||||
_ => 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));
|
||||
}
|
||||
},
|
||||
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;
|
||||
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) => {
|
||||
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);
|
||||
|
@ -1995,7 +2103,11 @@ impl Parser {
|
|||
let bound = TypeBoundSpec::non_default(lhs.name.into_token(), spec_with_op);
|
||||
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;
|
||||
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;
|
||||
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())?;
|
||||
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;
|
||||
Ok(t_spec)
|
||||
|
@ -2397,9 +2524,66 @@ impl Parser {
|
|||
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);
|
||||
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> {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "erg_type"
|
||||
version = "0.5.1"
|
||||
version = "0.5.5-nightly.1"
|
||||
description = "APIs for Erg types"
|
||||
authors = ["erg-lang team <moderation.erglang@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
@ -18,8 +18,8 @@ simplified_chinese = [ "erg_common/simplified_chinese" ]
|
|||
traditional_chinese = [ "erg_common/traditional_chinese" ]
|
||||
|
||||
[dependencies]
|
||||
erg_common = { version = "0.5.1", path = "../erg_common" }
|
||||
erg_parser = { version = "0.5.1", path = "../erg_parser" }
|
||||
erg_common = { version = "0.5.5-nightly.1", path = "../erg_common" }
|
||||
erg_parser = { version = "0.5.5-nightly.1", path = "../erg_parser" }
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
|
|
@ -632,6 +632,7 @@ impl<T: Clone + HasLevel> Free<T> {
|
|||
pub fn unbound_name(&self) -> Option<Str> {
|
||||
match &*self.borrow() {
|
||||
FreeKind::NamedUnbound { name, .. } => Some(name.clone()),
|
||||
FreeKind::Unbound { id, .. } => Some(Str::from(id.to_string())),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1817,6 +1817,7 @@ impl Type {
|
|||
|
||||
pub fn tvar_name(&self) -> Option<Str> {
|
||||
match self {
|
||||
Self::FreeVar(fv) if fv.is_linked() => fv.crack().tvar_name(),
|
||||
Self::FreeVar(fv) => fv.unbound_name(),
|
||||
Self::MonoQVar(name) => Some(name.clone()),
|
||||
_ => None,
|
||||
|
|
|
@ -509,6 +509,7 @@ impl TyParam {
|
|||
pub fn name(&self) -> Option<Str> {
|
||||
match self {
|
||||
Self::Type(t) => Some(t.name()),
|
||||
Self::FreeVar(fv) if fv.is_linked() => fv.crack().name(),
|
||||
Self::Mono(name) => Some(name.clone()),
|
||||
Self::MonoQVar(name) => Some(name.clone()),
|
||||
_ => None,
|
||||
|
@ -518,6 +519,7 @@ impl TyParam {
|
|||
pub fn tvar_name(&self) -> Option<Str> {
|
||||
match self {
|
||||
Self::Type(t) => t.tvar_name(),
|
||||
Self::FreeVar(fv) if fv.is_linked() => fv.crack().tvar_name(),
|
||||
Self::FreeVar(fv) => fv.unbound_name(),
|
||||
Self::MonoQVar(name) => Some(name.clone()),
|
||||
_ => None,
|
||||
|
|
|
@ -802,8 +802,12 @@ pub mod value_set {
|
|||
|
||||
// false -> SyntaxError
|
||||
pub fn is_homogeneous(set: &Set<ValueObj>) -> bool {
|
||||
let l_first = set.iter().next().unwrap().class();
|
||||
set.iter().all(|c| c.class() == l_first)
|
||||
if let Some(first) = set.iter().next() {
|
||||
let l_first = first.class();
|
||||
set.iter().all(|c| c.class() == l_first)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
pub fn inner_class(set: &Set<ValueObj>) -> Type {
|
||||
|
|
|
@ -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.
|
||||
> 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.
|
||||
|
||||
|
|
|
@ -22,20 +22,20 @@ print(foo.public)
|
|||
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
|
||||
time = pyimport "time"
|
||||
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.
|
||||
Type hints on the Python side are ignored since they are not 100% guaranteed.
|
||||
|
@ -47,30 +47,34 @@ def bar(x):
|
|||
...
|
||||
def baz():
|
||||
...
|
||||
class C:
|
||||
...
|
||||
...
|
||||
```
|
||||
|
||||
```python
|
||||
````python
|
||||
# foo.d.er
|
||||
foo = pyimport "foo"
|
||||
.X = declare foo.'X', Int
|
||||
.bar = declare foo.'bar', Int -> Int
|
||||
.baz! = declare foo.'baz', () => Int
|
||||
.X: Int
|
||||
.bar!: Int => Int
|
||||
.foo! = baz!: () => Int # aliasing
|
||||
.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
|
||||
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
|
||||
declare|S: Subroutine| sub!: S, T =
|
||||
# Actually, => can be cast to a function without block side effects
|
||||
decl_proc proc!: Proc, T =
|
||||
x =>
|
||||
assert x in T.Input
|
||||
y = sub!(x)
|
||||
y = proc!(x)
|
||||
assert y in T.Output
|
||||
y
|
||||
```
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# 基本事項
|
||||
|
||||
[](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)
|
||||
[](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.*の間に破壊的変更が加えられる可能性があり、それに伴うドキュメントの更新が追いついていない可能性があります。予めご了承ください。
|
||||
> また、本ドキュメントの誤りを見つけた場合は、[こちらのフォーム](https://forms.gle/HtLYRfYzWCAaeTGb6)または[GitHubリポジトリ](https://github.com/mtshiba/TheErgBook/issues/new)から修正の提案をしていただけると幸いです。
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Pythonとの連携
|
||||
|
||||
[](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)
|
||||
[](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
|
||||
|
||||
|
@ -49,29 +49,34 @@ def bar(x):
|
|||
...
|
||||
def baz():
|
||||
...
|
||||
class C:
|
||||
...
|
||||
```
|
||||
|
||||
```python
|
||||
# foo.d.er
|
||||
foo = pyimport "foo"
|
||||
.X = declare foo.'X', Int
|
||||
.bar = declare foo.'bar', Int -> Int
|
||||
.baz! = declare foo.'baz', () => Int
|
||||
.X: Int
|
||||
.bar!: Int => Int
|
||||
.foo! = baz!: () => Int # aliasing
|
||||
.C!: Class
|
||||
```
|
||||
|
||||
`d.er`内では宣言と定義(エイリアシング)以外の構文は使えません。
|
||||
|
||||
Pythonの関数はすべてプロシージャとして、クラスはすべて可変クラスとしてしか登録できないことに注意してください。
|
||||
|
||||
```python
|
||||
foo = pyimport "foo"
|
||||
assert foo.bar(1) in Int
|
||||
assert foo.bar!(1) in Int
|
||||
```
|
||||
|
||||
これは、実行時に型チェックを行うことで型安全性を担保しています。`declare`関数は概ね以下のように動作します。
|
||||
これは、実行時に型チェックを行うことで型安全性を担保しています。チェック機構は概ね以下のように動作します。
|
||||
|
||||
```python
|
||||
declare|S: Subroutine| sub!: S, T =
|
||||
# 実は、=>はブロックの副作用がなければ関数にキャストできる
|
||||
decl_proc proc!: Proc, T =
|
||||
x =>
|
||||
assert x in T.Input
|
||||
y = sub!(x)
|
||||
y = proc!(x)
|
||||
assert y in T.Output
|
||||
y
|
||||
```
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# 基本
|
||||
|
||||
[](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)
|
||||
[](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.* 期间发生破坏性更改,并且文档可能没有相应更新。 请事先了解这一点。
|
||||
> 如果您在本文档中发现任何错误,请报告至 [此处的表单](https://forms.gle/HtLYRfYzWCAaeTGb6) 或 [GitHub repo](https://github.com/mtshiba/TheErgBook/issues/new )。 我们将不胜感激您的建议。
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# 基本
|
||||
|
||||
[](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)
|
||||
[](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.* 期間發生破壞性更改,并且文檔可能沒有相應更新。 請事先了解這一點。
|
||||
> 如果您在本文檔中發現任何錯誤,請報告至 [此處的表單](https://forms.gle/HtLYRfYzWCAaeTGb6) 或 [GitHub repo](https://github.com/mtshiba/TheErgBook/issues/new )。 我們將不勝感激您的建議。
|
||||
|
|
|
@ -18,7 +18,7 @@ sum = match a:
|
|||
(i: Int) -> i
|
||||
_ -> panic "unknown object"
|
||||
|
||||
for! 0..1000, i =>
|
||||
for! 0..<1000, i =>
|
||||
print! "i = {i}"
|
||||
if i >= 100:
|
||||
do return break()
|
||||
|
|
2
examples/declare.d.er
Normal file
2
examples/declare.d.er
Normal file
|
@ -0,0 +1,2 @@
|
|||
.x: Int
|
||||
.f: Int -> Int
|
2
examples/declare.py
Normal file
2
examples/declare.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
x = 0
|
||||
def f(x: int) -> int: return x + 1
|
3
examples/use_py.er
Normal file
3
examples/use_py.er
Normal file
|
@ -0,0 +1,3 @@
|
|||
declare = pyimport "declare"
|
||||
|
||||
print! declare.f(declare.x + 1)
|
Loading…
Add table
Add a link
Reference in a new issue