Fix import to be called from anywhere

This commit is contained in:
Shunsuke Shibayama 2022-09-29 11:48:38 +09:00
parent f548f9e6ef
commit 23a6f630c9
21 changed files with 979 additions and 549 deletions

View file

@ -4,7 +4,7 @@
use std::env;
use std::fs::File;
use std::io::{stdin, BufRead, BufReader, Read};
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use std::process;
use std::str::FromStr;
@ -35,7 +35,7 @@ impl Input {
pub fn enclosed_name(&self) -> &str {
match self {
Self::File(filename) => filename.as_os_str().to_str().unwrap_or("???"),
Self::File(filename) => filename.to_str().unwrap_or("???"),
Self::REPL | Self::Pipe(_) => "<stdin>",
Self::Str(_) => "<string>",
Self::Dummy => "<dummy>",
@ -45,7 +45,7 @@ impl Input {
/// ファイルに書き出すとき使う
pub fn filename(&self) -> &str {
match self {
Self::File(filename) => filename.as_os_str().to_str().unwrap_or("???"),
Self::File(filename) => filename.to_str().unwrap_or("???"),
Self::REPL | Self::Pipe(_) => "stdin",
Self::Str(_) => "string",
Self::Dummy => "dummy",
@ -116,6 +116,21 @@ impl Input {
Self::Dummy => panic!("cannot read from a dummy file"),
}
}
pub fn resolve(&self, path: &Path) -> Result<PathBuf, std::io::Error> {
let mut dir = if let Self::File(mut path) = self.clone() {
path.pop();
path
} else {
PathBuf::new()
};
dir.push(path);
dir.set_extension("er");
dir.canonicalize().or_else(|_| {
dir.set_extension("d.er");
dir.canonicalize()
})
}
}
#[derive(Debug, Clone)]

View file

@ -594,11 +594,11 @@ impl Context {
(Ref(l), r) => self.supertype_of(l, r),
(RefMut { before: l, .. }, r) => self.supertype_of(l, r),
(
Poly {
BuiltinPoly {
name: ln,
params: lparams,
},
Poly {
BuiltinPoly {
name: rn,
params: rparams,
},
@ -608,6 +608,23 @@ impl Context {
}
self.poly_supertype_of(lhs, lparams, rparams)
}
(
Poly {
path: lp,
name: ln,
params: lparams,
},
Poly {
path: rp,
name: rn,
params: rparams,
},
) => {
if lp != rp || ln != rn || lparams.len() != rparams.len() {
return false;
}
self.poly_supertype_of(lhs, lparams, rparams)
}
(MonoQVar(name), r) | (PolyQVar { name, .. }, r) => {
panic!("internal error: not instantiated type variable: '{name}, r: {r}")
}

View file

@ -14,7 +14,7 @@ use erg_parser::ast::*;
use erg_parser::token::{Token, TokenKind};
use erg_type::constructors::{
builtin_mono, enum_t, mono_proj, poly, ref_, ref_mut, refinement, subr_t,
builtin_mono, builtin_poly, mono_proj, poly, ref_, ref_mut, refinement, subr_t, v_enum,
};
use erg_type::typaram::{OpKind, TyParam};
use erg_type::value::ValueObj;
@ -305,7 +305,7 @@ impl Context {
match subr {
ConstSubr::User(_user) => todo!(),
ConstSubr::Builtin(builtin) => builtin
.call(args, self.mod_name().clone(), __name__)
.call(args, self.path().to_path_buf(), __name__)
.map_err(|mut e| {
e.loc = loc;
EvalErrors::from(EvalError::new(e, self.cfg.input.clone(), self.caused_by()))
@ -445,7 +445,7 @@ impl Context {
non_default_params.clone(),
var_params.clone(),
default_params.clone(),
enum_t(set![return_t.clone()]),
v_enum(set![return_t.clone()]),
);
let sig_t = self.generalize_t(sig_t);
let as_type = subr_t(
@ -791,11 +791,21 @@ impl Context {
};
Ok(ref_mut(before, after))
}
Type::Poly { name, mut params } => {
Type::BuiltinPoly { name, mut params } => {
for p in params.iter_mut() {
*p = self.eval_tp(&mem::take(p))?;
}
Ok(poly(name, params))
Ok(builtin_poly(name, params))
}
Type::Poly {
path,
name,
mut params,
} => {
for p in params.iter_mut() {
*p = self.eval_tp(&mem::take(p))?;
}
Ok(poly(path, name, params))
}
other if other.is_monomorphic() => Ok(other),
other => todo!("{other}"),
@ -839,7 +849,7 @@ impl Context {
let p = self.eval_tp(p)?;
match p {
TyParam::Value(ValueObj::Mut(v)) => Ok(v.borrow().class().mutate()),
TyParam::Value(v) => Ok(enum_t(set![v])),
TyParam::Value(v) => Ok(v_enum(set![v])),
TyParam::Erased(t) => Ok((*t).clone()),
TyParam::FreeVar(fv) => {
if let Some(t) = fv.get_type() {
@ -852,7 +862,7 @@ impl Context {
TyParam::Type(_) => Ok(Type::Type),
TyParam::Mono(name) => self
.rec_get_const_obj(&name)
.map(|v| enum_t(set![v.clone()]))
.map(|v| v_enum(set![v.clone()]))
.ok_or_else(|| {
EvalErrors::from(EvalError::unreachable(
self.cfg.input.clone(),

View file

@ -1,4 +1,5 @@
use std::mem;
use std::path::PathBuf;
use erg_common::Str;
@ -12,7 +13,7 @@ use erg_type::ValueArgs;
/// Requirement: Type, Impl := Type -> ClassType
pub fn class_func(
mut args: ValueArgs,
mod_name: Str,
path: PathBuf,
__name__: Option<Str>,
) -> EvalValueResult<ValueObj> {
let require = args.remove_left_or_key("Requirement").ok_or_else(|| {
@ -39,14 +40,14 @@ pub fn class_func(
};
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>")));
let t = mono(path, __name__.unwrap_or(Str::ever("<Lambda>")));
Ok(ValueObj::gen_t(TypeKind::Class, t, require, impls, None))
}
/// Super: ClassType, Impl := Type, Additional := Type -> ClassType
pub fn inherit_func(
mut args: ValueArgs,
mod_name: Str,
path: PathBuf,
__name__: Option<Str>,
) -> EvalValueResult<ValueObj> {
let sup = args.remove_left_or_key("Super").ok_or_else(|| {
@ -75,7 +76,7 @@ pub fn inherit_func(
let impls = impls.map(|v| v.as_type().unwrap());
let additional = args.remove_left_or_key("Additional");
let additional = additional.map(|v| v.as_type().unwrap());
let t = mono(mod_name, __name__.unwrap_or(Str::ever("<Lambda>")));
let t = mono(path, __name__.unwrap_or(Str::ever("<Lambda>")));
Ok(ValueObj::gen_t(
TypeKind::Subclass,
t,
@ -89,7 +90,7 @@ pub fn inherit_func(
/// This function is used by the compiler to mark a class as inheritable and does nothing in terms of actual operation.
pub fn inheritable_func(
mut args: ValueArgs,
_mod_name: Str,
_path: PathBuf,
__name__: Option<Str>,
) -> EvalValueResult<ValueObj> {
let class = args.remove_left_or_key("Class").ok_or_else(|| {
@ -124,7 +125,7 @@ pub fn inheritable_func(
/// Requirement: Type, Impl := Type -> TraitType
pub fn trait_func(
mut args: ValueArgs,
mod_name: Str,
path: PathBuf,
__name__: Option<Str>,
) -> EvalValueResult<ValueObj> {
let require = args.remove_left_or_key("Requirement").ok_or_else(|| {
@ -151,14 +152,14 @@ pub fn trait_func(
};
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>")));
let t = mono(path, __name__.unwrap_or(Str::ever("<Lambda>")));
Ok(ValueObj::gen_t(TypeKind::Trait, t, require, impls, None))
}
/// Super: TraitType, Impl := Type, Additional := Type -> TraitType
pub fn subsume_func(
mut args: ValueArgs,
mod_name: Str,
path: PathBuf,
__name__: Option<Str>,
) -> EvalValueResult<ValueObj> {
let sup = args.remove_left_or_key("Super").ok_or_else(|| {
@ -187,7 +188,7 @@ pub fn subsume_func(
let impls = impls.map(|v| v.as_type().unwrap());
let additional = args.remove_left_or_key("Additional");
let additional = additional.map(|v| v.as_type().unwrap());
let t = mono(mod_name, __name__.unwrap_or(Str::ever("<Lambda>")));
let t = mono(path, __name__.unwrap_or(Str::ever("<Lambda>")));
Ok(ValueObj::gen_t(
TypeKind::Subtrait,
t,

View file

@ -4,6 +4,8 @@
pub mod const_func;
pub mod py_mods;
use std::path::PathBuf;
use erg_common::config::ErgConfig;
use erg_common::error::Location;
use erg_common::vis::Visibility;
@ -61,7 +63,7 @@ impl Context {
panic!("already registered: {name}");
} else {
// TODO: not all value objects are comparable
let vi = VarInfo::new(enum_t(set! {obj.clone()}), Const, Private, Builtin, None);
let vi = VarInfo::new(v_enum(set! {obj.clone()}), Const, Private, Builtin, None);
self.consts.insert(VarName::from_str(Str::rc(name)), obj);
self.locals.insert(VarName::from_str(Str::rc(name)), vi);
}
@ -206,31 +208,31 @@ impl Context {
let params = vec![PS::t("T", NonDefault)];
let input = Self::builtin_poly_trait("Input", params.clone(), 2);
let output = Self::builtin_poly_trait("Output", params, 2);
in_.register_superclass(poly("Input", vec![ty_tp(mono_q("T"))]), &input);
in_.register_superclass(builtin_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(
op_t,
set! { static_instance("T", Type), subtypeof(mono_q("I"), poly("In", vec![ty_tp(mono_q("T"))])) },
set! { static_instance("T", Type), subtypeof(mono_q("I"), builtin_poly("In", vec![ty_tp(mono_q("T"))])) },
);
in_.register_builtin_decl("__in__", op_t, Public);
// 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::builtin_poly_trait("Eq", vec![PS::t("R", WithDefault)], 2);
eq.register_superclass(poly("Output", vec![ty_tp(mono_q("R"))]), &output);
eq.register_superclass(builtin_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);
let op_t = quant(
op_t,
set! {
subtypeof(mono_q("Self"), poly("Eq", vec![ty_tp(mono_q("R"))])),
subtypeof(mono_q("Self"), builtin_poly("Eq", vec![ty_tp(mono_q("R"))])),
static_instance("R", Type)
},
);
eq.register_builtin_decl("__eq__", op_t, Public);
let mut partial_ord =
Self::builtin_poly_trait("PartialOrd", vec![PS::t("R", WithDefault)], 2);
partial_ord.register_superclass(poly("Eq", vec![ty_tp(mono_q("R"))]), &eq);
partial_ord.register_superclass(builtin_poly("Eq", vec![ty_tp(mono_q("R"))]), &eq);
let op_t = fn1_met(
mono_q("Self"),
mono_q("R"),
@ -239,15 +241,15 @@ impl Context {
let op_t = quant(
op_t,
set! {
subtypeof(mono_q("Self"), poly("PartialOrd", vec![ty_tp(mono_q("R"))])),
subtypeof(mono_q("Self"), builtin_poly("PartialOrd", vec![ty_tp(mono_q("R"))])),
static_instance("R", Type)
},
);
partial_ord.register_builtin_decl("__partial_cmp__", op_t, Public);
let mut ord = Self::builtin_mono_trait("Ord", 2);
ord.register_superclass(poly("Eq", vec![ty_tp(builtin_mono("Self"))]), &eq);
ord.register_superclass(builtin_poly("Eq", vec![ty_tp(builtin_mono("Self"))]), &eq);
ord.register_superclass(
poly("PartialOrd", vec![ty_tp(builtin_mono("Self"))]),
builtin_poly("PartialOrd", vec![ty_tp(builtin_mono("Self"))]),
&partial_ord,
);
// FIXME: poly trait
@ -258,18 +260,18 @@ impl Context {
poly("Mul", vec![]),
], */
let mut seq = Self::builtin_poly_trait("Seq", vec![PS::t("T", NonDefault)], 2);
seq.register_superclass(poly("Output", vec![ty_tp(mono_q("T"))]), &output);
seq.register_superclass(builtin_poly("Output", vec![ty_tp(mono_q("T"))]), &output);
let self_t = mono_q("Self");
let t = fn0_met(self_t.clone(), Nat);
let t = quant(
t,
set! {subtypeof(self_t.clone(), poly("Seq", vec![TyParam::erased(Type)]))},
set! {subtypeof(self_t.clone(), builtin_poly("Seq", vec![TyParam::erased(Type)]))},
);
seq.register_builtin_decl("len", t, Public);
let t = fn1_met(self_t.clone(), Nat, mono_q("T"));
let t = quant(
t,
set! {subtypeof(self_t, poly("Seq", vec![ty_tp(mono_q("T"))])), static_instance("T", Type)},
set! {subtypeof(self_t, builtin_poly("Seq", vec![ty_tp(mono_q("T"))])), static_instance("T", Type)},
);
// Seq.get: |Self <: Seq(T)| Self.(Nat) -> T
seq.register_builtin_decl("get", t, Public);
@ -279,8 +281,8 @@ impl Context {
let ty_params = vec![ty_tp(mono_q("R"))];
let mut add = Self::builtin_poly_trait("Add", params.clone(), 2);
// 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()));
add.register_superclass(builtin_poly("Output", vec![ty_tp(mono_q("R"))]), &output);
let self_bound = subtypeof(mono_q("Self"), builtin_poly("Add", ty_params.clone()));
let op_t = fn1_met(
mono_q("Self"),
r.clone(),
@ -290,31 +292,31 @@ impl Context {
add.register_builtin_decl("__add__", op_t, Public);
add.register_builtin_decl("Output", Type, Public);
let mut sub = Self::builtin_poly_trait("Sub", params.clone(), 2);
sub.register_superclass(poly("Output", vec![ty_tp(mono_q("R"))]), &output);
sub.register_superclass(builtin_poly("Output", vec![ty_tp(mono_q("R"))]), &output);
let op_t = fn1_met(
mono_q("Self"),
r.clone(),
mono_proj(mono_q("Self"), "Output"),
);
let self_bound = subtypeof(mono_q("Self"), poly("Sub", ty_params.clone()));
let self_bound = subtypeof(mono_q("Self"), builtin_poly("Sub", ty_params.clone()));
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::builtin_poly_trait("Mul", params.clone(), 2);
mul.register_superclass(poly("Output", vec![ty_tp(mono_q("R"))]), &output);
mul.register_superclass(builtin_poly("Output", vec![ty_tp(mono_q("R"))]), &output);
let op_t = fn1_met(
mono_q("Self"),
r.clone(),
mono_proj(mono_q("Self"), "Output"),
);
let self_bound = subtypeof(mono_q("Self"), poly("Mul", ty_params.clone()));
let self_bound = subtypeof(mono_q("Self"), builtin_poly("Mul", ty_params.clone()));
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::builtin_poly_trait("Div", params, 2);
div.register_superclass(poly("Output", vec![ty_tp(mono_q("R"))]), &output);
div.register_superclass(builtin_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()));
let self_bound = subtypeof(mono_q("Self"), builtin_poly("Div", ty_params.clone()));
let op_t = quant(op_t, set! {r_bound, self_bound});
div.register_builtin_decl("__div__", op_t, Public);
div.register_builtin_decl("Output", Type, Public);
@ -324,22 +326,30 @@ impl Context {
self.register_builtin_type(builtin_mono("Mutable"), mutable, Const);
self.register_builtin_type(builtin_mono("Immutizable"), immutizable, Const);
self.register_builtin_type(builtin_mono("Mutizable"), mutizable, Const);
self.register_builtin_type(poly("Input", vec![ty_tp(mono_q("T"))]), input, Const);
self.register_builtin_type(poly("Output", vec![ty_tp(mono_q("T"))]), output, Const);
self.register_builtin_type(poly("In", vec![ty_tp(mono_q("T"))]), in_, Const);
self.register_builtin_type(poly("Eq", vec![ty_tp(mono_q("R"))]), eq, Const);
self.register_builtin_type(
poly("PartialOrd", vec![ty_tp(mono_q("R"))]),
builtin_poly("Input", vec![ty_tp(mono_q("T"))]),
input,
Const,
);
self.register_builtin_type(
builtin_poly("Output", vec![ty_tp(mono_q("T"))]),
output,
Const,
);
self.register_builtin_type(builtin_poly("In", vec![ty_tp(mono_q("T"))]), in_, Const);
self.register_builtin_type(builtin_poly("Eq", vec![ty_tp(mono_q("R"))]), eq, Const);
self.register_builtin_type(
builtin_poly("PartialOrd", vec![ty_tp(mono_q("R"))]),
partial_ord,
Const,
);
self.register_builtin_type(builtin_mono("Ord"), ord, Const);
self.register_builtin_type(builtin_mono("Num"), num, Const);
self.register_builtin_type(poly("Seq", vec![ty_tp(mono_q("T"))]), seq, Const);
self.register_builtin_type(poly("Add", ty_params.clone()), add, Const);
self.register_builtin_type(poly("Sub", ty_params.clone()), sub, Const);
self.register_builtin_type(poly("Mul", ty_params.clone()), mul, Const);
self.register_builtin_type(poly("Div", ty_params), div, Const);
self.register_builtin_type(builtin_poly("Seq", vec![ty_tp(mono_q("T"))]), seq, Const);
self.register_builtin_type(builtin_poly("Add", ty_params.clone()), add, Const);
self.register_builtin_type(builtin_poly("Sub", ty_params.clone()), sub, Const);
self.register_builtin_type(builtin_poly("Mul", ty_params.clone()), mul, Const);
self.register_builtin_type(builtin_poly("Div", ty_params), div, Const);
self.register_const_param_defaults(
"Eq",
vec![ConstTemplate::Obj(ValueObj::builtin_t(mono_q("Self")))],
@ -384,7 +394,7 @@ impl Context {
);
let mut obj_in = Self::builtin_methods("In", 2);
obj_in.register_builtin_impl("__in__", fn1_met(Obj, Type, Bool), Const, Public);
obj.register_trait(Obj, poly("Eq", vec![ty_tp(Type)]), obj_in);
obj.register_trait(Obj, builtin_poly("Eq", vec![ty_tp(Type)]), obj_in);
let mut obj_mutizable = Self::builtin_methods("Mutizable", 1);
obj_mutizable.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Obj!")));
obj.register_trait(Obj, builtin_mono("Mutizable"), obj_mutizable);
@ -405,7 +415,7 @@ impl Context {
);
float.register_trait(
Float,
poly("PartialOrd", vec![ty_tp(Float)]),
builtin_poly("PartialOrd", vec![ty_tp(Float)]),
float_partial_ord,
);
// Float doesn't have an `Eq` implementation
@ -413,21 +423,21 @@ impl Context {
let mut float_add = Self::builtin_methods("Add", 2);
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);
float.register_trait(Float, builtin_poly("Add", vec![ty_tp(Float)]), float_add);
let mut float_sub = Self::builtin_methods("Sub", 2);
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);
float.register_trait(Float, builtin_poly("Sub", vec![ty_tp(Float)]), float_sub);
let mut float_mul = Self::builtin_methods("Mul", 2);
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);
float.register_trait(Float, builtin_poly("Mul", vec![ty_tp(Float)]), float_mul);
let mut float_div = Self::builtin_methods("Div", 2);
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);
float.register_trait(Float, builtin_poly("Div", vec![ty_tp(Float)]), float_div);
let mut float_mutizable = Self::builtin_methods("Mutizable", 2);
float_mutizable
.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Float!")));
@ -448,31 +458,31 @@ impl Context {
);
ratio.register_trait(
Ratio,
poly("PartialOrd", vec![ty_tp(Ratio)]),
builtin_poly("PartialOrd", vec![ty_tp(Ratio)]),
ratio_partial_ord,
);
let mut ratio_eq = Self::builtin_methods("Eq", 2);
ratio_eq.register_builtin_impl("__eq__", fn1_met(Ratio, Ratio, Bool), Const, Public);
ratio.register_trait(Ratio, poly("Eq", vec![ty_tp(Ratio)]), ratio_eq);
ratio.register_trait(Ratio, builtin_poly("Eq", vec![ty_tp(Ratio)]), ratio_eq);
let op_t = fn1_met(Ratio, Ratio, Ratio);
let mut ratio_add = Self::builtin_methods("Add", 2);
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);
ratio.register_trait(Ratio, builtin_poly("Add", vec![ty_tp(Ratio)]), ratio_add);
let mut ratio_sub = Self::builtin_methods("Sub", 2);
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);
ratio.register_trait(Ratio, builtin_poly("Sub", vec![ty_tp(Ratio)]), ratio_sub);
let mut ratio_mul = Self::builtin_methods("Mul", 2);
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);
ratio.register_trait(Ratio, builtin_poly("Mul", vec![ty_tp(Ratio)]), ratio_mul);
let mut ratio_div = Self::builtin_methods("Div", 2);
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);
ratio.register_trait(Ratio, builtin_poly("Div", vec![ty_tp(Ratio)]), ratio_div);
let mut ratio_mutizable = Self::builtin_methods("Mutizable", 2);
ratio_mutizable
.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Ratio!")));
@ -482,7 +492,7 @@ impl Context {
int.register_superclass(Obj, &obj);
int.register_marker_trait(builtin_mono("Num"));
int.register_marker_trait(builtin_mono("Ord"));
int.register_marker_trait(poly("Eq", vec![ty_tp(Int)]));
int.register_marker_trait(builtin_poly("Eq", vec![ty_tp(Int)]));
// class("Rational"),
// class("Integral"),
int.register_builtin_impl("abs", fn0_met(Int, Nat), Immutable, Public);
@ -493,25 +503,29 @@ impl Context {
Const,
Public,
);
int.register_trait(Int, poly("PartialOrd", vec![ty_tp(Int)]), int_partial_ord);
int.register_trait(
Int,
builtin_poly("PartialOrd", vec![ty_tp(Int)]),
int_partial_ord,
);
let mut int_eq = Self::builtin_methods("Eq", 2);
int_eq.register_builtin_impl("__eq__", fn1_met(Int, Int, Bool), Const, Public);
int.register_trait(Int, poly("Eq", vec![ty_tp(Int)]), int_eq);
int.register_trait(Int, builtin_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::builtin_methods("Add", 2);
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);
int.register_trait(Int, builtin_poly("Add", vec![ty_tp(Int)]), int_add);
let mut int_sub = Self::builtin_methods("Sub", 2);
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);
int.register_trait(Int, builtin_poly("Sub", vec![ty_tp(Int)]), int_sub);
let mut int_mul = Self::builtin_methods("Mul", 2);
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);
int.register_trait(Int, builtin_poly("Mul", vec![ty_tp(Int)]), int_mul);
let mut int_mutizable = Self::builtin_methods("Mutizable", 2);
int_mutizable.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Int!")));
int.register_trait(Int, builtin_mono("Mutizable"), int_mutizable);
@ -539,7 +553,7 @@ impl Context {
nat.register_marker_trait(builtin_mono("Ord"));
let mut nat_eq = Self::builtin_methods("Eq", 2);
nat_eq.register_builtin_impl("__eq__", fn1_met(Nat, Nat, Bool), Const, Public);
nat.register_trait(Nat, poly("Eq", vec![ty_tp(Nat)]), nat_eq);
nat.register_trait(Nat, builtin_poly("Eq", vec![ty_tp(Nat)]), nat_eq);
let mut nat_partial_ord = Self::builtin_methods("PartialOrd", 2);
nat_partial_ord.register_builtin_impl(
"__cmp__",
@ -547,17 +561,21 @@ impl Context {
Const,
Public,
);
nat.register_trait(Nat, poly("PartialOrd", vec![ty_tp(Nat)]), nat_partial_ord);
nat.register_trait(
Nat,
builtin_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::builtin_methods("Add", 2);
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);
nat.register_trait(Nat, builtin_poly("Add", vec![ty_tp(Nat)]), nat_add);
let mut nat_mul = Self::builtin_methods("Mul", 2);
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);
nat.register_trait(Nat, builtin_poly("Mul", vec![ty_tp(Nat)]), nat_mul);
let mut nat_mutizable = Self::builtin_methods("Mutizable", 2);
nat_mutizable.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Nat!")));
nat.register_trait(Nat, builtin_mono("Mutizable"), nat_mutizable);
@ -584,16 +602,16 @@ impl Context {
);
bool_.register_trait(
Bool,
poly("PartialOrd", vec![ty_tp(Bool)]),
builtin_poly("PartialOrd", vec![ty_tp(Bool)]),
bool_partial_ord,
);
let mut bool_eq = Self::builtin_methods("Eq", 2);
bool_eq.register_builtin_impl("__eq__", fn1_met(Bool, Bool, Bool), Const, Public);
bool_.register_trait(Bool, poly("Eq", vec![ty_tp(Bool)]), bool_eq);
bool_.register_trait(Bool, builtin_poly("Eq", vec![ty_tp(Bool)]), bool_eq);
let mut bool_add = Self::builtin_methods("Add", 2);
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);
bool_.register_trait(Bool, builtin_poly("Add", vec![ty_tp(Bool)]), bool_add);
let mut bool_mutizable = Self::builtin_methods("Mutizable", 2);
bool_mutizable
.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Bool!")));
@ -627,19 +645,19 @@ impl Context {
);
let mut str_eq = Self::builtin_methods("Eq", 2);
str_eq.register_builtin_impl("__eq__", fn1_met(Str, Str, Bool), Const, Public);
str_.register_trait(Str, poly("Eq", vec![ty_tp(Str)]), str_eq);
str_.register_trait(Str, builtin_poly("Eq", vec![ty_tp(Str)]), str_eq);
let mut str_seq = Self::builtin_methods("Seq", 2);
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);
str_.register_trait(Str, builtin_poly("Seq", vec![ty_tp(Str)]), str_seq);
let mut str_add = Self::builtin_methods("Add", 2);
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);
str_.register_trait(Str, builtin_poly("Add", vec![ty_tp(Str)]), str_add);
let mut str_mul = Self::builtin_methods("Mul", 2);
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);
str_.register_trait(Str, builtin_poly("Mul", vec![ty_tp(Nat)]), str_mul);
let mut str_mutizable = Self::builtin_methods("Mutizable", 2);
str_mutizable.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Str!")));
str_.register_trait(Str, builtin_mono("Mutizable"), str_mutizable);
@ -649,24 +667,37 @@ impl Context {
type_.register_marker_trait(builtin_mono("Named"));
let mut type_eq = Self::builtin_methods("Eq", 2);
type_eq.register_builtin_impl("__eq__", fn1_met(Type, Type, Bool), Const, Public);
type_.register_trait(Type, poly("Eq", vec![ty_tp(Type)]), type_eq);
type_.register_trait(Type, builtin_poly("Eq", vec![ty_tp(Type)]), type_eq);
let mut class_type = Self::builtin_mono_class("ClassType", 2);
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::builtin_methods("Eq", 2);
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::builtin_mono_class("Module", 2);
module.register_superclass(Obj, &obj);
module.register_marker_trait(builtin_mono("Named"));
let mut module_eq = Self::builtin_methods("Eq", 2);
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);
class_type.register_trait(Class, builtin_poly("Eq", vec![ty_tp(Class)]), class_eq);
let g_module_t = builtin_mono("GenericModule");
let mut generic_module = Self::builtin_mono_class("GenericModule", 2);
generic_module.register_superclass(Obj, &obj);
generic_module.register_marker_trait(builtin_mono("Named"));
let mut generic_module_eq = Self::builtin_methods("Eq", 2);
generic_module_eq.register_builtin_impl(
"__eq__",
fn1_met(g_module_t.clone(), g_module_t.clone(), Bool),
Const,
Public,
);
generic_module.register_trait(
g_module_t.clone(),
builtin_poly("Eq", vec![ty_tp(g_module_t.clone())]),
generic_module_eq,
);
let module_t = module(mono_q_tp("Path"));
let mut module = Self::builtin_poly_class("Module", vec![PS::named_nd("Path", Str)], 2);
module.register_superclass(g_module_t.clone(), &generic_module);
let mut array_ =
Self::builtin_poly_class("Array", vec![PS::t_nd("T"), PS::named_nd("N", Nat)], 10);
array_.register_superclass(Obj, &obj);
array_.register_marker_trait(poly("Output", vec![ty_tp(mono_q("T"))]));
array_.register_marker_trait(builtin_poly("Output", vec![ty_tp(mono_q("T"))]));
let n = mono_q_tp("N");
let m = mono_q_tp("M");
let array_t = array(mono_q("T"), n.clone());
@ -682,7 +713,7 @@ impl Context {
set! {static_instance("N", Nat), static_instance("M", Nat)},
);
array_.register_builtin_impl("concat", t, Immutable, Public);
let mut_type = ValueObj::builtin_t(poly(
let mut_type = ValueObj::builtin_t(builtin_poly(
"Array!",
vec![TyParam::t(mono_q("T")), TyParam::mono_q("N").mutate()],
));
@ -695,9 +726,13 @@ impl Context {
Const,
Public,
);
array_.register_trait(array_t.clone(), poly("Eq", vec![ty_tp(array_t)]), array_eq);
array_.register_trait(
array_t.clone(),
builtin_poly("Eq", vec![ty_tp(array_t)]),
array_eq,
);
array_.register_marker_trait(builtin_mono("Mutizable"));
array_.register_marker_trait(poly("Seq", vec![ty_tp(mono_q("T"))]));
array_.register_marker_trait(builtin_poly("Seq", vec![ty_tp(mono_q("T"))]));
// TODO: make Tuple6, Tuple7, ... etc.
let mut tuple_ = Self::builtin_mono_class("Tuple", 2);
tuple_.register_superclass(Obj, &obj);
@ -710,7 +745,7 @@ impl Context {
);
tuple_.register_trait(
builtin_mono("Tuple"),
poly("Eq", vec![ty_tp(builtin_mono("Tuple"))]),
builtin_poly("Eq", vec![ty_tp(builtin_mono("Tuple"))]),
tuple_eq,
);
let mut tuple1 = Self::builtin_poly_class("Tuple1", vec![PS::t_nd("A")], 2);
@ -720,16 +755,19 @@ impl Context {
tuple1_eq.register_builtin_impl(
"__eq__",
fn1_met(
poly("Tuple1", vec![ty_tp(mono_q("A"))]),
poly("Tuple1", vec![ty_tp(mono_q("A"))]),
builtin_poly("Tuple1", vec![ty_tp(mono_q("A"))]),
builtin_poly("Tuple1", vec![ty_tp(mono_q("A"))]),
Bool,
),
Const,
Public,
);
tuple1.register_trait(
poly("Tuple1", vec![ty_tp(mono_q("A"))]),
poly("Eq", vec![ty_tp(poly("Tuple1", vec![ty_tp(mono_q("A"))]))]),
builtin_poly("Tuple1", vec![ty_tp(mono_q("A"))]),
builtin_poly(
"Eq",
vec![ty_tp(builtin_poly("Tuple1", vec![ty_tp(mono_q("A"))]))],
),
tuple1_eq,
);
let mut tuple2 = Self::builtin_poly_class("Tuple2", vec![PS::t_nd("A"), PS::t_nd("B")], 2);
@ -739,18 +777,18 @@ impl Context {
tuple2_eq.register_builtin_impl(
"__eq__",
fn1_met(
poly("Tuple2", vec![ty_tp(mono_q("A")), ty_tp(mono_q("B"))]),
poly("Tuple2", vec![ty_tp(mono_q("A")), ty_tp(mono_q("B"))]),
builtin_poly("Tuple2", vec![ty_tp(mono_q("A")), ty_tp(mono_q("B"))]),
builtin_poly("Tuple2", vec![ty_tp(mono_q("A")), ty_tp(mono_q("B"))]),
Bool,
),
Const,
Public,
);
tuple2.register_trait(
poly("Tuple2", vec![ty_tp(mono_q("A")), ty_tp(mono_q("B"))]),
poly(
builtin_poly("Tuple2", vec![ty_tp(mono_q("A")), ty_tp(mono_q("B"))]),
builtin_poly(
"Eq",
vec![ty_tp(poly(
vec![ty_tp(builtin_poly(
"Tuple2",
vec![ty_tp(mono_q("A")), ty_tp(mono_q("B"))],
))],
@ -768,11 +806,11 @@ impl Context {
tuple3_eq.register_builtin_impl(
"__eq__",
fn1_met(
poly(
builtin_poly(
"Tuple3",
vec![ty_tp(mono_q("A")), ty_tp(mono_q("B")), ty_tp(mono_q("C"))],
),
poly(
builtin_poly(
"Tuple3",
vec![ty_tp(mono_q("A")), ty_tp(mono_q("B")), ty_tp(mono_q("C"))],
),
@ -782,13 +820,13 @@ impl Context {
Public,
);
tuple3.register_trait(
poly(
builtin_poly(
"Tuple3",
vec![ty_tp(mono_q("A")), ty_tp(mono_q("B")), ty_tp(mono_q("C"))],
),
poly(
builtin_poly(
"Eq",
vec![ty_tp(poly(
vec![ty_tp(builtin_poly(
"Tuple3",
vec![ty_tp(mono_q("A")), ty_tp(mono_q("B")), ty_tp(mono_q("C"))],
))],
@ -806,7 +844,7 @@ impl Context {
tuple4_eq.register_builtin_impl(
"__eq__",
fn1_met(
poly(
builtin_poly(
"Tuple4",
vec![
ty_tp(mono_q("A")),
@ -815,7 +853,7 @@ impl Context {
ty_tp(mono_q("D")),
],
),
poly(
builtin_poly(
"Tuple4",
vec![
ty_tp(mono_q("A")),
@ -830,7 +868,7 @@ impl Context {
Public,
);
tuple4.register_trait(
poly(
builtin_poly(
"Tuple4",
vec![
ty_tp(mono_q("A")),
@ -839,9 +877,9 @@ impl Context {
ty_tp(mono_q("D")),
],
),
poly(
builtin_poly(
"Eq",
vec![ty_tp(poly(
vec![ty_tp(builtin_poly(
"Tuple4",
vec![
ty_tp(mono_q("A")),
@ -870,7 +908,7 @@ impl Context {
tuple5_eq.register_builtin_impl(
"__eq__",
fn1_met(
poly(
builtin_poly(
"Tuple5",
vec![
ty_tp(mono_q("A")),
@ -880,7 +918,7 @@ impl Context {
ty_tp(mono_q("E")),
],
),
poly(
builtin_poly(
"Tuple5",
vec![
ty_tp(mono_q("A")),
@ -896,7 +934,7 @@ impl Context {
Public,
);
tuple5.register_trait(
poly(
builtin_poly(
"Tuple5",
vec![
ty_tp(mono_q("A")),
@ -906,9 +944,9 @@ impl Context {
ty_tp(mono_q("E")),
],
),
poly(
builtin_poly(
"Eq",
vec![ty_tp(poly(
vec![ty_tp(builtin_poly(
"Tuple5",
vec![
ty_tp(mono_q("A")),
@ -939,7 +977,7 @@ impl Context {
tuple6_eq.register_builtin_impl(
"__eq__",
fn1_met(
poly(
builtin_poly(
"Tuple6",
vec![
ty_tp(mono_q("A")),
@ -950,7 +988,7 @@ impl Context {
ty_tp(mono_q("F")),
],
),
poly(
builtin_poly(
"Tuple6",
vec![
ty_tp(mono_q("A")),
@ -967,7 +1005,7 @@ impl Context {
Public,
);
tuple6.register_trait(
poly(
builtin_poly(
"Tuple6",
vec![
ty_tp(mono_q("A")),
@ -978,9 +1016,9 @@ impl Context {
ty_tp(mono_q("F")),
],
),
poly(
builtin_poly(
"Eq",
vec![ty_tp(poly(
vec![ty_tp(builtin_poly(
"Tuple6",
vec![
ty_tp(mono_q("A")),
@ -1013,7 +1051,7 @@ impl Context {
tuple7_eq.register_builtin_impl(
"__eq__",
fn1_met(
poly(
builtin_poly(
"Tuple7",
vec![
ty_tp(mono_q("A")),
@ -1025,7 +1063,7 @@ impl Context {
ty_tp(mono_q("G")),
],
),
poly(
builtin_poly(
"Tuple7",
vec![
ty_tp(mono_q("A")),
@ -1043,7 +1081,7 @@ impl Context {
Public,
);
tuple7.register_trait(
poly(
builtin_poly(
"Tuple7",
vec![
ty_tp(mono_q("A")),
@ -1055,9 +1093,9 @@ impl Context {
ty_tp(mono_q("G")),
],
),
poly(
builtin_poly(
"Eq",
vec![ty_tp(poly(
vec![ty_tp(builtin_poly(
"Tuple7",
vec![
ty_tp(mono_q("A")),
@ -1092,7 +1130,7 @@ impl Context {
tuple8_eq.register_builtin_impl(
"__eq__",
fn1_met(
poly(
builtin_poly(
"Tuple8",
vec![
ty_tp(mono_q("A")),
@ -1105,7 +1143,7 @@ impl Context {
ty_tp(mono_q("H")),
],
),
poly(
builtin_poly(
"Tuple8",
vec![
ty_tp(mono_q("A")),
@ -1124,7 +1162,7 @@ impl Context {
Public,
);
tuple8.register_trait(
poly(
builtin_poly(
"Tuple8",
vec![
ty_tp(mono_q("A")),
@ -1137,9 +1175,9 @@ impl Context {
ty_tp(mono_q("H")),
],
),
poly(
builtin_poly(
"Eq",
vec![ty_tp(poly(
vec![ty_tp(builtin_poly(
"Tuple8",
vec![
ty_tp(mono_q("A")),
@ -1289,8 +1327,8 @@ impl Context {
builtin_mono("Mutable"),
str_mut_mutable,
);
let array_t = poly("Array", vec![ty_tp(mono_q("T")), mono_q_tp("N")]);
let array_mut_t = poly("Array!", vec![ty_tp(mono_q("T")), mono_q_tp("N")]);
let array_t = builtin_poly("Array", vec![ty_tp(mono_q("T")), mono_q_tp("N")]);
let array_mut_t = builtin_poly("Array!", vec![ty_tp(mono_q("T")), mono_q_tp("N")]);
let mut array_mut_ = Self::builtin_poly_class(
"Array!",
vec![PS::t_nd("T"), PS::named_nd("N", builtin_mono("Nat!"))],
@ -1301,7 +1339,7 @@ impl Context {
let t = pr_met(
ref_mut(
array_mut_t.clone(),
Some(poly(
Some(builtin_poly(
"Array!",
vec![ty_tp(mono_q("T")), mono_q_tp("N") + value(1)],
)),
@ -1354,10 +1392,10 @@ impl Context {
builtin_mono("Mutable"),
array_mut_mutable,
);
let range_t = poly("Range", vec![TyParam::t(mono_q("T"))]);
let range_t = builtin_poly("Range", vec![TyParam::t(mono_q("T"))]);
let mut range = Self::builtin_poly_class("Range", vec![PS::t_nd("T")], 2);
range.register_superclass(Obj, &obj);
range.register_marker_trait(poly("Output", vec![ty_tp(mono_q("T"))]));
range.register_marker_trait(builtin_poly("Output", vec![ty_tp(mono_q("T"))]));
let mut range_eq = Self::builtin_methods("Eq", 2);
range_eq.register_builtin_impl(
"__eq__",
@ -1367,7 +1405,7 @@ impl Context {
);
range.register_trait(
range_t.clone(),
poly("Eq", vec![ty_tp(range_t.clone())]),
builtin_poly("Eq", vec![ty_tp(range_t.clone())]),
range_eq,
);
let mut proc = Self::builtin_mono_class("Proc", 2);
@ -1392,7 +1430,8 @@ impl Context {
self.register_builtin_type(Str, str_, Const);
self.register_builtin_type(Type, type_, Const);
self.register_builtin_type(Class, class_type, Const);
self.register_builtin_type(Module, module, Const);
self.register_builtin_type(g_module_t, generic_module, Const);
self.register_builtin_type(module_t, module, Const);
self.register_builtin_type(array_t, array_, Const);
self.register_builtin_type(tuple(vec![mono_q("A")]), tuple1, Const);
self.register_builtin_type(tuple(vec![mono_q("A"), mono_q("B")]), tuple2, Const);
@ -1504,7 +1543,12 @@ impl Context {
option(mono_q("T")),
);
let t_if = quant(t_if, set! {static_instance("T", Type)});
let t_import = nd_func(vec![param_t("path", Str)], None, Module);
let t_import = nd_func(
vec![anon(tp_enum(Str, set! {mono_q_tp("Path")}))],
None,
module(mono_q_tp("Path")),
);
let t_import = quant(t_import, set! {static_instance("Path", Str)});
let t_log = func(
vec![],
Some(param_t("objects", ref_(Obj))),
@ -1516,7 +1560,12 @@ impl Context {
],
NoneType,
);
let t_pyimport = nd_func(vec![param_t("path", Str)], None, Module);
let t_pyimport = nd_func(
vec![anon(tp_enum(Str, set! {mono_q_tp("Path")}))],
None,
module(mono_q_tp("Path")),
);
let t_pyimport = quant(t_pyimport, set! {static_instance("Path", Str)});
let t_quit = func(vec![], None, vec![param_t("code", Int)], NoneType);
self.register_builtin_impl("abs", t_abs, Immutable, Private);
self.register_builtin_impl("assert", t_assert, Const, Private); // assert casting に悪影響が出る可能性があるため、Constとしておく
@ -1658,7 +1707,7 @@ impl Context {
op_t,
set! {
static_instance("R", Type),
subtypeof(l.clone(), poly("Add", params.clone()))
subtypeof(l.clone(), builtin_poly("Add", params.clone()))
},
);
self.register_builtin_impl("__add__", op_t, Const, Private);
@ -1667,7 +1716,7 @@ impl Context {
op_t,
set! {
static_instance("R", Type),
subtypeof(l.clone(), poly("Sub", params.clone()))
subtypeof(l.clone(), builtin_poly("Sub", params.clone()))
},
);
self.register_builtin_impl("__sub__", op_t, Const, Private);
@ -1676,7 +1725,7 @@ impl Context {
op_t,
set! {
static_instance("R", Type),
subtypeof(l.clone(), poly("Mul", params.clone()))
subtypeof(l.clone(), builtin_poly("Mul", params.clone()))
},
);
self.register_builtin_impl("__mul__", op_t, Const, Private);
@ -1685,22 +1734,22 @@ impl Context {
op_t,
set! {
static_instance("R", Type),
subtypeof(l.clone(), poly("Div", params.clone()))
subtypeof(l.clone(), builtin_poly("Div", params.clone()))
},
);
self.register_builtin_impl("__div__", op_t, Const, Private);
let m = mono_q("M");
let op_t = bin_op(m.clone(), m.clone(), mono_proj(m.clone(), "PowOutput"));
let op_t = quant(op_t, set! {subtypeof(m, poly("Mul", vec![]))});
let op_t = quant(op_t, set! {subtypeof(m, builtin_poly("Mul", vec![]))});
// TODO: add bound: M == M.Output
self.register_builtin_impl("__pow__", op_t, Const, Private);
let d = mono_q("D");
let op_t = bin_op(d.clone(), d.clone(), mono_proj(d.clone(), "ModOutput"));
let op_t = quant(op_t, set! {subtypeof(d, poly("Div", vec![]))});
let op_t = quant(op_t, set! {subtypeof(d, builtin_poly("Div", vec![]))});
self.register_builtin_impl("__mod__", op_t, Const, Private);
let e = mono_q("E");
let op_t = bin_op(e.clone(), e.clone(), Bool);
let op_t = quant(op_t, set! {subtypeof(e, poly("Eq", vec![]))});
let op_t = quant(op_t, set! {subtypeof(e, builtin_poly("Eq", vec![]))});
self.register_builtin_impl("__eq__", op_t.clone(), Const, Private);
self.register_builtin_impl("__ne__", op_t, Const, Private);
let op_t = bin_op(l.clone(), r, Bool);
@ -1708,7 +1757,7 @@ impl Context {
op_t,
set! {
static_instance("R", Type),
subtypeof(l, poly("PartialOrd", params))
subtypeof(l, builtin_poly("PartialOrd", params))
},
);
self.register_builtin_impl("__lt__", op_t.clone(), Const, Private);
@ -1728,7 +1777,7 @@ impl Context {
let op_t = bin_op(mono_q("T"), mono_q("I"), Bool);
let op_t = quant(
op_t,
set! { static_instance("T", Type), subtypeof(mono_q("I"), poly("In", vec![ty_tp(mono_q("T"))])) },
set! { static_instance("T", Type), subtypeof(mono_q("I"), builtin_poly("In", vec![ty_tp(mono_q("T"))])) },
);
self.register_builtin_impl("__in__", op_t, Const, Private);
/* unary */
@ -1772,7 +1821,7 @@ impl Context {
);
interval.register_trait(
Type::from(&m..=&n),
poly("Add", vec![TyParam::from(&o..=&p)]),
builtin_poly("Add", vec![TyParam::from(&o..=&p)]),
interval_add,
);
let mut interval_sub = Self::builtin_methods("Sub", 2);
@ -1788,7 +1837,7 @@ impl Context {
);
interval.register_trait(
Type::from(&m..=&n),
poly("Sub", vec![TyParam::from(&o..=&p)]),
builtin_poly("Sub", vec![TyParam::from(&o..=&p)]),
interval_sub,
);
self.register_builtin_patch("Interval", interval, Const);
@ -1800,7 +1849,7 @@ impl Context {
pub(crate) fn init_builtins(mod_cache: &SharedModuleCache) {
// TODO: capacityを正確に把握する
let mut ctx = Context::module("<builtins>".into(), ErgConfig::default(), None, None, 40);
let mut ctx = Context::builtin_module("<builtins>", 40);
ctx.init_builtin_funcs();
ctx.init_builtin_const_funcs();
ctx.init_builtin_procs();
@ -1808,7 +1857,7 @@ impl Context {
ctx.init_builtin_traits();
ctx.init_builtin_classes();
ctx.init_builtin_patches();
mod_cache.register(VarName::from_static("<builtins>"), None, ctx);
mod_cache.register(PathBuf::from("<builtins>"), None, ctx);
}
pub fn new_module<S: Into<Str>>(

View file

@ -1,6 +1,6 @@
use erg_common::vis::Visibility;
use erg_type::constructors::proc1;
use erg_type::constructors::{builtin_mono, proc1};
use erg_type::Type;
use Type::*;
@ -12,7 +12,12 @@ use Visibility::*;
impl Context {
pub(crate) fn init_py_importlib_mod() -> Self {
let mut importlib = Context::builtin_module("importlib", 15);
importlib.register_builtin_impl("reload!", proc1(Module, NoneType), Immutable, Public);
importlib.register_builtin_impl(
"reload!",
proc1(builtin_mono("GenericModule"), NoneType),
Immutable,
Public,
);
importlib
}
}

View file

@ -2,7 +2,7 @@ use erg_common::set;
use erg_common::vis::Visibility;
use erg_type::constructors::{
builtin_mono, mono_q, nd_proc, param_t, poly, proc, quant, static_instance, ty_tp,
builtin_mono, builtin_poly, mono_q, nd_proc, param_t, proc, quant, static_instance, ty_tp,
};
use erg_type::Type;
use Type::*;
@ -36,7 +36,10 @@ impl Context {
Public,
);
let t = nd_proc(
vec![param_t("seq", poly("Seq", vec![ty_tp(mono_q("T"))]))],
vec![param_t(
"seq",
builtin_poly("Seq", vec![ty_tp(mono_q("T"))]),
)],
None,
mono_q("T"),
);

View file

@ -1,20 +1,23 @@
// (type) getters & validators
use std::option::Option; // conflicting to Type::Option
use std::path::{Path, PathBuf};
use erg_common::config::Input;
use erg_common::error::{ErrorCore, ErrorKind, Location};
use erg_common::levenshtein::get_similar_name;
use erg_common::set::Set;
use erg_common::traits::{Locational, Stream};
use erg_common::vis::{Field, Visibility};
use erg_common::Str;
use erg_common::{enum_unwrap, fmt_option, fmt_slice, log, set};
use erg_common::{option_enum_unwrap, Str};
use Type::*;
use ast::VarName;
use erg_parser::ast::{self, Identifier};
use erg_parser::token::Token;
use erg_type::constructors::{builtin_mono, func, mono, mono_proj};
use erg_type::constructors::{builtin_mono, func, module, mono, mono_proj, v_enum};
use erg_type::typaram::TyParam;
use erg_type::value::{GenTypeObj, TypeObj, ValueObj};
use erg_type::{HasType, ParamTy, SubrKind, SubrType, TyBound, Type};
@ -86,21 +89,15 @@ impl Context {
self.locals.get_key_value(name)
}
fn get_singular_ctx(&self, obj: &hir::Expr, namespace: &Str) -> SingleTyCheckResult<&Context> {
pub fn get_singular_ctx(
&self,
obj: &hir::Expr,
namespace: &Str,
) -> SingleTyCheckResult<&Context> {
match obj {
hir::Expr::Accessor(hir::Accessor::Ident(ident)) => self
.get_mod(ident.inspect())
.or_else(|| self.rec_get_type(ident.inspect()).map(|(_, ctx)| ctx))
.ok_or_else(|| {
TyCheckError::no_var_error(
self.cfg.input.clone(),
line!() as usize,
obj.loc(),
namespace.into(),
ident.inspect(),
self.get_similar_name(ident.inspect()),
)
}),
hir::Expr::Accessor(hir::Accessor::Ident(ident)) => {
self.get_singular_ctx_from_ident(&ident.clone().downcast(), namespace)
}
hir::Expr::Accessor(hir::Accessor::Attr(attr)) => {
// REVIEW: 両方singularとは限らない?
let ctx = self.get_singular_ctx(&attr.obj, namespace)?;
@ -111,6 +108,25 @@ impl Context {
}
}
pub fn get_singular_ctx_from_ident(
&self,
ident: &ast::Identifier,
namespace: &Str,
) -> SingleTyCheckResult<&Context> {
self.get_mod(ident)
.or_else(|| self.rec_get_type(ident.inspect()).map(|(_, ctx)| ctx))
.ok_or_else(|| {
TyCheckError::no_var_error(
self.cfg.input.clone(),
line!() as usize,
ident.loc(),
namespace.into(),
ident.inspect(),
self.get_similar_name(ident.inspect()),
)
})
}
fn get_match_call_t(
&self,
pos_args: &[hir::PosArg],
@ -197,31 +213,74 @@ impl Context {
Ok(t)
}
pub(crate) fn get_local_uniq_obj_name(&self, name: &VarName) -> Option<Str> {
// TODO: types, functions, patches
if let Some(ctx) = self.get_mod(name.inspect()) {
return Some(ctx.name.clone());
fn get_import_call_t(
&self,
pos_args: &[hir::PosArg],
kw_args: &[hir::KwArg],
) -> TyCheckResult<Type> {
let mod_name = pos_args
.get(0)
.map(|a| &a.expr)
.or_else(|| {
kw_args
.iter()
.find(|k| &k.keyword.inspect()[..] == "Path")
.map(|a| &a.expr)
})
.unwrap();
let path = match mod_name {
hir::Expr::Lit(lit) => {
if self.subtype_of(&lit.value.class(), &Str) {
enum_unwrap!(&lit.value, ValueObj::Str)
} else {
return Err(TyCheckErrors::from(TyCheckError::type_mismatch_error(
self.cfg.input.clone(),
line!() as usize,
mod_name.loc(),
self.caused_by(),
"import::name",
&Str,
mod_name.ref_t(),
self.get_candidates(mod_name.ref_t()),
self.get_type_mismatch_hint(&Str, mod_name.ref_t()),
)));
}
if let Some((_, ctx)) = self.rec_get_type(name.inspect()) {
return Some(ctx.name.clone());
}
None
_other => {
return Err(TyCheckErrors::from(TyCheckError::feature_error(
self.cfg.input.clone(),
mod_name.loc(),
"non-literal importing",
self.caused_by(),
)))
}
};
let path = PathBuf::from(&path[..]);
let s = ValueObj::Str(Str::rc(path.to_str().unwrap()));
let import_t = func(
vec![ParamTy::anonymous(v_enum(set! {s.clone()}))],
None,
vec![],
module(TyParam::Value(s)),
);
Ok(import_t)
}
pub(crate) fn rec_get_var_t(
&self,
ident: &Identifier,
input: &Input,
namespace: &Str,
) -> SingleTyCheckResult<Type> {
if let Some(vi) = self.get_current_scope_var(&ident.inspect()[..]) {
self.validate_visibility(ident, vi, namespace)?;
self.validate_visibility(ident, vi, input, namespace)?;
Ok(vi.t())
} else {
if let Some(parent) = self.get_outer().or_else(|| self.get_builtins()) {
return parent.rec_get_var_t(ident, namespace);
return parent.rec_get_var_t(ident, input, namespace);
}
Err(TyCheckError::no_var_error(
self.cfg.input.clone(),
input.clone(),
line!() as usize,
ident.loc(),
namespace.into(),
@ -235,11 +294,12 @@ impl Context {
&self,
obj: &hir::Expr,
ident: &Identifier,
input: &Input,
namespace: &Str,
) -> SingleTyCheckResult<Type> {
let self_t = obj.t();
let name = ident.name.token();
match self.get_attr_t_from_attributive_t(obj, &self_t, ident, namespace) {
match self.get_attr_t_from_attributive(obj, &self_t, ident, namespace) {
Ok(t) => {
return Ok(t);
}
@ -249,7 +309,7 @@ impl Context {
}
}
if let Ok(singular_ctx) = self.get_singular_ctx(obj, namespace) {
match singular_ctx.rec_get_var_t(ident, namespace) {
match singular_ctx.rec_get_var_t(ident, input, namespace) {
Ok(t) => {
return Ok(t);
}
@ -269,7 +329,7 @@ impl Context {
None, // TODO:
)
})? {
match ctx.rec_get_var_t(ident, namespace) {
match ctx.rec_get_var_t(ident, input, namespace) {
Ok(t) => {
return Ok(t);
}
@ -281,10 +341,10 @@ impl Context {
}
// TODO: dependent type widening
if let Some(parent) = self.get_outer().or_else(|| self.get_builtins()) {
parent.rec_get_attr_t(obj, ident, namespace)
parent.rec_get_attr_t(obj, ident, input, namespace)
} else {
Err(TyCheckError::no_attr_error(
self.cfg.input.clone(),
input.clone(),
line!() as usize,
name.loc(),
namespace.into(),
@ -295,7 +355,9 @@ impl Context {
}
}
fn get_attr_t_from_attributive_t(
/// get type from given attributive type (Record).
/// not ModuleType or ClassType etc.
fn get_attr_t_from_attributive(
&self,
obj: &hir::Expr,
t: &Type,
@ -304,18 +366,18 @@ impl Context {
) -> SingleTyCheckResult<Type> {
match t {
Type::FreeVar(fv) if fv.is_linked() => {
self.get_attr_t_from_attributive_t(obj, &fv.crack(), ident, namespace)
self.get_attr_t_from_attributive(obj, &fv.crack(), ident, namespace)
}
Type::FreeVar(fv) => {
let sup = fv.get_sup().unwrap();
self.get_attr_t_from_attributive_t(obj, &sup, ident, namespace)
self.get_attr_t_from_attributive(obj, &sup, ident, namespace)
}
Type::Ref(t) => self.get_attr_t_from_attributive_t(obj, t, ident, namespace),
Type::Ref(t) => self.get_attr_t_from_attributive(obj, t, ident, namespace),
Type::RefMut { before, .. } => {
self.get_attr_t_from_attributive_t(obj, before, ident, namespace)
self.get_attr_t_from_attributive(obj, before, ident, namespace)
}
Type::Refinement(refine) => {
self.get_attr_t_from_attributive_t(obj, &refine.t, ident, namespace)
self.get_attr_t_from_attributive(obj, &refine.t, ident, namespace)
}
Type::Record(record) => {
// REVIEW: `rec.get(name.inspect())` returns None (Borrow<Str> is implemented for Field). Why?
@ -334,11 +396,6 @@ impl Context {
))
}
}
Module => {
let mod_ctx = self.get_singular_ctx(obj, namespace)?;
let t = mod_ctx.rec_get_var_t(ident, namespace)?;
Ok(t)
}
other => {
if let Some(v) = self.rec_get_const_obj(&other.name()) {
match v {
@ -372,6 +429,7 @@ impl Context {
&self,
obj: &hir::Expr,
method_name: &Option<Identifier>,
input: &Input,
namespace: &Str,
) -> SingleTyCheckResult<Type> {
if let Some(method_name) = method_name.as_ref() {
@ -393,7 +451,7 @@ impl Context {
.get(method_name.inspect())
.or_else(|| ctx.decls.get(method_name.inspect()))
{
self.validate_visibility(method_name, vi, namespace)?;
self.validate_visibility(method_name, vi, input, namespace)?;
return Ok(vi.t());
}
for (_, methods_ctx) in ctx.methods_list.iter() {
@ -402,7 +460,7 @@ impl Context {
.get(method_name.inspect())
.or_else(|| methods_ctx.decls.get(method_name.inspect()))
{
self.validate_visibility(method_name, vi, namespace)?;
self.validate_visibility(method_name, vi, input, namespace)?;
return Ok(vi.t());
}
}
@ -413,7 +471,7 @@ impl Context {
.get(method_name.inspect())
.or_else(|| singular_ctx.decls.get(method_name.inspect()))
{
self.validate_visibility(method_name, vi, namespace)?;
self.validate_visibility(method_name, vi, input, namespace)?;
return Ok(vi.t());
}
for (_, method_ctx) in singular_ctx.methods_list.iter() {
@ -422,7 +480,7 @@ impl Context {
.get(method_name.inspect())
.or_else(|| method_ctx.decls.get(method_name.inspect()))
{
self.validate_visibility(method_name, vi, namespace)?;
self.validate_visibility(method_name, vi, input, namespace)?;
return Ok(vi.t());
}
}
@ -456,11 +514,12 @@ impl Context {
&self,
ident: &Identifier,
vi: &VarInfo,
input: &Input,
namespace: &str,
) -> SingleTyCheckResult<()> {
if ident.vis() != vi.vis {
Err(TyCheckError::visibility_error(
self.cfg.input.clone(),
input.clone(),
line!() as usize,
ident.loc(),
self.caused_by(),
@ -474,7 +533,7 @@ impl Context {
&& !namespace.contains(&self.name[..])
{
Err(TyCheckError::visibility_error(
self.cfg.input.clone(),
input.clone(),
line!() as usize,
ident.loc(),
self.caused_by(),
@ -490,6 +549,7 @@ impl Context {
&self,
op: &Token,
args: &[hir::PosArg],
input: &Input,
namespace: &Str,
) -> TyCheckResult<Type> {
erg_common::debug_power_assert!(args.len() == 2);
@ -497,10 +557,11 @@ impl Context {
let symbol = Token::new(op.kind, Str::rc(cont), op.lineno, op.col_begin);
let t = self.rec_get_var_t(
&Identifier::new(None, VarName::new(symbol.clone())),
input,
namespace,
)?;
let op = hir::Expr::Accessor(hir::Accessor::private(symbol, t));
self.get_call_t(&op, &None, args, &[], namespace)
self.get_call_t(&op, &None, args, &[], input, namespace)
.map_err(|errs| {
let op = enum_unwrap!(op, hir::Expr::Accessor:(hir::Accessor::Ident:(_)));
let lhs = args[0].expr.clone();
@ -528,6 +589,7 @@ impl Context {
&self,
op: &Token,
args: &[hir::PosArg],
input: &Input,
namespace: &Str,
) -> TyCheckResult<Type> {
erg_common::debug_power_assert!(args.len() == 1);
@ -535,10 +597,11 @@ impl Context {
let symbol = Token::new(op.kind, Str::rc(cont), op.lineno, op.col_begin);
let t = self.rec_get_var_t(
&Identifier::new(None, VarName::new(symbol.clone())),
input,
namespace,
)?;
let op = hir::Expr::Accessor(hir::Accessor::private(symbol, t));
self.get_call_t(&op, &None, args, &[], namespace)
self.get_call_t(&op, &None, args, &[], input, namespace)
.map_err(|errs| {
let op = enum_unwrap!(op, hir::Expr::Accessor:(hir::Accessor::Ident:(_)));
let expr = args[0].expr.clone();
@ -880,17 +943,34 @@ impl Context {
method_name: &Option<Identifier>,
pos_args: &[hir::PosArg],
kw_args: &[hir::KwArg],
input: &Input,
namespace: &Str,
) -> TyCheckResult<Type> {
match obj {
hir::Expr::Accessor(hir::Accessor::Ident(local))
if local.vis().is_private() && &local.inspect()[..] == "match" =>
{
if let hir::Expr::Accessor(hir::Accessor::Ident(local)) = obj {
if local.vis().is_private() {
match &local.inspect()[..] {
"match" => {
return self.get_match_call_t(pos_args, kw_args);
}
"import" | "pyimport" | "py" => {
return self.get_import_call_t(pos_args, kw_args);
}
// handle assert casting
/*"assert" => {
if let Some(arg) = pos_args.first() {
match &arg.expr {
hir::Expr::BinOp(bin) if bin.op.is(TokenKind::InOp) && bin.rhs.ref_t() == &Type => {
let t = self.eval_const_expr(bin.lhs.as_ref(), None)?.as_type().unwrap();
}
_ => {}
}
let found = self.search_callee_t(obj, method_name, namespace)?;
}
},*/
_ => {}
}
}
}
let found = self.search_callee_t(obj, method_name, input, namespace)?;
log!(
"Found:\ncallee: {obj}{}\nfound: {found}",
fmt_option!(pre ".", method_name.as_ref().map(|ident| &ident.name))
@ -1192,11 +1272,33 @@ impl Context {
}
}
},
Type::Poly { name, params: _ } => {
if let Some((t, ctx)) = self.rec_get_poly_type(name) {
Type::BuiltinPoly { name, .. } => {
if let Some(res) = self.get_builtins().unwrap_or(self).rec_get_poly_type(name) {
return Some(res);
}
}
Type::Poly { path, name, .. } => {
if self.path() == path {
if let Some((t, ctx)) = self.rec_get_mono_type(name) {
return Some((t, ctx));
}
}
let path = self.cfg.input.resolve(path.as_path()).ok()?;
if let Some(ctx) = self
.mod_cache
.as_ref()
.and_then(|cache| cache.ref_ctx(path.as_path()))
.or_else(|| {
self.py_mod_cache
.as_ref()
.and_then(|cache| cache.ref_ctx(path.as_path()))
})
{
if let Some((t, ctx)) = ctx.rec_get_mono_type(name) {
return Some((t, ctx));
}
}
}
Type::Record(rec) if rec.values().all(|attr| self.supertype_of(&Type, attr)) => {
return self
.get_builtins()
@ -1210,14 +1312,21 @@ impl Context {
.rec_get_mono_type("Record");
}
Type::Mono { path, name } => {
if self.mod_name() == path {
if self.path() == path {
if let Some((t, ctx)) = self.rec_get_mono_type(name) {
return Some((t, ctx));
}
} else if let Some(ctx) = self
}
let path = self.cfg.input.resolve(path.as_path()).ok()?;
if let Some(ctx) = self
.mod_cache
.as_ref()
.and_then(|cache| cache.ref_ctx(path))
.and_then(|cache| cache.ref_ctx(path.as_path()))
.or_else(|| {
self.py_mod_cache
.as_ref()
.and_then(|cache| cache.ref_ctx(path.as_path()))
})
{
if let Some((t, ctx)) = ctx.rec_get_mono_type(name) {
return Some((t, ctx));
@ -1274,7 +1383,7 @@ impl Context {
return Some(res);
}
}
Type::Poly { name, params: _ } => {
Type::BuiltinPoly { name, params: _ } => {
if let Some((t, ctx)) = self.rec_get_mut_poly_type(name) {
return Some((t, ctx));
}
@ -1327,16 +1436,28 @@ impl Context {
}
// FIXME: 現在の実装だとimportしたモジュールはどこからでも見れる
fn get_mod(&self, name: &Str) -> Option<&Context> {
fn get_mod(&self, ident: &ast::Identifier) -> Option<&Context> {
let t = self
.rec_get_var_t(ident, &self.cfg.input, &self.name)
.ok()?;
match t {
Type::BuiltinPoly { name, mut params } if &name[..] == "Module" => {
let path =
option_enum_unwrap!(params.remove(0), TyParam::Value:(ValueObj::Str:(_)))?;
let path = Path::new(&path[..]);
let path = self.cfg.input.resolve(path).ok()?;
self.mod_cache
.as_ref()
.and_then(|cache| cache.ref_ctx(name))
.and_then(|cache| cache.ref_ctx(&path))
.or_else(|| {
self.py_mod_cache
.as_ref()
.and_then(|cache| cache.ref_ctx(name))
.and_then(|cache| cache.ref_ctx(&path))
})
}
_ => None,
}
}
// rec_get_const_localとは違い、位置情報を持たないしエラーとならない
pub(crate) fn rec_get_const_obj(&self, name: &str) -> Option<&ValueObj> {
@ -1370,7 +1491,7 @@ impl Context {
if self.kind.is_method_def() || self.kind.is_type() {
// TODO: poly type
let name = self.name.split(&[':', '.']).last().unwrap();
let mono_t = mono(self.mod_name(), Str::rc(name));
let mono_t = mono(self.path(), Str::rc(name));
if let Some((t, _)) = self.get_nominal_type_ctx(&mono_t) {
Some(t.clone())
} else {

View file

@ -106,7 +106,7 @@ impl TyVarContext {
) -> Type {
if let Some(temp_defaults) = ctx.rec_get_const_param_defaults(name) {
let (_, ctx) = ctx
.get_nominal_type_ctx(&poly(name.clone(), params.clone()))
.get_nominal_type_ctx(&builtin_poly(name.clone(), params.clone()))
.unwrap_or_else(|| panic!("{} not found", name));
let defined_params_len = ctx.params.len();
let given_params_len = params.len();
@ -123,9 +123,9 @@ impl TyVarContext {
self.push_or_init_typaram(&tp.tvar_name().unwrap(), &tp);
inst_defaults.push(tp);
}
poly(name, [inst_non_defaults, inst_defaults].concat())
builtin_poly(name, [inst_non_defaults, inst_defaults].concat())
} else {
poly(name, self.instantiate_params(params))
builtin_poly(name, self.instantiate_params(params))
}
}
@ -146,7 +146,10 @@ impl TyVarContext {
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::Poly { .. } => todo!(),
Type::BuiltinPoly { name, params } => {
self.instantiate_poly(mid.name(), &name, params, ctx)
}
Type::MonoProj { lhs, rhs } => {
let lhs = if lhs.has_qvar() {
self.instantiate_qvar(*lhs)
@ -174,9 +177,10 @@ impl TyVarContext {
}
TyBound::Instance { name, t } => {
let t = match t {
Type::Poly { name, params } => {
Type::BuiltinPoly { name, params } => {
self.instantiate_poly(name.clone(), &name, params, ctx)
}
Type::Poly { .. } => todo!(),
t => t,
};
let constraint = Constraint::new_type_of(t.clone());
@ -385,7 +389,7 @@ impl Context {
mode: RegistrationMode,
) -> TyCheckResult<Type> {
let opt_decl_sig_t = self
.rec_get_var_t(&sig.ident, &self.name)
.rec_get_var_t(&sig.ident, &self.cfg.input, &self.name)
.ok()
.map(|t| enum_unwrap!(t, Type::Subr));
let bounds = self.instantiate_ty_bounds(&sig.bounds, PreRegister)?;
@ -453,7 +457,7 @@ impl Context {
self.instantiate_typespec(&spec_with_op.t_spec, opt_decl_t, tv_ctx, mode)?
} else {
match &sig.pat {
ast::ParamPattern::Lit(lit) => enum_t(set![eval_lit(lit)]),
ast::ParamPattern::Lit(lit) => v_enum(set![eval_lit(lit)]),
// TODO: Array<Lit>
_ => {
let level = if mode == PreRegister {
@ -528,7 +532,7 @@ impl Context {
} else if let Some(decl_t) = opt_decl_t {
Ok(decl_t.typ().clone())
} else {
let typ = mono(self.mod_name(), Str::rc(other));
let typ = mono(self.path(), Str::rc(other));
if let Some((defined_t, _)) = self.get_nominal_type_ctx(&typ) {
Ok(defined_t.clone())
} else {
@ -551,8 +555,8 @@ impl Context {
todo!()
}
});
// FIXME: if type is a trait
Ok(poly(Str::rc(other), params.collect()))
// FIXME: non-builtin
Ok(builtin_poly(Str::rc(other), params.collect()))
}
}
}
@ -573,7 +577,7 @@ impl Context {
) -> SingleTyCheckResult<Type> {
match expr {
ast::ConstExpr::Accessor(ast::ConstAccessor::Local(name)) => {
Ok(mono(self.mod_name(), name.inspect()))
Ok(mono(self.path(), name.inspect()))
}
_ => todo!(),
}
@ -632,7 +636,7 @@ impl Context {
.collect(),
)),
// TODO: エラー処理(リテラルでない、ダブりがある)はパーサーにやらせる
TypeSpec::Enum(set) => Ok(enum_t(
TypeSpec::Enum(set) => Ok(v_enum(
set.pos_args()
.map(|arg| {
if let ast::ConstExpr::Lit(lit) = &arg.expr {
@ -861,11 +865,21 @@ impl Context {
let lhs = self.instantiate_t(*lhs, tv_ctx, loc)?;
Ok(mono_proj(lhs, rhs))
}
Poly { name, mut params } => {
BuiltinPoly { name, mut params } => {
for param in params.iter_mut() {
*param = self.instantiate_tp(mem::take(param), tv_ctx, loc)?;
}
Ok(poly(name, params))
Ok(builtin_poly(name, params))
}
Poly {
path,
name,
mut params,
} => {
for param in params.iter_mut() {
*param = self.instantiate_tp(mem::take(param), tv_ctx, loc)?;
}
Ok(poly(path, name, params))
}
Quantified(_) => {
panic!("a quantified type should not be instantiated, instantiate the inner type")

View file

@ -16,6 +16,7 @@ pub mod tyvar;
use std::fmt;
use std::mem;
use std::option::Option; // conflicting to Type::Option
use std::path::Path;
use erg_common::astr::AtomicStr;
use erg_common::config::ErgConfig;
@ -288,6 +289,11 @@ impl ImportKind {
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ContextInfo {
mod_id: usize,
}
/// Represents the context of the current scope
///
/// Recursive functions/methods are highlighted with the prefix `rec_`, as performance may be significantly degraded.
@ -773,13 +779,13 @@ impl Context {
self.outer.as_ref().map(|x| x.as_ref())
}
pub(crate) fn mod_name(&self) -> &Str {
pub(crate) fn path(&self) -> &Path {
if let Some(outer) = self.get_outer() {
outer.mod_name()
outer.path()
} else if self.kind == ContextKind::Module {
&self.name
Path::new(&self.name[..])
} else {
BUILTINS
Path::new(&BUILTINS[..])
}
}
@ -787,10 +793,10 @@ impl Context {
/// This avoids infinite loops.
pub(crate) fn get_builtins(&self) -> Option<&Context> {
// builtins中で定義した型等はmod_cacheがNoneになっている
if &self.mod_name()[..] != "<builtins>" {
if self.path().to_string_lossy() != "<builtins>" {
self.mod_cache
.as_ref()
.map(|cache| cache.ref_ctx("<builtins>").unwrap())
.map(|cache| cache.ref_ctx(Path::new("<builtins>")).unwrap())
} else {
None
}
@ -809,6 +815,7 @@ impl Context {
};
log!(info "{}: current namespace: {name}", fn_name!());
self.outer = Some(Box::new(mem::take(self)));
self.cfg = self.get_outer().unwrap().cfg.clone();
self.mod_cache = self.get_outer().unwrap().mod_cache.clone();
self.py_mod_cache = self.get_outer().unwrap().py_mod_cache.clone();
self.name = name.into();

View file

@ -1,5 +1,5 @@
use std::option::Option;
use std::path::PathBuf; // conflicting to Type::Option
use std::path::PathBuf;
use erg_common::config::{ErgConfig, Input};
use erg_common::levenshtein::get_similar_name;
@ -12,10 +12,9 @@ use erg_type::free::HasLevel;
use ast::{DefId, Identifier, VarName};
use erg_parser::ast;
use erg_type::constructors::{enum_t, func, func1, proc, ref_, ref_mut};
use erg_type::constructors::{func, func1, proc, ref_, ref_mut, v_enum};
use erg_type::value::{GenTypeObj, TypeKind, TypeObj, ValueObj};
use erg_type::{HasType, ParamTy, SubrType, TyBound, Type};
use Type::*;
use erg_type::{ParamTy, SubrType, TyBound, Type};
use crate::build_hir::HIRBuilder;
use crate::context::{ClassDefType, Context, DefaultInfo, RegistrationMode, TraitInstance};
@ -23,7 +22,7 @@ use crate::error::readable_name;
use crate::error::{
CompileResult, SingleTyCheckResult, TyCheckError, TyCheckErrors, TyCheckResult,
};
use crate::hir::{self, Literal};
use crate::hir::Literal;
use crate::mod_cache::SharedModuleCache;
use crate::varinfo::{Mutability, ParamIdx, VarInfo, VarKind};
use Mutability::*;
@ -484,7 +483,7 @@ impl Context {
let bounds = self.instantiate_ty_bounds(&sig.bounds, PreRegister)?;
let mut tv_ctx = TyVarContext::new(self.level, bounds, self);
let (obj, const_t) = match self.eval_const_block(&def.body.block, __name__) {
Ok(obj) => (obj.clone(), enum_t(set! {obj})),
Ok(obj) => (obj.clone(), v_enum(set! {obj})),
Err(e) => {
return Err(e);
}
@ -505,7 +504,7 @@ impl Context {
}
ast::Signature::Var(sig) if sig.is_const() => {
let (obj, const_t) = match self.eval_const_block(&def.body.block, __name__) {
Ok(obj) => (obj.clone(), enum_t(set! {obj})),
Ok(obj) => (obj.clone(), v_enum(set! {obj})),
Err(e) => {
return Err(e);
}
@ -609,7 +608,7 @@ impl Context {
other => {
let id = DefId(get_hash(ident));
let vi = VarInfo::new(
enum_t(set! {other.clone()}),
v_enum(set! {other.clone()}),
Const,
ident.vis(),
VarKind::Defined(id),
@ -818,67 +817,33 @@ impl Context {
pub(crate) fn import_mod(
&mut self,
kind: ImportKind,
var_name: &VarName,
mod_name: &hir::Expr,
) -> CompileResult<()> {
match mod_name {
hir::Expr::Lit(lit) => {
if self.subtype_of(&lit.value.class(), &Str) {
mod_name: &Literal,
) -> CompileResult<PathBuf> {
if kind.is_erg_import() {
self.import_erg_mod(var_name, lit)?;
self.import_erg_mod(mod_name)
} else {
self.import_py_mod(var_name, lit)?;
self.import_py_mod(mod_name)
}
} else {
return Err(TyCheckErrors::from(TyCheckError::type_mismatch_error(
self.cfg.input.clone(),
line!() as usize,
mod_name.loc(),
self.caused_by(),
"import::name",
&Str,
mod_name.ref_t(),
self.get_candidates(mod_name.ref_t()),
self.get_type_mismatch_hint(&Str, mod_name.ref_t()),
)));
}
}
_other => {
return Err(TyCheckErrors::from(TyCheckError::feature_error(
self.cfg.input.clone(),
mod_name.loc(),
"non-literal importing",
self.caused_by(),
)))
}
}
Ok(())
}
fn import_erg_mod(&mut self, var_name: &VarName, lit: &Literal) -> CompileResult<()> {
let __name__ = enum_unwrap!(lit.value.clone(), ValueObj::Str);
fn import_erg_mod(&mut self, mod_name: &Literal) -> CompileResult<PathBuf> {
let __name__ = enum_unwrap!(mod_name.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(var_name, __name__, lit, mod_cache, py_mod_cache)?,
_ => self.import_user_erg_mod(__name__, mod_name, mod_cache, py_mod_cache),
}
Ok(())
}
fn import_user_erg_mod(
&self,
var_name: &VarName,
__name__: Str,
name_lit: &Literal,
mod_name: &Literal,
mod_cache: &SharedModuleCache,
py_mod_cache: &SharedModuleCache,
) -> CompileResult<()> {
if let Some((_, entry)) = mod_cache.get_by_name(&__name__) {
mod_cache.register_alias(var_name.clone(), entry);
return Ok(());
}
) -> CompileResult<PathBuf> {
let mut dir = if let Input::File(mut path) = self.cfg.input.clone() {
path.pop();
path
@ -893,7 +858,7 @@ impl Context {
self.cfg.input.clone(),
line!() as usize,
err.to_string(),
name_lit.loc(),
mod_name.loc(),
self.caused_by(),
self.mod_cache.as_ref().unwrap().get_similar_name(&__name__),
self.similar_builtin_py_mod_name(&__name__).or_else(|| {
@ -906,56 +871,68 @@ impl Context {
return Err(err);
}
};
let cfg = ErgConfig::with_path(path);
if mod_cache.get(&path).is_some() {
return Ok(path);
}
let cfg = ErgConfig::with_path(path.clone());
let src = cfg.input.read();
let mut builder = HIRBuilder::new_with_cache(
cfg,
var_name.inspect(),
mod_cache.clone(),
py_mod_cache.clone(),
);
let mut builder =
HIRBuilder::new_with_cache(cfg, __name__, 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());
mod_cache.register(path.clone(), Some(hir), builder.pop_ctx());
}
Err((maybe_hir, errs)) => {
if let Some(hir) = maybe_hir {
mod_cache.register(var_name.clone(), Some(hir), builder.pop_ctx());
mod_cache.register(path, Some(hir), builder.pop_ctx());
}
return Err(errs);
}
}
Ok(())
Ok(path)
}
fn import_py_mod(&mut self, var_name: &VarName, lit: &Literal) -> CompileResult<()> {
let __name__ = enum_unwrap!(lit.value.clone(), ValueObj::Str);
let mod_cache = self.mod_cache.as_ref().unwrap();
fn import_py_mod(&mut self, mod_name: &Literal) -> CompileResult<PathBuf> {
let __name__ = enum_unwrap!(mod_name.value.clone(), ValueObj::Str);
let py_mod_cache = self.py_mod_cache.as_ref().unwrap();
match &__name__[..] {
"importlib" => {
mod_cache.register(var_name.clone(), None, Self::init_py_importlib_mod());
let path = PathBuf::from("<builtins>.importlib");
py_mod_cache.register(path.clone(), None, Self::init_py_importlib_mod());
Ok(path)
}
"io" => {
mod_cache.register(var_name.clone(), None, Self::init_py_io_mod());
let path = PathBuf::from("<builtins>.io");
py_mod_cache.register(path.clone(), None, Self::init_py_io_mod());
Ok(path)
}
"math" => {
mod_cache.register(var_name.clone(), None, Self::init_py_math_mod());
let path = PathBuf::from("<builtins>.math");
py_mod_cache.register(path.clone(), None, Self::init_py_math_mod());
Ok(path)
}
"random" => {
mod_cache.register(var_name.clone(), None, Self::init_py_random_mod());
let path = PathBuf::from("<builtins>.random");
py_mod_cache.register(path.clone(), None, Self::init_py_random_mod());
Ok(path)
}
"socket" => {
mod_cache.register(var_name.clone(), None, Self::init_py_socket_mod());
let path = PathBuf::from("<builtins>.socket");
py_mod_cache.register(path.clone(), None, Self::init_py_socket_mod());
Ok(path)
}
"sys" => {
mod_cache.register(var_name.clone(), None, Self::init_py_sys_mod());
let path = PathBuf::from("<builtins>.sys");
py_mod_cache.register(path.clone(), None, Self::init_py_sys_mod());
Ok(path)
}
"time" => {
mod_cache.register(var_name.clone(), None, Self::init_py_time_mod());
let path = PathBuf::from("<builtins>.time");
py_mod_cache.register(path.clone(), None, Self::init_py_time_mod());
Ok(path)
}
_ => self.import_user_py_mod(var_name, lit)?,
_ => self.import_user_py_mod(mod_name),
}
Ok(())
}
fn similar_builtin_py_mod_name(&self, name: &Str) -> Option<Str> {
@ -966,13 +943,9 @@ impl Context {
.map(Str::rc)
}
fn import_user_py_mod(&self, var_name: &VarName, lit: &Literal) -> CompileResult<()> {
let __name__ = enum_unwrap!(lit.value.clone(), ValueObj::Str);
fn import_user_py_mod(&self, mod_name: &Literal) -> CompileResult<PathBuf> {
let __name__ = enum_unwrap!(mod_name.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) = self.cfg.input.clone() {
path.pop();
path
@ -987,39 +960,34 @@ impl Context {
self.cfg.input.clone(),
line!() as usize,
err.to_string(),
lit.loc(),
mod_name.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__)
}),
self.similar_builtin_py_mod_name(&__name__)
.or_else(|| py_mod_cache.get_similar_name(&__name__)),
);
return Err(TyCheckErrors::from(err));
}
};
let cfg = ErgConfig::with_path(path);
if py_mod_cache.get(&path).is_some() {
return Ok(path);
}
let cfg = ErgConfig::with_path(path.clone());
let src = cfg.input.read();
let mut builder = HIRBuilder::new_with_cache(
cfg,
var_name.inspect(),
py_mod_cache.clone(),
py_mod_cache.clone(),
);
let mut builder =
HIRBuilder::new_with_cache(cfg, __name__, 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());
py_mod_cache.register(path.clone(), Some(hir), builder.pop_ctx());
}
Err((maybe_hir, errs)) => {
if let Some(hir) = maybe_hir {
py_mod_cache.register(var_name.clone(), Some(hir), builder.pop_ctx());
py_mod_cache.register(path, Some(hir), builder.pop_ctx());
}
return Err(errs);
}
}
Ok(())
Ok(path)
}
pub(crate) fn _push_subtype_bound(&mut self, sub: Type, sup: Type) {

View file

@ -4,7 +4,7 @@ use erg_common::Str;
// use erg_common::error::Location;
use erg_common::{enum_unwrap, set};
use erg_type::constructors::{func1, mono_q, poly, quant, refinement};
use erg_type::constructors::{builtin_poly, func1, mono_q, quant, refinement};
use erg_type::typaram::TyParam;
use erg_type::{Predicate, TyBound, Type};
use Type::*;
@ -32,7 +32,7 @@ impl Context {
pub fn test_resolve_trait_inner1(&self) -> Result<(), ()> {
let name = Str::ever("Add");
let params = vec![TyParam::t(Nat)];
let maybe_trait = poly(name.clone(), params);
let maybe_trait = builtin_poly(name.clone(), params);
let mut min = Type::Obj;
for pair in self.rec_get_trait_impls(&name) {
if self.supertype_of(&pair.sup_trait, &maybe_trait) {
@ -48,7 +48,7 @@ impl Context {
pub fn test_instantiation_and_generalization(&self) -> Result<(), ()> {
let t = mono_q("T");
let eq = poly("Eq", vec![TyParam::t(t.clone())]);
let eq = builtin_poly("Eq", vec![TyParam::t(t.clone())]);
let bound = TyBound::subtype_of(t.clone(), eq);
let bounds = set! {bound};
let unbound_t = func1(t.clone(), t);

View file

@ -22,6 +22,7 @@ use crate::hir;
use Predicate as Pred;
use Type::*;
use ValueObj::{Inf, NegInf};
use Variance::*;
impl Context {
pub const TOP_LEVEL: usize = 1;
@ -159,12 +160,23 @@ impl Context {
let after = after.map(|aft| self.generalize_t_inner(*aft, bounds, lazy_inits));
ref_mut(self.generalize_t_inner(*before, bounds, lazy_inits), after)
}
Poly { name, mut params } => {
BuiltinPoly { name, mut params } => {
let params = params
.iter_mut()
.map(|p| self.generalize_tp(mem::take(p), bounds, lazy_inits))
.collect::<Vec<_>>();
poly(name, params)
builtin_poly(name, params)
}
Poly {
path,
name,
mut params,
} => {
let params = params
.iter_mut()
.map(|p| self.generalize_tp(mem::take(p), bounds, lazy_inits))
.collect::<Vec<_>>();
poly(path, name, params)
}
MonoProj { lhs, rhs } => {
let lhs = self.generalize_t_inner(*lhs, bounds, lazy_inits);
@ -203,21 +215,26 @@ impl Context {
}
}
fn deref_tp(&self, tp: TyParam, loc: Location) -> SingleTyCheckResult<TyParam> {
fn deref_tp(
&self,
tp: TyParam,
variance: Variance,
loc: Location,
) -> SingleTyCheckResult<TyParam> {
match tp {
TyParam::FreeVar(fv) if fv.is_linked() => {
let inner = fv.unwrap_linked();
self.deref_tp(inner, loc)
self.deref_tp(inner, variance, loc)
}
TyParam::FreeVar(_fv) if self.level == 0 => Err(TyCheckError::dummy_infer_error(
self.cfg.input.clone(),
fn_name!(),
line!(),
)),
TyParam::Type(t) => Ok(TyParam::t(self.deref_tyvar(*t, loc)?)),
TyParam::Type(t) => Ok(TyParam::t(self.deref_tyvar(*t, variance, loc)?)),
TyParam::App { name, mut args } => {
for param in args.iter_mut() {
*param = self.deref_tp(mem::take(param), loc)?;
*param = self.deref_tp(mem::take(param), variance, loc)?;
}
Ok(TyParam::App { name, args })
}
@ -243,6 +260,7 @@ impl Context {
fn deref_constraint(
&self,
constraint: Constraint,
variance: Variance,
loc: Location,
) -> SingleTyCheckResult<Constraint> {
match constraint {
@ -259,12 +277,14 @@ impl Context {
));
}
Ok(Constraint::new_sandwiched(
self.deref_tyvar(sub, loc)?,
self.deref_tyvar(sup, loc)?,
self.deref_tyvar(sub, variance, loc)?,
self.deref_tyvar(sup, variance, loc)?,
cyclic,
))
}
Constraint::TypeOf(t) => Ok(Constraint::new_type_of(self.deref_tyvar(t, loc)?)),
Constraint::TypeOf(t) => {
Ok(Constraint::new_type_of(self.deref_tyvar(t, variance, loc)?))
}
_ => unreachable!(),
}
}
@ -273,10 +293,16 @@ impl Context {
/// ```python
// ?T(:> Nat, <: Int)[n] ==> Nat (self.level <= n)
// ?T(:> Nat, <: Sub(?U(:> {1}))) ==> Nat
// ?T(:> Nat, <: Sub(?U(:> {1}))) -> ?U ==> |U: Type, T <: Sub(U)| T -> U
// ?T(:> Nat, <: Sub(Str)) ==> Error!
// ?T(:> {1, "a"}, <: Eq(?T(:> {1, "a"}, ...)) ==> Error!
// ```
pub(crate) fn deref_tyvar(&self, t: Type, loc: Location) -> SingleTyCheckResult<Type> {
pub(crate) fn deref_tyvar(
&self,
t: Type,
variance: Variance,
loc: Location,
) -> SingleTyCheckResult<Type> {
match t {
// ?T(:> Nat, <: Int)[n] ==> Nat (self.level <= n)
// ?T(:> Nat, <: Sub ?U(:> {1}))[n] ==> Nat
@ -288,13 +314,31 @@ impl Context {
if self.level <= fv.level().unwrap() {
// REVIEW: Even if type constraints can be satisfied, implementation may not exist
if self.subtype_of(sub_t, super_t) {
match variance {
Variance::Covariant => Ok(sub_t.clone()),
Variance::Contravariant => Ok(super_t.clone()),
Variance::Invariant => {
if self.supertype_of(sub_t, super_t) {
Ok(sub_t.clone())
} else {
Err(TyCheckError::subtyping_error(
self.cfg.input.clone(),
line!() as usize,
&self.deref_tyvar(sub_t.clone(), loc)?,
&self.deref_tyvar(super_t.clone(), loc)?,
&self.deref_tyvar(sub_t.clone(), variance, loc)?,
&self.deref_tyvar(super_t.clone(), variance, loc)?,
None,
Some(loc),
self.caused_by(),
))
}
}
}
} else {
Err(TyCheckError::subtyping_error(
self.cfg.input.clone(),
line!() as usize,
&self.deref_tyvar(sub_t.clone(), variance, loc)?,
&self.deref_tyvar(super_t.clone(), variance, loc)?,
None,
Some(loc),
self.caused_by(),
@ -318,42 +362,62 @@ impl Context {
}
} else {
let new_constraint = fv.crack_constraint().clone();
let new_constraint = self.deref_constraint(new_constraint, loc)?;
let new_constraint = self.deref_constraint(new_constraint, variance, loc)?;
fv.update_constraint(new_constraint);
Ok(Type::FreeVar(fv))
}
}
Type::FreeVar(fv) if fv.is_linked() => {
let t = fv.unwrap_linked();
self.deref_tyvar(t, loc)
self.deref_tyvar(t, variance, loc)
}
Type::Poly { name, mut params } => {
for param in params.iter_mut() {
*param = self.deref_tp(mem::take(param), loc)?;
Type::BuiltinPoly { name, mut params } => {
let typ = builtin_poly(&name, params.clone());
let (_, ctx) = self.get_nominal_type_ctx(&typ).unwrap();
let variances = ctx.type_params_variance();
for (param, variance) in params.iter_mut().zip(variances.into_iter()) {
*param = self.deref_tp(mem::take(param), variance, loc)?;
}
Ok(Type::Poly { name, params })
Ok(Type::BuiltinPoly { name, params })
}
Type::Poly {
path,
name,
mut params,
} => {
let typ = poly(path.clone(), &name, params.clone());
let (_, ctx) = self.get_nominal_type_ctx(&typ).unwrap();
let variances = ctx.type_params_variance();
for (param, variance) in params.iter_mut().zip(variances.into_iter()) {
*param = self.deref_tp(mem::take(param), variance, loc)?;
}
Ok(Type::Poly { path, name, params })
}
Type::Subr(mut subr) => {
for param in subr.non_default_params.iter_mut() {
*param.typ_mut() = self.deref_tyvar(mem::take(param.typ_mut()), loc)?;
*param.typ_mut() =
self.deref_tyvar(mem::take(param.typ_mut()), Contravariant, loc)?;
}
if let Some(var_args) = &mut subr.var_params {
*var_args.typ_mut() = self.deref_tyvar(mem::take(var_args.typ_mut()), loc)?;
*var_args.typ_mut() =
self.deref_tyvar(mem::take(var_args.typ_mut()), Contravariant, loc)?;
}
for d_param in subr.default_params.iter_mut() {
*d_param.typ_mut() = self.deref_tyvar(mem::take(d_param.typ_mut()), loc)?;
*d_param.typ_mut() =
self.deref_tyvar(mem::take(d_param.typ_mut()), Contravariant, loc)?;
}
subr.return_t = Box::new(self.deref_tyvar(mem::take(&mut subr.return_t), loc)?);
subr.return_t =
Box::new(self.deref_tyvar(mem::take(&mut subr.return_t), Covariant, loc)?);
Ok(Type::Subr(subr))
}
Type::Ref(t) => {
let t = self.deref_tyvar(*t, loc)?;
let t = self.deref_tyvar(*t, variance, loc)?;
Ok(ref_(t))
}
Type::RefMut { before, after } => {
let before = self.deref_tyvar(*before, loc)?;
let before = self.deref_tyvar(*before, variance, loc)?;
let after = if let Some(after) = after {
Some(self.deref_tyvar(*after, loc)?)
Some(self.deref_tyvar(*after, variance, loc)?)
} else {
None
};
@ -362,12 +426,29 @@ impl Context {
Type::Callable { .. } => todo!(),
Type::Record(mut rec) => {
for (_, field) in rec.iter_mut() {
*field = self.deref_tyvar(mem::take(field), loc)?;
*field = self.deref_tyvar(mem::take(field), variance, loc)?;
}
Ok(Type::Record(rec))
}
// |X <: T <: X| X -> X ==> T -> T
/*Type::Quantified(quant) => {
let mut replace_list = vec![];
let mut new_bounds = set!{};
for bound in quant.bounds.into_iter() {
if let Some((sub, mid, sup)) = bound.get_types() {
if self.subtype_of(sub, sup) && self.supertype_of(sub, sup) {
replace_list.push((mid, sub));
} else {
new_bounds.insert(bound);
}
} else {
new_bounds.insert(bound);
}
}
Ok(())
}*/
Type::Refinement(refine) => {
let t = self.deref_tyvar(*refine.t, loc)?;
let t = self.deref_tyvar(*refine.t, variance, loc)?;
// TODO: deref_predicate
Ok(refinement(refine.var, t, refine.preds))
}
@ -401,7 +482,7 @@ impl Context {
hir::Expr::Accessor(acc) => {
let loc = acc.loc();
let t = acc.ref_mut_t();
*t = self.deref_tyvar(mem::take(t), loc)?;
*t = self.deref_tyvar(mem::take(t), Covariant, loc)?;
match acc {
hir::Accessor::Attr(attr) => {
self.resolve_expr_t(&mut attr.obj)?;
@ -420,7 +501,7 @@ impl Context {
hir::Expr::Array(array) => match array {
hir::Array::Normal(arr) => {
let loc = arr.loc();
arr.t = self.deref_tyvar(mem::take(&mut arr.t), loc)?;
arr.t = self.deref_tyvar(mem::take(&mut arr.t), Covariant, loc)?;
for elem in arr.elems.pos_args.iter_mut() {
self.resolve_expr_t(&mut elem.expr)?;
}
@ -443,10 +524,12 @@ impl Context {
for attr in record.attrs.iter_mut() {
match &mut attr.sig {
hir::Signature::Var(var) => {
var.t = self.deref_tyvar(mem::take(&mut var.t), var.loc())?;
var.t =
self.deref_tyvar(mem::take(&mut var.t), Covariant, var.loc())?;
}
hir::Signature::Subr(subr) => {
subr.t = self.deref_tyvar(mem::take(&mut subr.t), subr.loc())?;
subr.t =
self.deref_tyvar(mem::take(&mut subr.t), Covariant, subr.loc())?;
}
}
for chunk in attr.body.block.iter_mut() {
@ -458,7 +541,7 @@ impl Context {
hir::Expr::BinOp(binop) => {
let loc = binop.loc();
let t = binop.signature_mut_t().unwrap();
*t = self.deref_tyvar(mem::take(t), loc)?;
*t = self.deref_tyvar(mem::take(t), Covariant, loc)?;
self.resolve_expr_t(&mut binop.lhs)?;
self.resolve_expr_t(&mut binop.rhs)?;
Ok(())
@ -466,14 +549,14 @@ impl Context {
hir::Expr::UnaryOp(unaryop) => {
let loc = unaryop.loc();
let t = unaryop.signature_mut_t().unwrap();
*t = self.deref_tyvar(mem::take(t), loc)?;
*t = self.deref_tyvar(mem::take(t), Covariant, loc)?;
self.resolve_expr_t(&mut unaryop.expr)?;
Ok(())
}
hir::Expr::Call(call) => {
let loc = call.loc();
let t = call.signature_mut_t().unwrap();
*t = self.deref_tyvar(mem::take(t), loc)?;
*t = self.deref_tyvar(mem::take(t), Covariant, loc)?;
for arg in call.args.pos_args.iter_mut() {
self.resolve_expr_t(&mut arg.expr)?;
}
@ -483,16 +566,16 @@ impl Context {
Ok(())
}
hir::Expr::Decl(decl) => {
decl.t = self.deref_tyvar(mem::take(&mut decl.t), decl.loc())?;
decl.t = self.deref_tyvar(mem::take(&mut decl.t), Covariant, decl.loc())?;
Ok(())
}
hir::Expr::Def(def) => {
match &mut def.sig {
hir::Signature::Var(var) => {
var.t = self.deref_tyvar(mem::take(&mut var.t), var.loc())?;
var.t = self.deref_tyvar(mem::take(&mut var.t), Covariant, var.loc())?;
}
hir::Signature::Subr(subr) => {
subr.t = self.deref_tyvar(mem::take(&mut subr.t), subr.loc())?;
subr.t = self.deref_tyvar(mem::take(&mut subr.t), Covariant, subr.loc())?;
}
}
for chunk in def.body.block.iter_mut() {
@ -501,7 +584,7 @@ impl Context {
Ok(())
}
hir::Expr::Lambda(lambda) => {
lambda.t = self.deref_tyvar(mem::take(&mut lambda.t), lambda.loc())?;
lambda.t = self.deref_tyvar(mem::take(&mut lambda.t), Covariant, lambda.loc())?;
for chunk in lambda.body.iter_mut() {
self.resolve_expr_t(chunk)?;
}
@ -780,17 +863,46 @@ impl Context {
(l, Type::Ref(r)) => self.reunify(l, r, bef_loc, aft_loc),
(l, Type::RefMut { before, .. }) => self.reunify(l, before, bef_loc, aft_loc),
(
Type::Poly {
Type::BuiltinPoly {
name: ln,
params: lps,
},
Type::Poly {
Type::BuiltinPoly {
name: rn,
params: rps,
},
) => {
if ln != rn {
let before_t = poly(ln.clone(), lps.clone());
let before_t = builtin_poly(ln.clone(), lps.clone());
return Err(TyCheckError::re_unification_error(
self.cfg.input.clone(),
line!() as usize,
&before_t,
after_t,
bef_loc,
aft_loc,
self.caused_by(),
));
}
for (l, r) in lps.iter().zip(rps.iter()) {
self.reunify_tp(l, r)?;
}
Ok(())
}
(
Type::Poly {
path: lp,
name: ln,
params: lps,
},
Type::Poly {
path: rp,
name: rn,
params: rps,
},
) => {
if lp != rp || ln != rn {
let before_t = poly(lp.clone(), ln.clone(), lps.clone());
return Err(TyCheckError::re_unification_error(
self.cfg.input.clone(),
line!() as usize,
@ -1047,11 +1159,11 @@ impl Context {
Ok(())
}
(
Type::Poly {
Type::BuiltinPoly {
name: ln,
params: lps,
},
Type::Poly {
Type::BuiltinPoly {
name: rn,
params: rps,
},
@ -1072,6 +1184,34 @@ impl Context {
}
Ok(())
}
(
Type::Poly {
path: lp,
name: ln,
params: lps,
},
Type::Poly {
path: rp,
name: rn,
params: rps,
},
) => {
if lp != rp || ln != rn {
return Err(TyCheckErrors::from(TyCheckError::unification_error(
self.cfg.input.clone(),
line!() as usize,
maybe_sub,
maybe_sup,
sub_loc,
sup_loc,
self.caused_by(),
)));
}
for (l, r) in lps.iter().zip(rps.iter()) {
self.sub_unify_tp(l, r, None, false)?;
}
Ok(())
}
(_, Type::Ref(t)) => {
self.sub_unify(maybe_sub, t, sub_loc, sup_loc, param_name)?;
Ok(())
@ -1085,7 +1225,7 @@ impl Context {
(Refinement(_), Refinement(_)) => todo!(),
(Type::Subr(_) | Type::Record(_), Type) => Ok(()),
// TODO Tuple2, ...
(Type::Poly{ name, .. }, Type) if &name[..] == "Array" || &name[..] == "Tuple" => Ok(()),
(Type::BuiltinPoly{ name, .. }, Type) if &name[..] == "Array" || &name[..] == "Tuple" => Ok(()),
_ => todo!("{maybe_sub} can be a subtype of {maybe_sup}, but failed to semi-unify (or existential types are not supported)"),
}
}

View file

@ -385,6 +385,10 @@ impl Identifier {
pub fn is_procedural(&self) -> bool {
self.name.is_procedural()
}
pub fn downcast(self) -> erg_parser::ast::Identifier {
erg_parser::ast::Identifier::new(self.dot, self.name)
}
}
#[derive(Debug, Clone)]

View file

@ -1,5 +1,5 @@
use std::mem;
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use erg_common::config::{ErgConfig, Input};
use erg_common::traits::{Locational, Stream};
@ -9,8 +9,9 @@ use erg_common::{enum_unwrap, log};
use erg_parser::ast::DefId;
use erg_parser::token::{Token, TokenKind};
use erg_type::typaram::TyParam;
use erg_type::value::ValueObj;
use erg_type::Type;
use erg_type::{HasType, Type};
use crate::hir::{
Accessor, Args, Block, Call, Def, DefBody, Expr, Identifier, Literal, PosArg, HIR,
@ -30,15 +31,16 @@ impl Linker {
// x = ModuleType("mod")
// exec(code, x.__dict__) # `code` is the mod's content
Expr::Def(ref def) if def.def_kind().is_erg_import() => {
let path = enum_unwrap!(def.sig.ref_t().typarams().remove(0), TyParam::Value:(ValueObj::Str:(_)));
let path = Path::new(&path[..]);
let path = cfg.input.resolve(path).unwrap();
// In the case of REPL, entries cannot be used up
let hir = if cfg.input.is_repl() {
mod_cache
.get(&def.sig.ident().inspect()[..])
.get(path.as_path())
.and_then(|entry| entry.hir.clone())
} else {
mod_cache
.remove(&def.sig.ident().inspect()[..])
.and_then(|entry| entry.hir)
mod_cache.remove(path.as_path()).and_then(|entry| entry.hir)
};
let mod_name = enum_unwrap!(def.body.block.first().unwrap(), Expr::Call)
.args

View file

@ -16,7 +16,7 @@ use erg_parser::build_ast::ASTBuilder;
use erg_parser::token::{Token, TokenKind};
use erg_type::constructors::{
array, array_mut, builtin_mono, free_var, func, mono, poly, proc, quant,
array, array_mut, builtin_mono, builtin_poly, free_var, func, mono, proc, quant,
};
use erg_type::free::Constraint;
use erg_type::typaram::TyParam;
@ -85,11 +85,8 @@ impl Runnable for ASTLowerer {
fn exec(&mut self) -> Result<(), Self::Errs> {
let mut ast_builder = ASTBuilder::new(self.cfg.copy());
let ast = ast_builder.build(self.input().read())?;
let (hir, warns) = self
.lower(ast, "exec")
.map_err(|(_, errs)| self.convert(errs))?;
let (hir, warns) = self.lower(ast, "exec").map_err(|(_, errs)| errs)?;
if self.cfg.verbose >= 2 {
let warns = self.convert(warns);
warns.fmt_all_stderr();
}
println!("{hir}");
@ -99,9 +96,7 @@ impl Runnable for ASTLowerer {
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))?;
let (hir, ..) = self.lower(ast, "eval").map_err(|(_, errs)| errs)?;
Ok(format!("{hir}"))
}
}
@ -121,13 +116,6 @@ impl ASTLowerer {
}
}
fn convert(&self, errs: LowerErrors) -> CompileErrors {
errs.into_iter()
.map(|e| CompileError::new(e.core, self.input().clone(), e.caused_by))
.collect::<Vec<_>>()
.into()
}
fn return_t_check(
&self,
loc: Location,
@ -160,7 +148,7 @@ impl ASTLowerer {
if mode != "eval" && !expr.ref_t().is_nonelike() && !expr.is_type_asc() {
Err(LowerError::syntax_error(
self.cfg.input.clone(),
0,
line!() as usize,
expr.loc(),
AtomicStr::arc(&self.ctx.name[..]),
switch_lang!(
@ -264,7 +252,7 @@ impl ASTLowerer {
match maybe_len {
Ok(v @ ValueObj::Nat(_)) => {
if elem.ref_t().is_mut() {
poly(
builtin_poly(
"ArrayWithMutType!",
vec![TyParam::t(elem.t()), TyParam::Value(v)],
)
@ -274,7 +262,7 @@ impl ASTLowerer {
}
Ok(v @ ValueObj::Mut(_)) if v.class() == builtin_mono("Nat!") => {
if elem.ref_t().is_mut() {
poly(
builtin_poly(
"ArrayWithMutTypeAndLength!",
vec![TyParam::t(elem.t()), TyParam::Value(v)],
)
@ -286,7 +274,7 @@ impl ASTLowerer {
// REVIEW: is it ok to ignore the error?
Err(_e) => {
if elem.ref_t().is_mut() {
poly(
builtin_poly(
"ArrayWithMutType!",
vec![TyParam::t(elem.t()), TyParam::erased(Type::Nat)],
)
@ -349,7 +337,9 @@ impl ASTLowerer {
}
ast::Accessor::Attr(attr) => {
let obj = self.lower_expr(*attr.obj)?;
let t = self.ctx.rec_get_attr_t(&obj, &attr.ident, &self.ctx.name)?;
let t =
self.ctx
.rec_get_attr_t(&obj, &attr.ident, &self.cfg.input, &self.ctx.name)?;
let ident = hir::Identifier::bare(attr.ident.dot, attr.ident.name);
let acc = hir::Accessor::Attr(hir::Attribute::new(obj, ident, t));
Ok(acc)
@ -389,8 +379,12 @@ impl ASTLowerer {
(Type::Failure, None)
} else {
(
self.ctx.rec_get_var_t(&ident, &self.ctx.name)?,
self.ctx.get_local_uniq_obj_name(&ident.name),
self.ctx
.rec_get_var_t(&ident, &self.cfg.input, &self.ctx.name)?,
self.ctx
.get_singular_ctx_from_ident(&ident, &self.ctx.name)
.ok()
.map(|ctx| ctx.name.clone()),
)
};
let ident = hir::Identifier::new(ident.dot, ident.name, __name__, t);
@ -403,7 +397,9 @@ impl ASTLowerer {
let lhs = hir::PosArg::new(self.lower_expr(*args.next().unwrap())?);
let rhs = hir::PosArg::new(self.lower_expr(*args.next().unwrap())?);
let args = [lhs, rhs];
let t = self.ctx.get_binop_t(&bin.op, &args, &self.ctx.name)?;
let t = self
.ctx
.get_binop_t(&bin.op, &args, &self.cfg.input, &self.ctx.name)?;
let mut args = args.into_iter();
let lhs = args.next().unwrap().expr;
let rhs = args.next().unwrap().expr;
@ -415,7 +411,9 @@ impl ASTLowerer {
let mut args = unary.args.into_iter();
let arg = hir::PosArg::new(self.lower_expr(*args.next().unwrap())?);
let args = [arg];
let t = self.ctx.get_unaryop_t(&unary.op, &args, &self.ctx.name)?;
let t = self
.ctx
.get_unaryop_t(&unary.op, &args, &self.cfg.input, &self.ctx.name)?;
let mut args = args.into_iter();
let expr = args.next().unwrap().expr;
Ok(hir::UnaryOp::new(unary.op, expr, t))
@ -443,6 +441,7 @@ impl ASTLowerer {
&call.method_name,
&hir_args.pos_args,
&hir_args.kw_args,
&self.cfg.input,
&self.ctx.name,
)?;
let method_name = if let Some(method_name) = call.method_name {
@ -455,7 +454,14 @@ impl ASTLowerer {
} else {
None
};
Ok(hir::Call::new(obj, method_name, hir_args, sig_t))
let call = hir::Call::new(obj, method_name, hir_args, sig_t);
if let Some(kind) = call.import_kind() {
let mod_name = enum_unwrap!(call.args.get_left_or_key("Path").unwrap(), hir::Expr::Lit);
if let Err(errs) = self.ctx.import_mod(kind, mod_name) {
self.errs.extend(errs.into_iter());
};
}
Ok(call)
}
fn lower_pack(&mut self, pack: ast::DataPack) -> LowerResult<hir::Call> {
@ -482,6 +488,7 @@ impl ASTLowerer {
&Some(method_name.clone()),
&args,
&[],
&self.cfg.input,
&self.ctx.name,
)?;
let args = hir::Args::new(args, None, vec![], None);
@ -630,20 +637,6 @@ impl ASTLowerer {
.as_mut()
.unwrap()
.assign_var_sig(&sig, found_body_t, id)?;
match block.first().unwrap() {
hir::Expr::Call(call) => {
if let Some(kind) = call.import_kind() {
if let Err(errs) = self.ctx.outer.as_mut().unwrap().import_mod(
kind,
&ident.name,
&call.args.pos_args.first().unwrap().expr,
) {
self.errs.extend(errs.into_iter());
};
}
}
_other => {}
}
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);
@ -785,7 +778,7 @@ impl ASTLowerer {
}
let (_, ctx) = self
.ctx
.get_nominal_type_ctx(&mono(self.ctx.mod_name(), hir_def.sig.ident().inspect()))
.get_nominal_type_ctx(&mono(self.ctx.path(), hir_def.sig.ident().inspect()))
.unwrap();
let type_obj = enum_unwrap!(self.ctx.rec_get_const_obj(hir_def.sig.ident().inspect()).unwrap(), ValueObj::Type:(TypeObj::Generated:(_)));
let sup_type = enum_unwrap!(&hir_def.body.block.first().unwrap(), hir::Expr::Call)
@ -1224,7 +1217,7 @@ impl ASTLowerer {
Ok(hir) => hir,
Err((hir, errs)) => {
self.errs.extend(errs.into_iter());
log!(err "the AST lowering process has failed.");
log!(err "the resolving process has failed. errs: {}", self.errs.len());
return Err((Some(hir), LowerErrors::from(self.errs.take_all())));
}
};
@ -1239,7 +1232,7 @@ impl ASTLowerer {
log!(info "the AST lowering process has completed.");
Ok((hir, LowerWarnings::from(self.warns.take_all())))
} else {
log!(err "the AST lowering process has failed.");
log!(err "the AST lowering process has failed. errs: {}", self.errs.len());
Err((Some(hir), LowerErrors::from(self.errs.take_all())))
}
}

View file

@ -1,6 +1,7 @@
use std::borrow::Borrow;
use std::fmt;
use std::hash::Hash;
use std::path::PathBuf;
use std::rc::Rc;
use erg_common::dict::Dict;
@ -8,8 +9,6 @@ use erg_common::levenshtein::get_similar_name;
use erg_common::shared::Shared;
use erg_common::Str;
use erg_parser::ast::VarName;
use crate::context::Context;
use crate::hir::HIR;
@ -65,13 +64,17 @@ impl ModuleEntry {
#[derive(Debug, Default)]
pub struct ModuleCache {
cache: Dict<VarName, ModuleEntry>,
cache: Dict<PathBuf, ModuleEntry>,
last_id: usize,
}
impl fmt::Display for ModuleCache {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ModuleCache {}", self.cache)
write!(f, "ModuleCache {{")?;
for (path, entry) in self.cache.iter() {
writeln!(f, "{}: {}, ", path.display(), entry)?;
}
write!(f, "}}")
}
}
@ -83,42 +86,32 @@ impl ModuleCache {
}
}
pub fn get<Q: Eq + Hash + ?Sized>(&self, name: &Q) -> Option<&ModuleEntry>
pub fn get<P: Eq + Hash + ?Sized>(&self, path: &P) -> Option<&ModuleEntry>
where
VarName: Borrow<Q>,
PathBuf: Borrow<P>,
{
self.cache.get(name)
self.cache.get(path)
}
pub fn get_by_name(&self, __name__: &str) -> Option<(&VarName, &ModuleEntry)> {
self.cache
.iter()
.find(|(_, ent)| &ent.ctx.name[..] == __name__)
}
pub fn get_mut<Q: Eq + Hash + ?Sized>(&mut self, name: &Q) -> Option<&mut ModuleEntry>
pub fn get_mut<Q: Eq + Hash + ?Sized>(&mut self, path: &Q) -> Option<&mut ModuleEntry>
where
VarName: Borrow<Q>,
PathBuf: Borrow<Q>,
{
self.cache.get_mut(name)
self.cache.get_mut(path)
}
pub fn register(&mut self, name: VarName, hir: Option<HIR>, ctx: Context) {
pub fn register(&mut self, path: PathBuf, hir: Option<HIR>, ctx: Context) {
self.last_id += 1;
let id = ModId::new(self.last_id);
let entry = ModuleEntry::new(id, hir, ctx);
self.cache.insert(name, entry);
self.cache.insert(path, entry);
}
pub fn register_alias(&mut self, name: VarName, entry: &ModuleEntry) {
self.cache.insert(name, entry.clone());
}
pub fn remove<Q: Eq + Hash + ?Sized>(&mut self, name: &Q) -> Option<ModuleEntry>
pub fn remove<Q: Eq + Hash + ?Sized>(&mut self, path: &Q) -> Option<ModuleEntry>
where
VarName: Borrow<Q>,
PathBuf: Borrow<Q>,
{
self.cache.remove(name)
self.cache.remove(path)
}
pub fn remove_by_id(&mut self, id: ModId) -> Option<ModuleEntry> {
@ -136,7 +129,7 @@ impl ModuleCache {
}
pub fn get_similar_name(&self, name: &str) -> Option<Str> {
get_similar_name(self.cache.iter().map(|(v, _)| &v.inspect()[..]), name).map(Str::rc)
get_similar_name(self.cache.iter().map(|(v, _)| v.to_str().unwrap()), name).map(Str::rc)
}
}
@ -156,55 +149,46 @@ impl SharedModuleCache {
self_
}
pub fn get<Q: Eq + Hash + ?Sized>(&self, name: &Q) -> Option<&ModuleEntry>
pub fn get<Q: Eq + Hash + ?Sized>(&self, path: &Q) -> Option<&ModuleEntry>
where
VarName: Borrow<Q>,
PathBuf: Borrow<Q>,
{
let ref_ = unsafe { self.0.as_ptr().as_ref().unwrap() };
ref_.get(name)
ref_.get(path)
}
pub fn get_by_name(&self, __name__: &str) -> Option<(&VarName, &ModuleEntry)> {
let ref_ = unsafe { self.0.as_ptr().as_ref().unwrap() };
ref_.get_by_name(__name__)
}
pub fn get_mut<Q: Eq + Hash + ?Sized>(&self, name: &Q) -> Option<&mut ModuleEntry>
pub fn get_mut<Q: Eq + Hash + ?Sized>(&self, path: &Q) -> Option<&mut ModuleEntry>
where
VarName: Borrow<Q>,
PathBuf: Borrow<Q>,
{
let ref_ = unsafe { self.0.as_ptr().as_mut().unwrap() };
ref_.get_mut(name)
ref_.get_mut(path)
}
pub fn get_ctx<Q: Eq + Hash + ?Sized>(&self, name: &Q) -> Option<Rc<Context>>
pub fn get_ctx<Q: Eq + Hash + ?Sized>(&self, path: &Q) -> Option<Rc<Context>>
where
VarName: Borrow<Q>,
PathBuf: Borrow<Q>,
{
self.0.borrow().get(name).map(|entry| entry.ctx.clone())
self.0.borrow().get(path).map(|entry| entry.ctx.clone())
}
pub fn ref_ctx<Q: Eq + Hash + ?Sized>(&self, name: &Q) -> Option<&Context>
pub fn ref_ctx<Q: Eq + Hash + ?Sized>(&self, path: &Q) -> Option<&Context>
where
VarName: Borrow<Q>,
PathBuf: Borrow<Q>,
{
let ref_ = unsafe { self.0.as_ptr().as_ref().unwrap() };
ref_.get(name).map(|entry| entry.ctx.as_ref())
ref_.get(path).map(|entry| entry.ctx.as_ref())
}
pub fn register(&self, name: VarName, hir: Option<HIR>, ctx: Context) {
self.0.borrow_mut().register(name, hir, ctx);
pub fn register(&self, path: PathBuf, hir: Option<HIR>, ctx: Context) {
self.0.borrow_mut().register(path, hir, ctx);
}
pub fn register_alias(&self, name: VarName, entry: &ModuleEntry) {
self.0.borrow_mut().register_alias(name, entry);
}
pub fn remove<Q: Eq + Hash + ?Sized>(&self, name: &Q) -> Option<ModuleEntry>
pub fn remove<Q: Eq + Hash + ?Sized>(&self, path: &Q) -> Option<ModuleEntry>
where
VarName: Borrow<Q>,
PathBuf: Borrow<Q>,
{
self.0.borrow_mut().remove(name)
self.0.borrow_mut().remove(path)
}
pub fn remove_by_id(&self, id: ModId) -> Option<ModuleEntry> {

View file

@ -509,7 +509,28 @@ impl Parser {
let local = ConstLocal::new(local.name.into_token());
Ok(ConstExpr::Accessor(ConstAccessor::Local(local)))
}
// TODO: App, Array, Record, BinOp, UnaryOp,
Expr::Array(array) => match array {
Array::Normal(arr) => {
let (elems, _, _) = arr.elems.deconstruct();
let mut const_elems = vec![];
for elem in elems.into_iter() {
let const_expr = self.validate_const_expr(elem.expr)?;
const_elems.push(ConstPosArg::new(const_expr));
}
let elems = ConstArgs::new(const_elems, vec![], None);
let const_arr = ConstArray::new(arr.l_sqbr, arr.r_sqbr, elems, None);
Ok(ConstExpr::Array(const_arr))
}
other => {
self.errs.push(ParseError::feature_error(
line!() as usize,
other.loc(),
"???",
));
Err(())
}
},
// TODO: App, Record, BinOp, UnaryOp,
other => {
self.errs.push(ParseError::syntax_error(
0,

View file

@ -23,35 +23,51 @@ pub fn named_free_var(name: Str, level: usize, constraint: Constraint) -> Type {
}
pub fn array(elem_t: Type, len: TyParam) -> Type {
poly("Array", vec![TyParam::t(elem_t), len])
builtin_poly("Array", vec![TyParam::t(elem_t), len])
}
pub fn array_mut(elem_t: Type, len: TyParam) -> Type {
poly("Array!", vec![TyParam::t(elem_t), len])
builtin_poly("Array!", vec![TyParam::t(elem_t), len])
}
pub fn dict(k_t: Type, v_t: Type) -> Type {
poly("Dict", vec![TyParam::t(k_t), TyParam::t(v_t)])
builtin_poly("Dict", vec![TyParam::t(k_t), TyParam::t(v_t)])
}
pub fn tuple(args: Vec<Type>) -> Type {
let name = format!("Tuple{}", args.len());
poly(name, args.into_iter().map(TyParam::t).collect())
builtin_poly(name, args.into_iter().map(TyParam::t).collect())
}
#[inline]
pub fn range(t: Type) -> Type {
poly("Range", vec![TyParam::t(t)])
builtin_poly("Range", vec![TyParam::t(t)])
}
pub fn enum_t(s: Set<ValueObj>) -> Type {
#[inline]
pub fn module(path: TyParam) -> Type {
builtin_poly("Module", vec![path])
}
pub fn v_enum(s: Set<ValueObj>) -> Type {
assert!(is_homogeneous(&s));
let name = Str::from(fresh_varname());
let t = inner_class(&s);
let preds = s
.iter()
.map(|o| Predicate::eq(name.clone(), TyParam::value(o.clone())))
.into_iter()
.map(|o| Predicate::eq(name.clone(), TyParam::value(o)))
.collect();
let refine = RefinementType::new(name, inner_class(&s), preds);
let refine = RefinementType::new(name, t, preds);
Type::Refinement(refine)
}
pub fn tp_enum(ty: Type, s: Set<TyParam>) -> Type {
let name = Str::from(fresh_varname());
let preds = s
.into_iter()
.map(|tp| Predicate::eq(name.clone(), tp))
.collect();
let refine = RefinementType::new(name, ty, preds);
Type::Refinement(refine)
}
@ -97,7 +113,7 @@ where
}
pub fn iter(t: Type) -> Type {
poly("Iter", vec![TyParam::t(t)])
builtin_poly("Iter", vec![TyParam::t(t)])
}
pub fn ref_(t: Type) -> Type {
@ -112,11 +128,11 @@ pub fn ref_mut(before: Type, after: Option<Type>) -> Type {
}
pub fn option(t: Type) -> Type {
poly("Option", vec![TyParam::t(t)])
builtin_poly("Option", vec![TyParam::t(t)])
}
pub fn option_mut(t: Type) -> Type {
poly("Option!", vec![TyParam::t(t)])
builtin_poly("Option!", vec![TyParam::t(t)])
}
pub fn subr_t(
@ -305,7 +321,7 @@ pub fn mono_q<S: Into<Str>>(name: S) -> Type {
}
#[inline]
pub fn mono<S: Into<Str>, T: Into<Str>>(path: S, name: T) -> Type {
pub fn mono<P: Into<PathBuf>, S: Into<Str>>(path: P, name: S) -> Type {
Type::Mono {
path: path.into(),
name: name.into(),
@ -313,8 +329,8 @@ pub fn mono<S: Into<Str>, T: Into<Str>>(path: S, name: T) -> Type {
}
#[inline]
pub fn poly<S: Into<Str>>(name: S, params: Vec<TyParam>) -> Type {
Type::Poly {
pub fn builtin_poly<S: Into<Str>>(name: S, params: Vec<TyParam>) -> Type {
Type::BuiltinPoly {
name: name.into(),
params,
}
@ -328,6 +344,15 @@ pub fn poly_q<S: Into<Str>>(name: S, params: Vec<TyParam>) -> Type {
}
}
#[inline]
pub fn poly<P: Into<PathBuf>, T: Into<Str>>(path: P, name: T, params: Vec<TyParam>) -> Type {
Type::Poly {
path: path.into(),
name: name.into(),
params,
}
}
#[inline]
pub fn mono_proj<S: Into<Str>>(lhs: Type, rhs: S) -> Type {
Type::MonoProj {

View file

@ -12,6 +12,7 @@ pub mod value;
use std::fmt;
use std::ops::{Range, RangeInclusive};
use std::path::PathBuf;
use erg_common::dict::Dict;
use erg_common::set::Set;
@ -181,7 +182,7 @@ impl ValueArgs {
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct BuiltinConstSubr {
name: &'static str,
subr: fn(ValueArgs, Str, Option<Str>) -> EvalValueResult<ValueObj>,
subr: fn(ValueArgs, PathBuf, Option<Str>) -> EvalValueResult<ValueObj>,
sig_t: Type,
as_type: Option<Type>,
}
@ -195,7 +196,7 @@ impl fmt::Display for BuiltinConstSubr {
impl BuiltinConstSubr {
pub const fn new(
name: &'static str,
subr: fn(ValueArgs, Str, Option<Str>) -> EvalValueResult<ValueObj>,
subr: fn(ValueArgs, PathBuf, Option<Str>) -> EvalValueResult<ValueObj>,
sig_t: Type,
as_type: Option<Type>,
) -> Self {
@ -210,10 +211,10 @@ impl BuiltinConstSubr {
pub fn call(
&self,
args: ValueArgs,
mod_name: Str,
path: PathBuf,
__name__: Option<Str>,
) -> EvalValueResult<ValueObj> {
(self.subr)(args, mod_name, __name__)
(self.subr)(args, path, __name__)
}
}
@ -416,6 +417,13 @@ impl TyBound {
}
}
pub fn get_types(&self) -> Option<(&Type, &Type, &Type)> {
match self {
Self::Sandwiched { sub, mid, sup } => Some((sub, mid, sup)),
Self::Instance { .. } => None,
}
}
pub fn get_lhs(&self) -> Str {
match self {
Self::Sandwiched { mid, .. } => mid.name(),
@ -1095,7 +1103,6 @@ pub enum Type {
Str,
NoneType,
Code,
Module,
Frame,
Error,
Inf, // {∞}
@ -1110,7 +1117,7 @@ pub enum Type {
Never, // {}
BuiltinMono(Str),
Mono {
path: Str,
path: PathBuf,
name: Str,
},
/* Polymorphic types */
@ -1138,7 +1145,12 @@ pub enum Type {
And(Box<Type>, Box<Type>),
Not(Box<Type>, Box<Type>),
Or(Box<Type>, Box<Type>),
BuiltinPoly {
name: Str,
params: Vec<TyParam>,
},
Poly {
path: PathBuf,
name: Str,
params: Vec<TyParam>,
},
@ -1170,7 +1182,6 @@ impl PartialEq for Type {
| (Self::Str, Self::Str)
| (Self::NoneType, Self::NoneType)
| (Self::Code, Self::Code)
| (Self::Module, Self::Module)
| (Self::Frame, Self::Frame)
| (Self::Error, Self::Error)
| (Self::Inf, Self::Inf)
@ -1182,11 +1193,11 @@ impl PartialEq for Type {
| (Self::NotImplemented, Self::NotImplemented)
| (Self::Ellipsis, Self::Ellipsis)
| (Self::Never, Self::Never) => true,
(Self::BuiltinMono(l), Self::BuiltinMono(r)) => l == r,
(Self::BuiltinMono(l), Self::BuiltinMono(r))
| (Self::MonoQVar(l), Self::MonoQVar(r)) => l == r,
(Self::Mono { path: lp, name: ln }, Self::Mono { path: rp, name: rn }) => {
lp == rp && ln == rn
}
(Self::MonoQVar(l), Self::MonoQVar(r)) => l == r,
(Self::Ref(l), Self::Ref(r)) => l == r,
(
Self::RefMut {
@ -1228,6 +1239,18 @@ impl PartialEq for Type {
| (Self::Or(ll, lr), Self::Or(rl, rr)) => ll == rl && lr == rr,
(
Self::Poly {
path: lp,
name: ln,
params: lps,
},
Self::Poly {
path: rp,
name: rn,
params: rps,
},
) => lp == rp && ln == rn && lps == rps,
(
Self::BuiltinPoly {
name: ln,
params: lps,
}
@ -1235,7 +1258,7 @@ impl PartialEq for Type {
name: ln,
params: lps,
},
Self::Poly {
Self::BuiltinPoly {
name: rn,
params: rps,
}
@ -1281,7 +1304,7 @@ impl LimitedDisplay for Type {
}
match self {
Self::BuiltinMono(name) => write!(f, "{name}"),
Self::Mono { path, name } => write!(f, "{name}(of {path})"),
Self::Mono { path, name } => write!(f, "{}.{name}", path.display()),
Self::Ref(t) => {
write!(f, "{}(", self.name())?;
t.limited_fmt(f, limit - 1)?;
@ -1338,7 +1361,17 @@ impl LimitedDisplay for Type {
write!(f, " or ")?;
rhs.limited_fmt(f, limit - 1)
}
Self::Poly { name, params } => {
Self::Poly { path, name, params } => {
write!(f, "{}.{name}(", path.display())?;
for (i, tp) in params.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
tp.limited_fmt(f, limit - 1)?;
}
write!(f, ")")
}
Self::BuiltinPoly { name, params } => {
write!(f, "{name}(")?;
for (i, tp) in params.iter().enumerate() {
if i > 0 {
@ -1430,7 +1463,9 @@ impl HasType for Type {
// Self::And(ts) | Self::Or(ts) => ,
Self::Subr(_sub) => todo!(),
Self::Callable { param_ts, .. } => param_ts.clone(),
Self::Poly { params, .. } => params.iter().filter_map(get_t_from_tp).collect(),
Self::BuiltinPoly { params, .. }
| Self::Poly { params, .. }
| Self::PolyQVar { params, .. } => params.iter().filter_map(get_t_from_tp).collect(),
_ => vec![],
}
}
@ -1488,7 +1523,9 @@ impl HasLevel for Type {
t.update_level(level);
}
}
Self::Poly { params, .. } => {
Self::Poly { params, .. }
| Self::BuiltinPoly { params, .. }
| Self::PolyQVar { params, .. } => {
for p in params.iter() {
p.update_level(level);
}
@ -1549,7 +1586,9 @@ impl HasLevel for Type {
t.lift();
}
}
Self::Poly { params, .. } => {
Self::Poly { params, .. }
| Self::BuiltinPoly { params, .. }
| Self::PolyQVar { params, .. } => {
for p in params.iter() {
p.lift();
}
@ -1622,7 +1661,6 @@ impl Type {
| Self::Str
| Self::NoneType
| Self::Code
| Self::Module
| Self::Frame
| Self::Error
| Self::Inf
@ -1648,8 +1686,10 @@ impl Type {
}
}
Self::BuiltinMono(name)
| Self::Mono { name, .. }
| Self::MonoQVar(name)
| Self::Poly { name, .. }
| Self::BuiltinPoly { name, .. }
| Self::PolyQVar { name, .. }
| Self::MonoProj { rhs: name, .. } => name.ends_with('!'),
Self::Refinement(refine) => refine.t.is_mut(),
@ -1661,11 +1701,13 @@ impl Type {
match self {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_nonelike(),
Self::NoneType => true,
Self::Poly { name, params } if &name[..] == "Option" || &name[..] == "Option!" => {
Self::BuiltinPoly { name, params, .. }
if &name[..] == "Option" || &name[..] == "Option!" =>
{
let inner_t = enum_unwrap!(params.first().unwrap(), TyParam::Type);
inner_t.is_nonelike()
}
Self::Poly { name, params } if &name[..] == "Tuple" => params.is_empty(),
Self::BuiltinPoly { name, params, .. } if &name[..] == "Tuple" => params.is_empty(),
Self::Refinement(refine) => refine.t.is_nonelike(),
_ => false,
}
@ -1693,7 +1735,9 @@ impl Type {
.map(|(sub, sup)| sub.contains_tvar(name) || sup.contains_tvar(name))
.unwrap_or(false)
}
Self::Poly { params, .. } => {
Self::Poly { params, .. }
| Self::BuiltinPoly { params, .. }
| Self::PolyQVar { params, .. } => {
for param in params.iter() {
match param {
TyParam::Type(t) if t.contains_tvar(name) => {
@ -1766,7 +1810,6 @@ impl Type {
Self::Trait => Str::ever("TraitType"),
Self::Patch => Str::ever("Patch"),
Self::Code => Str::ever("Code"),
Self::Module => Str::ever("Module"),
Self::Frame => Str::ever("Frame"),
Self::Error => Str::ever("Error"),
Self::Inf => Str::ever("Inf"),
@ -1789,7 +1832,9 @@ impl Type {
}) => Str::ever("Proc"),
Self::Callable { .. } => Str::ever("Callable"),
Self::Record(_) => Str::ever("Record"),
Self::Poly { name, .. } | Self::PolyQVar { name, .. } => name.clone(),
Self::Poly { name, .. }
| Self::BuiltinPoly { name, .. }
| Self::PolyQVar { name, .. } => name.clone(),
// NOTE: compiler/codegen/convert_to_python_methodでクラス名を使うため、こうすると都合が良い
Self::Refinement(refine) => refine.t.name(),
Self::Quantified(_) => Str::ever("Quantified"),
@ -1819,7 +1864,7 @@ impl Type {
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()),
Self::MonoQVar(name) | Self::PolyQVar { name, .. } => Some(name.clone()),
_ => None,
}
}
@ -1869,7 +1914,9 @@ impl Type {
quant.unbound_callable.has_unbound_var()
|| quant.bounds.iter().any(|tb| tb.has_qvar())
}
Self::Poly { params, .. } => params.iter().any(|tp| tp.has_qvar()),
Self::Poly { params, .. } | Self::BuiltinPoly { params, .. } => {
params.iter().any(|tp| tp.has_qvar())
}
Self::MonoProj { lhs, .. } => lhs.has_qvar(),
_ => false,
}
@ -1907,9 +1954,9 @@ impl Type {
Self::Quantified(quant) => {
quant.unbound_callable.is_cachable() || quant.bounds.iter().all(|b| b.is_cachable())
}
Self::Poly { params, .. } | Self::PolyQVar { params, .. } => {
params.iter().all(|p| p.is_cachable())
}
Self::Poly { params, .. }
| Self::BuiltinPoly { params, .. }
| Self::PolyQVar { params, .. } => params.iter().all(|p| p.is_cachable()),
Self::MonoProj { lhs, .. } => lhs.is_cachable(),
_ => true,
}
@ -1958,9 +2005,9 @@ impl Type {
quant.unbound_callable.has_unbound_var()
|| quant.bounds.iter().any(|b| b.has_unbound_var())
}
Self::Poly { params, .. } | Self::PolyQVar { params, .. } => {
params.iter().any(|p| p.has_unbound_var())
}
Self::Poly { params, .. }
| Self::BuiltinPoly { params, .. }
| Self::PolyQVar { params, .. } => params.iter().any(|p| p.has_unbound_var()),
Self::MonoProj { lhs, .. } => lhs.has_no_unbound_var(),
_ => false,
}
@ -1984,7 +2031,9 @@ impl Type {
+ 1,
),
Self::Callable { param_ts, .. } => Some(param_ts.len() + 1),
Self::Poly { params, .. } | Self::PolyQVar { params, .. } => Some(params.len()),
Self::Poly { params, .. }
| Self::BuiltinPoly { params, .. }
| Self::PolyQVar { params, .. } => Some(params.len()),
_ => None,
}
}
@ -2000,7 +2049,9 @@ impl Type {
}
Self::Subr(subr) => subr.typarams(),
Self::Callable { param_ts: _, .. } => todo!(),
Self::Poly { params, .. } | Self::PolyQVar { params, .. } => params.clone(),
Self::Poly { params, .. }
| Self::BuiltinPoly { params, .. }
| Self::PolyQVar { params, .. } => params.clone(),
_ => vec![],
}
}

View file

@ -18,7 +18,7 @@ use erg_common::{dict, fmt_iter, impl_display_from_debug, switch_lang};
use erg_common::{RcArray, Str};
use crate::codeobj::CodeObj;
use crate::constructors::{array, builtin_mono, poly, refinement, tuple};
use crate::constructors::{array, builtin_mono, builtin_poly, refinement, tuple};
use crate::free::fresh_varname;
use crate::typaram::TyParam;
use crate::{ConstSubr, HasType, Predicate, Type};
@ -506,7 +506,7 @@ impl ValueObj {
Self::Float(_) => builtin_mono("Float!"),
Self::Str(_) => builtin_mono("Str!"),
Self::Bool(_) => builtin_mono("Bool!"),
Self::Array(arr) => poly(
Self::Array(arr) => builtin_poly(
"Array!",
vec![
TyParam::t(arr.iter().next().unwrap().class()),