mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-01 21:21:10 +00:00
WIP: impl Trait
This commit is contained in:
parent
346d00fcd8
commit
aa527dcbc8
11 changed files with 227 additions and 51 deletions
|
@ -16,10 +16,12 @@ use erg_parser::token::{Token, TokenKind};
|
||||||
use erg_type::constructors::{enum_t, mono, mono_proj, poly, ref_, ref_mut, refinement, subr_t};
|
use erg_type::constructors::{enum_t, mono, mono_proj, poly, ref_, ref_mut, refinement, subr_t};
|
||||||
use erg_type::typaram::{OpKind, TyParam};
|
use erg_type::typaram::{OpKind, TyParam};
|
||||||
use erg_type::value::ValueObj;
|
use erg_type::value::ValueObj;
|
||||||
use erg_type::{ConstSubr, HasType, Predicate, TyBound, Type, UserConstSubr, ValueArgs};
|
use erg_type::{
|
||||||
|
ConstSubr, HasType, ParamTy, Predicate, SubrKind, TyBound, Type, UserConstSubr, ValueArgs,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::context::instantiate::TyVarContext;
|
use crate::context::instantiate::TyVarContext;
|
||||||
use crate::context::{ClassDefType, Context};
|
use crate::context::{ClassDefType, Context, RegistrationMode};
|
||||||
use crate::error::{EvalError, EvalResult, TyCheckResult};
|
use crate::error::{EvalError, EvalResult, TyCheckResult};
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -343,7 +345,7 @@ impl Context {
|
||||||
fn eval_const_normal_record(&self, record: &NormalRecord) -> EvalResult<ValueObj> {
|
fn eval_const_normal_record(&self, record: &NormalRecord) -> EvalResult<ValueObj> {
|
||||||
let mut attrs = vec![];
|
let mut attrs = vec![];
|
||||||
// HACK: should avoid cloning
|
// HACK: should avoid cloning
|
||||||
let mut record_ctx = Context::instant(Str::ever("<unnamed record>"), 2, self.clone());
|
let mut record_ctx = Context::instant(Str::ever("<unnamed record>"), 0, self.clone());
|
||||||
for attr in record.attrs.iter() {
|
for attr in record.attrs.iter() {
|
||||||
let name = attr.sig.ident().map(|i| i.inspect());
|
let name = attr.sig.ident().map(|i| i.inspect());
|
||||||
let elem = record_ctx.eval_const_block(&attr.body.block, name)?;
|
let elem = record_ctx.eval_const_block(&attr.body.block, name)?;
|
||||||
|
@ -360,11 +362,63 @@ impl Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_const_lambda(&self, lambda: &Lambda) -> EvalResult<ValueObj> {
|
fn eval_const_lambda(&self, lambda: &Lambda) -> EvalResult<ValueObj> {
|
||||||
|
let mut non_default_params = Vec::with_capacity(lambda.sig.params.non_defaults.len());
|
||||||
|
for sig in lambda.sig.params.non_defaults.iter() {
|
||||||
|
let t = self.instantiate_param_sig_t(sig, None, RegistrationMode::Normal)?;
|
||||||
|
let pt = if let Some(name) = sig.inspect() {
|
||||||
|
ParamTy::kw(name.clone(), t)
|
||||||
|
} else {
|
||||||
|
ParamTy::anonymous(t)
|
||||||
|
};
|
||||||
|
non_default_params.push(pt);
|
||||||
|
}
|
||||||
|
let var_params = if let Some(p) = lambda.sig.params.var_args.as_ref() {
|
||||||
|
let t = self.instantiate_param_sig_t(p, None, RegistrationMode::Normal)?;
|
||||||
|
let pt = if let Some(name) = p.inspect() {
|
||||||
|
ParamTy::kw(name.clone(), t)
|
||||||
|
} else {
|
||||||
|
ParamTy::anonymous(t)
|
||||||
|
};
|
||||||
|
Some(pt)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let mut default_params = Vec::with_capacity(lambda.sig.params.defaults.len());
|
||||||
|
for sig in lambda.sig.params.defaults.iter() {
|
||||||
|
let t = self.instantiate_param_sig_t(sig, None, RegistrationMode::Normal)?;
|
||||||
|
let pt = if let Some(name) = sig.inspect() {
|
||||||
|
ParamTy::kw(name.clone(), t)
|
||||||
|
} else {
|
||||||
|
ParamTy::anonymous(t)
|
||||||
|
};
|
||||||
|
default_params.push(pt);
|
||||||
|
}
|
||||||
|
// HACK: should avoid cloning
|
||||||
|
let mut lambda_ctx = Context::instant(Str::ever("<lambda>"), 0, self.clone());
|
||||||
|
let return_t = lambda_ctx.eval_const_block(&lambda.body, None)?;
|
||||||
|
// FIXME: lambda: i: Int -> Int
|
||||||
|
// => sig_t: (i: Type) -> Type
|
||||||
|
// => as_type: (i: Int) -> Int
|
||||||
|
let sig_t = subr_t(
|
||||||
|
SubrKind::from(lambda.op.kind),
|
||||||
|
non_default_params.clone(),
|
||||||
|
var_params.clone(),
|
||||||
|
default_params.clone(),
|
||||||
|
enum_t(set![return_t.clone()]),
|
||||||
|
);
|
||||||
|
let as_type = subr_t(
|
||||||
|
SubrKind::from(lambda.op.kind),
|
||||||
|
non_default_params,
|
||||||
|
var_params,
|
||||||
|
default_params,
|
||||||
|
return_t.as_type().ok_or_else(|| todo!())?.into_typ(),
|
||||||
|
);
|
||||||
let subr = ConstSubr::User(UserConstSubr::new(
|
let subr = ConstSubr::User(UserConstSubr::new(
|
||||||
Str::ever("<lambda>"),
|
Str::ever("<lambda>"),
|
||||||
lambda.sig.params.clone(),
|
lambda.sig.params.clone(),
|
||||||
lambda.body.clone(),
|
lambda.body.clone(),
|
||||||
Type::Uninited,
|
sig_t,
|
||||||
|
Some(as_type),
|
||||||
));
|
));
|
||||||
Ok(ValueObj::Subr(subr))
|
Ok(ValueObj::Subr(subr))
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,24 +7,8 @@ use erg_common::color::{RED, RESET};
|
||||||
use erg_common::error::{ErrorCore, ErrorKind, Location};
|
use erg_common::error::{ErrorCore, ErrorKind, Location};
|
||||||
use erg_type::constructors::{and, mono};
|
use erg_type::constructors::{and, mono};
|
||||||
use erg_type::value::{EvalValueResult, TypeKind, TypeObj, ValueObj};
|
use erg_type::value::{EvalValueResult, TypeKind, TypeObj, ValueObj};
|
||||||
use erg_type::Type;
|
|
||||||
use erg_type::ValueArgs;
|
use erg_type::ValueArgs;
|
||||||
|
|
||||||
fn value_obj_to_t(value: ValueObj) -> TypeObj {
|
|
||||||
match value {
|
|
||||||
ValueObj::Type(t) => t,
|
|
||||||
ValueObj::Record(rec) => TypeObj::Builtin(Type::Record(
|
|
||||||
rec.into_iter()
|
|
||||||
.map(|(k, v)| (k, value_obj_to_t(v).typ().clone()))
|
|
||||||
.collect(),
|
|
||||||
)),
|
|
||||||
ValueObj::Subr(subr) => {
|
|
||||||
todo!("{subr}")
|
|
||||||
}
|
|
||||||
other => todo!("{other}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Requirement: Type, Impl := Type -> ClassType
|
/// Requirement: Type, Impl := Type -> ClassType
|
||||||
pub fn class_func(mut args: ValueArgs, __name__: Option<Str>) -> EvalValueResult<ValueObj> {
|
pub fn class_func(mut args: ValueArgs, __name__: Option<Str>) -> EvalValueResult<ValueObj> {
|
||||||
let require = args.remove_left_or_key("Requirement").ok_or_else(|| {
|
let require = args.remove_left_or_key("Requirement").ok_or_else(|| {
|
||||||
|
@ -36,9 +20,9 @@ pub fn class_func(mut args: ValueArgs, __name__: Option<Str>) -> EvalValueResult
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
let require = value_obj_to_t(require);
|
let require = require.as_type().unwrap();
|
||||||
let impls = args.remove_left_or_key("Impl");
|
let impls = args.remove_left_or_key("Impl");
|
||||||
let impls = impls.map(value_obj_to_t);
|
let impls = impls.map(|v| v.as_type().unwrap());
|
||||||
let t = mono(__name__.unwrap_or(Str::ever("<Lambda>")));
|
let t = mono(__name__.unwrap_or(Str::ever("<Lambda>")));
|
||||||
Ok(ValueObj::gen_t(TypeKind::Class, t, require, impls, None))
|
Ok(ValueObj::gen_t(TypeKind::Class, t, require, impls, None))
|
||||||
}
|
}
|
||||||
|
@ -54,11 +38,11 @@ pub fn inherit_func(mut args: ValueArgs, __name__: Option<Str>) -> EvalValueResu
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
let sup = value_obj_to_t(sup);
|
let sup = sup.as_type().unwrap();
|
||||||
let impls = args.remove_left_or_key("Impl");
|
let impls = args.remove_left_or_key("Impl");
|
||||||
let impls = impls.map(value_obj_to_t);
|
let impls = impls.map(|v| v.as_type().unwrap());
|
||||||
let additional = args.remove_left_or_key("Additional");
|
let additional = args.remove_left_or_key("Additional");
|
||||||
let additional = additional.map(value_obj_to_t);
|
let additional = additional.map(|v| v.as_type().unwrap());
|
||||||
let t = mono(__name__.unwrap_or(Str::ever("<Lambda>")));
|
let t = mono(__name__.unwrap_or(Str::ever("<Lambda>")));
|
||||||
Ok(ValueObj::gen_t(
|
Ok(ValueObj::gen_t(
|
||||||
TypeKind::Subclass,
|
TypeKind::Subclass,
|
||||||
|
@ -112,9 +96,9 @@ pub fn trait_func(mut args: ValueArgs, __name__: Option<Str>) -> EvalValueResult
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
let require = value_obj_to_t(require);
|
let require = require.as_type().unwrap();
|
||||||
let impls = args.remove_left_or_key("Impl");
|
let impls = args.remove_left_or_key("Impl");
|
||||||
let impls = impls.map(value_obj_to_t);
|
let impls = impls.map(|v| v.as_type().unwrap());
|
||||||
let t = mono(__name__.unwrap_or(Str::ever("<Lambda>")));
|
let t = mono(__name__.unwrap_or(Str::ever("<Lambda>")));
|
||||||
Ok(ValueObj::gen_t(TypeKind::Trait, t, require, impls, None))
|
Ok(ValueObj::gen_t(TypeKind::Trait, t, require, impls, None))
|
||||||
}
|
}
|
||||||
|
@ -130,11 +114,11 @@ pub fn subsume_func(mut args: ValueArgs, __name__: Option<Str>) -> EvalValueResu
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
let sup = value_obj_to_t(sup);
|
let sup = sup.as_type().unwrap();
|
||||||
let impls = args.remove_left_or_key("Impl");
|
let impls = args.remove_left_or_key("Impl");
|
||||||
let impls = impls.map(value_obj_to_t);
|
let impls = impls.map(|v| v.as_type().unwrap());
|
||||||
let additional = args.remove_left_or_key("Additional");
|
let additional = args.remove_left_or_key("Additional");
|
||||||
let additional = additional.map(value_obj_to_t);
|
let additional = additional.map(|v| v.as_type().unwrap());
|
||||||
let t = mono(__name__.unwrap_or(Str::ever("<Lambda>")));
|
let t = mono(__name__.unwrap_or(Str::ever("<Lambda>")));
|
||||||
Ok(ValueObj::gen_t(
|
Ok(ValueObj::gen_t(
|
||||||
TypeKind::Subtrait,
|
TypeKind::Subtrait,
|
||||||
|
|
|
@ -1486,7 +1486,7 @@ impl Context {
|
||||||
vec![param_t("Impl", Type)],
|
vec![param_t("Impl", Type)],
|
||||||
Class,
|
Class,
|
||||||
);
|
);
|
||||||
let class = ConstSubr::Builtin(BuiltinConstSubr::new("Class", class_func, class_t));
|
let class = ConstSubr::Builtin(BuiltinConstSubr::new("Class", class_func, class_t, None));
|
||||||
self.register_builtin_const("Class", ValueObj::Subr(class));
|
self.register_builtin_const("Class", ValueObj::Subr(class));
|
||||||
let inherit_t = func(
|
let inherit_t = func(
|
||||||
vec![param_t("Super", Class)],
|
vec![param_t("Super", Class)],
|
||||||
|
@ -1494,7 +1494,12 @@ impl Context {
|
||||||
vec![param_t("Impl", Type), param_t("Additional", Type)],
|
vec![param_t("Impl", Type), param_t("Additional", Type)],
|
||||||
Class,
|
Class,
|
||||||
);
|
);
|
||||||
let inherit = ConstSubr::Builtin(BuiltinConstSubr::new("Inherit", inherit_func, inherit_t));
|
let inherit = ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||||
|
"Inherit",
|
||||||
|
inherit_func,
|
||||||
|
inherit_t,
|
||||||
|
None,
|
||||||
|
));
|
||||||
self.register_builtin_const("Inherit", ValueObj::Subr(inherit));
|
self.register_builtin_const("Inherit", ValueObj::Subr(inherit));
|
||||||
let trait_t = func(
|
let trait_t = func(
|
||||||
vec![param_t("Requirement", Type)],
|
vec![param_t("Requirement", Type)],
|
||||||
|
@ -1502,7 +1507,7 @@ impl Context {
|
||||||
vec![param_t("Impl", Type)],
|
vec![param_t("Impl", Type)],
|
||||||
Trait,
|
Trait,
|
||||||
);
|
);
|
||||||
let trait_ = ConstSubr::Builtin(BuiltinConstSubr::new("Trait", trait_func, trait_t));
|
let trait_ = ConstSubr::Builtin(BuiltinConstSubr::new("Trait", trait_func, trait_t, None));
|
||||||
self.register_builtin_const("Trait", ValueObj::Subr(trait_));
|
self.register_builtin_const("Trait", ValueObj::Subr(trait_));
|
||||||
let subsume_t = func(
|
let subsume_t = func(
|
||||||
vec![param_t("Super", Trait)],
|
vec![param_t("Super", Trait)],
|
||||||
|
@ -1510,7 +1515,12 @@ impl Context {
|
||||||
vec![param_t("Impl", Type), param_t("Additional", Type)],
|
vec![param_t("Impl", Type), param_t("Additional", Type)],
|
||||||
Trait,
|
Trait,
|
||||||
);
|
);
|
||||||
let subsume = ConstSubr::Builtin(BuiltinConstSubr::new("Subsume", subsume_func, subsume_t));
|
let subsume = ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||||
|
"Subsume",
|
||||||
|
subsume_func,
|
||||||
|
subsume_t,
|
||||||
|
None,
|
||||||
|
));
|
||||||
self.register_builtin_const("Subsume", ValueObj::Subr(subsume));
|
self.register_builtin_const("Subsume", ValueObj::Subr(subsume));
|
||||||
// decorators
|
// decorators
|
||||||
let inheritable_t = func1(Class, Class);
|
let inheritable_t = func1(Class, Class);
|
||||||
|
@ -1518,6 +1528,7 @@ impl Context {
|
||||||
"Inheritable",
|
"Inheritable",
|
||||||
inheritable_func,
|
inheritable_func,
|
||||||
inheritable_t,
|
inheritable_t,
|
||||||
|
None,
|
||||||
));
|
));
|
||||||
self.register_builtin_const("Inheritable", ValueObj::Subr(inheritable));
|
self.register_builtin_const("Inheritable", ValueObj::Subr(inheritable));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1259,6 +1259,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// FIXME: if trait, returns a freevar
|
||||||
pub(crate) fn rec_get_self_t(&self) -> Option<Type> {
|
pub(crate) fn rec_get_self_t(&self) -> Option<Type> {
|
||||||
if self.kind.is_method_def() || self.kind.is_type() {
|
if self.kind.is_method_def() || self.kind.is_type() {
|
||||||
// TODO: poly type
|
// TODO: poly type
|
||||||
|
|
|
@ -628,11 +628,7 @@ impl Context {
|
||||||
.collect();
|
.collect();
|
||||||
let return_t = self.instantiate_typespec(&subr.return_t, mode)?;
|
let return_t = self.instantiate_typespec(&subr.return_t, mode)?;
|
||||||
Ok(subr_t(
|
Ok(subr_t(
|
||||||
if subr.arrow.is(TokenKind::FuncArrow) {
|
SubrKind::from(subr.arrow.kind),
|
||||||
SubrKind::Func
|
|
||||||
} else {
|
|
||||||
SubrKind::Proc
|
|
||||||
},
|
|
||||||
non_defaults,
|
non_defaults,
|
||||||
var_args,
|
var_args,
|
||||||
defaults,
|
defaults,
|
||||||
|
|
|
@ -649,6 +649,28 @@ impl Context {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
TypeKind::Trait => {
|
||||||
|
if gen.t.is_monomorphic() {
|
||||||
|
let ctx = Self::mono_trait(gen.t.name(), self.level);
|
||||||
|
self.register_gen_mono_type(ident, gen, ctx, Const);
|
||||||
|
} else {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TypeKind::Subtrait => {
|
||||||
|
if gen.t.is_monomorphic() {
|
||||||
|
let super_classes = vec![gen.require_or_sup.typ().clone()];
|
||||||
|
// let super_traits = gen.impls.iter().map(|to| to.typ().clone()).collect();
|
||||||
|
let mut ctx = Self::mono_trait(gen.t.name(), self.level);
|
||||||
|
for sup in super_classes.into_iter() {
|
||||||
|
let (_, sup_ctx) = self.get_nominal_type_ctx(&sup).unwrap();
|
||||||
|
ctx.register_superclass(sup, sup_ctx);
|
||||||
|
}
|
||||||
|
self.register_gen_mono_type(ident, gen, ctx, Const);
|
||||||
|
} else {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
other => todo!("{other:?}"),
|
other => todo!("{other:?}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1027,6 +1027,9 @@ impl Context {
|
||||||
(Type::MonoProj { .. }, _) => todo!(),
|
(Type::MonoProj { .. }, _) => todo!(),
|
||||||
(_, Type::MonoProj { .. }) => todo!(),
|
(_, Type::MonoProj { .. }) => todo!(),
|
||||||
(Refinement(_), Refinement(_)) => todo!(),
|
(Refinement(_), Refinement(_)) => todo!(),
|
||||||
|
(Type::Subr(_) | Type::Record(_), Type) => Ok(()),
|
||||||
|
// TODO Tuple2, ...
|
||||||
|
(Type::Poly{ 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)"),
|
_ => todo!("{maybe_sub} can be a subtype of {maybe_sup}, but failed to semi-unify (or existential types are not supported)"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -562,7 +562,14 @@ impl ASTLowerer {
|
||||||
name,
|
name,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
self.ctx.grow(name, ContextKind::Instant, def.sig.vis())?;
|
let kind = if def.is_class_def() {
|
||||||
|
ContextKind::Class
|
||||||
|
} else if def.is_trait_def() {
|
||||||
|
ContextKind::Trait
|
||||||
|
} else {
|
||||||
|
ContextKind::Instant
|
||||||
|
};
|
||||||
|
self.ctx.grow(name, kind, def.sig.vis())?;
|
||||||
let res = match def.sig {
|
let res = match def.sig {
|
||||||
ast::Signature::Subr(sig) => self.lower_subr_def(sig, def.body),
|
ast::Signature::Subr(sig) => self.lower_subr_def(sig, def.body),
|
||||||
ast::Signature::Var(sig) => self.lower_var_def(sig, def.body),
|
ast::Signature::Var(sig) => self.lower_var_def(sig, def.body),
|
||||||
|
|
|
@ -225,6 +225,20 @@ impl Args {
|
||||||
pub fn push_kw(&mut self, arg: KwArg) {
|
pub fn push_kw(&mut self, arg: KwArg) {
|
||||||
self.kw_args.push(arg);
|
self.kw_args.push(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_left_or_key(&self, key: &str) -> Option<&Expr> {
|
||||||
|
if !self.pos_args.is_empty() {
|
||||||
|
self.pos_args.get(0).map(|a| &a.expr)
|
||||||
|
} else {
|
||||||
|
self.kw_args.iter().find_map(|a| {
|
||||||
|
if &a.keyword.content[..] == key {
|
||||||
|
Some(&a.expr)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
@ -2862,6 +2876,34 @@ impl Def {
|
||||||
pub const fn is_subr(&self) -> bool {
|
pub const fn is_subr(&self) -> bool {
|
||||||
matches!(&self.sig, Signature::Subr(_))
|
matches!(&self.sig, Signature::Subr(_))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_class_def(&self) -> bool {
|
||||||
|
match self.body.block.first().unwrap() {
|
||||||
|
Expr::Call(call)
|
||||||
|
if call.obj.get_name().map(|n| &n[..]) == Some("Class")
|
||||||
|
|| call.obj.get_name().map(|n| &n[..]) == Some("Inherit") =>
|
||||||
|
{
|
||||||
|
true
|
||||||
|
}
|
||||||
|
Expr::Call(call) if call.obj.get_name().map(|n| &n[..]) == Some("Inheritable") => {
|
||||||
|
if let Some(Expr::Call(inner)) = call.args.get_left_or_key("Class") {
|
||||||
|
inner.obj.get_name().map(|n| &n[..]) == Some("Class")
|
||||||
|
|| inner.obj.get_name().map(|n| &n[..]) == Some("Inherit")
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_trait_def(&self) -> bool {
|
||||||
|
matches!(
|
||||||
|
self.body.block.first().unwrap(),
|
||||||
|
Expr::Call(call) if call.obj.get_name().map(|n| &n[..]) == Some("Trait")
|
||||||
|
|| call.obj.get_name().map(|n| &n[..]) == Some("Subsume")
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// e.g.
|
/// e.g.
|
||||||
|
|
|
@ -20,6 +20,7 @@ use erg_common::vis::Field;
|
||||||
use erg_common::{enum_unwrap, fmt_option, fmt_set_split_with, set, Str};
|
use erg_common::{enum_unwrap, fmt_option, fmt_set_split_with, set, Str};
|
||||||
|
|
||||||
use erg_parser::ast::{Block, Params};
|
use erg_parser::ast::{Block, Params};
|
||||||
|
use erg_parser::token::TokenKind;
|
||||||
|
|
||||||
use crate::constructors::{int_interval, mono, mono_q};
|
use crate::constructors::{int_interval, mono, mono_q};
|
||||||
use crate::free::{
|
use crate::free::{
|
||||||
|
@ -135,16 +136,24 @@ pub struct UserConstSubr {
|
||||||
name: Str,
|
name: Str,
|
||||||
params: Params,
|
params: Params,
|
||||||
block: Block,
|
block: Block,
|
||||||
t: Type,
|
sig_t: Type,
|
||||||
|
as_type: Option<Type>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserConstSubr {
|
impl UserConstSubr {
|
||||||
pub const fn new(name: Str, params: Params, block: Block, t: Type) -> Self {
|
pub const fn new(
|
||||||
|
name: Str,
|
||||||
|
params: Params,
|
||||||
|
block: Block,
|
||||||
|
sig_t: Type,
|
||||||
|
as_type: Option<Type>,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name,
|
name,
|
||||||
params,
|
params,
|
||||||
block,
|
block,
|
||||||
t,
|
sig_t,
|
||||||
|
as_type,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -173,7 +182,8 @@ impl ValueArgs {
|
||||||
pub struct BuiltinConstSubr {
|
pub struct BuiltinConstSubr {
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
subr: fn(ValueArgs, Option<Str>) -> EvalValueResult<ValueObj>,
|
subr: fn(ValueArgs, Option<Str>) -> EvalValueResult<ValueObj>,
|
||||||
t: Type,
|
sig_t: Type,
|
||||||
|
as_type: Option<Type>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for BuiltinConstSubr {
|
impl fmt::Display for BuiltinConstSubr {
|
||||||
|
@ -186,9 +196,15 @@ impl BuiltinConstSubr {
|
||||||
pub const fn new(
|
pub const fn new(
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
subr: fn(ValueArgs, Option<Str>) -> EvalValueResult<ValueObj>,
|
subr: fn(ValueArgs, Option<Str>) -> EvalValueResult<ValueObj>,
|
||||||
t: Type,
|
sig_t: Type,
|
||||||
|
as_type: Option<Type>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self { name, subr, t }
|
Self {
|
||||||
|
name,
|
||||||
|
subr,
|
||||||
|
sig_t,
|
||||||
|
as_type,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn call(&self, args: ValueArgs, __name__: Option<Str>) -> EvalValueResult<ValueObj> {
|
pub fn call(&self, args: ValueArgs, __name__: Option<Str>) -> EvalValueResult<ValueObj> {
|
||||||
|
@ -214,10 +230,17 @@ impl fmt::Display for ConstSubr {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConstSubr {
|
impl ConstSubr {
|
||||||
pub fn class(&self) -> Type {
|
pub fn sig_t(&self) -> &Type {
|
||||||
match self {
|
match self {
|
||||||
ConstSubr::User(user) => user.t.clone(),
|
ConstSubr::User(user) => &user.sig_t,
|
||||||
ConstSubr::Builtin(builtin) => builtin.t.clone(),
|
ConstSubr::Builtin(builtin) => &builtin.sig_t,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_type(&self) -> Option<&Type> {
|
||||||
|
match self {
|
||||||
|
ConstSubr::User(user) => user.as_type.as_ref(),
|
||||||
|
ConstSubr::Builtin(builtin) => builtin.as_type.as_ref(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -976,6 +999,16 @@ pub enum SubrKind {
|
||||||
Proc,
|
Proc,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<TokenKind> for SubrKind {
|
||||||
|
fn from(op_kind: TokenKind) -> Self {
|
||||||
|
match op_kind {
|
||||||
|
TokenKind::FuncArrow => Self::Func,
|
||||||
|
TokenKind::ProcArrow => Self::Proc,
|
||||||
|
_ => panic!("invalid token kind for subr kind"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl SubrKind {
|
impl SubrKind {
|
||||||
pub const fn arrow(&self) -> Str {
|
pub const fn arrow(&self) -> Str {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -14,7 +14,7 @@ use erg_common::rccell::RcCell;
|
||||||
use erg_common::serialize::*;
|
use erg_common::serialize::*;
|
||||||
use erg_common::set;
|
use erg_common::set;
|
||||||
use erg_common::vis::Field;
|
use erg_common::vis::Field;
|
||||||
use erg_common::{fmt_iter, impl_display_from_debug, switch_lang};
|
use erg_common::{dict, fmt_iter, impl_display_from_debug, switch_lang};
|
||||||
use erg_common::{RcArray, Str};
|
use erg_common::{RcArray, Str};
|
||||||
|
|
||||||
use crate::codeobj::CodeObj;
|
use crate::codeobj::CodeObj;
|
||||||
|
@ -99,6 +99,13 @@ impl TypeObj {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn into_typ(self) -> Type {
|
||||||
|
match self {
|
||||||
|
TypeObj::Builtin(t) => t,
|
||||||
|
TypeObj::Generated(t) => t.t,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn contains_intersec(&self, other: &Type) -> bool {
|
pub fn contains_intersec(&self, other: &Type) -> bool {
|
||||||
match self {
|
match self {
|
||||||
TypeObj::Builtin(t) => t.contains_intersec(other),
|
TypeObj::Builtin(t) => t.contains_intersec(other),
|
||||||
|
@ -482,7 +489,7 @@ impl ValueObj {
|
||||||
Self::Record(rec) => {
|
Self::Record(rec) => {
|
||||||
Type::Record(rec.iter().map(|(k, v)| (k.clone(), v.class())).collect())
|
Type::Record(rec.iter().map(|(k, v)| (k.clone(), v.class())).collect())
|
||||||
}
|
}
|
||||||
Self::Subr(subr) => subr.class(),
|
Self::Subr(subr) => subr.sig_t().clone(),
|
||||||
Self::Type(t_obj) => match t_obj {
|
Self::Type(t_obj) => match t_obj {
|
||||||
// TODO: builtin
|
// TODO: builtin
|
||||||
TypeObj::Builtin(_t) => Type::Type,
|
TypeObj::Builtin(_t) => Type::Type,
|
||||||
|
@ -771,6 +778,22 @@ impl ValueObj {
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn as_type(&self) -> Option<TypeObj> {
|
||||||
|
match self {
|
||||||
|
Self::Type(t) => Some(t.clone()),
|
||||||
|
Self::Record(rec) => {
|
||||||
|
let mut attr_ts = dict! {};
|
||||||
|
for (k, v) in rec.iter() {
|
||||||
|
attr_ts.insert(k.clone(), v.as_type()?.typ().clone());
|
||||||
|
}
|
||||||
|
Some(TypeObj::Builtin(Type::Record(attr_ts)))
|
||||||
|
}
|
||||||
|
Self::Subr(subr) => Some(TypeObj::Builtin(subr.as_type().unwrap().clone())),
|
||||||
|
Self::Array(_) | Self::Tuple(_) | Self::Dict(_) => todo!(),
|
||||||
|
_other => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod value_set {
|
pub mod value_set {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue