diff --git a/compiler/erg_compiler/context/eval.rs b/compiler/erg_compiler/context/eval.rs index baa158d4..e251521d 100644 --- a/compiler/erg_compiler/context/eval.rs +++ b/compiler/erg_compiler/context/eval.rs @@ -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::typaram::{OpKind, TyParam}; 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::{ClassDefType, Context}; +use crate::context::{ClassDefType, Context, RegistrationMode}; use crate::error::{EvalError, EvalResult, TyCheckResult}; #[inline] @@ -343,7 +345,7 @@ impl Context { fn eval_const_normal_record(&self, record: &NormalRecord) -> EvalResult { let mut attrs = vec![]; // HACK: should avoid cloning - let mut record_ctx = Context::instant(Str::ever(""), 2, self.clone()); + let mut record_ctx = Context::instant(Str::ever(""), 0, self.clone()); for attr in record.attrs.iter() { let name = attr.sig.ident().map(|i| i.inspect()); 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 { + 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(""), 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( Str::ever(""), lambda.sig.params.clone(), lambda.body.clone(), - Type::Uninited, + sig_t, + Some(as_type), )); Ok(ValueObj::Subr(subr)) } diff --git a/compiler/erg_compiler/context/initialize/const_func.rs b/compiler/erg_compiler/context/initialize/const_func.rs index 6313b8b8..ff1610b4 100644 --- a/compiler/erg_compiler/context/initialize/const_func.rs +++ b/compiler/erg_compiler/context/initialize/const_func.rs @@ -7,24 +7,8 @@ use erg_common::color::{RED, RESET}; use erg_common::error::{ErrorCore, ErrorKind, Location}; use erg_type::constructors::{and, mono}; use erg_type::value::{EvalValueResult, TypeKind, TypeObj, ValueObj}; -use erg_type::Type; 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 pub fn class_func(mut args: ValueArgs, __name__: Option) -> EvalValueResult { let require = args.remove_left_or_key("Requirement").ok_or_else(|| { @@ -36,9 +20,9 @@ pub fn class_func(mut args: ValueArgs, __name__: Option) -> EvalValueResult None, ) })?; - let require = value_obj_to_t(require); + let require = require.as_type().unwrap(); 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(""))); Ok(ValueObj::gen_t(TypeKind::Class, t, require, impls, None)) } @@ -54,11 +38,11 @@ pub fn inherit_func(mut args: ValueArgs, __name__: Option) -> EvalValueResu None, ) })?; - let sup = value_obj_to_t(sup); + let sup = sup.as_type().unwrap(); 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 = additional.map(value_obj_to_t); + let additional = additional.map(|v| v.as_type().unwrap()); let t = mono(__name__.unwrap_or(Str::ever(""))); Ok(ValueObj::gen_t( TypeKind::Subclass, @@ -112,9 +96,9 @@ pub fn trait_func(mut args: ValueArgs, __name__: Option) -> EvalValueResult None, ) })?; - let require = value_obj_to_t(require); + let require = require.as_type().unwrap(); 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(""))); Ok(ValueObj::gen_t(TypeKind::Trait, t, require, impls, None)) } @@ -130,11 +114,11 @@ pub fn subsume_func(mut args: ValueArgs, __name__: Option) -> EvalValueResu None, ) })?; - let sup = value_obj_to_t(sup); + let sup = sup.as_type().unwrap(); 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 = additional.map(value_obj_to_t); + let additional = additional.map(|v| v.as_type().unwrap()); let t = mono(__name__.unwrap_or(Str::ever(""))); Ok(ValueObj::gen_t( TypeKind::Subtrait, diff --git a/compiler/erg_compiler/context/initialize/mod.rs b/compiler/erg_compiler/context/initialize/mod.rs index 8091bcfc..44d542e5 100644 --- a/compiler/erg_compiler/context/initialize/mod.rs +++ b/compiler/erg_compiler/context/initialize/mod.rs @@ -1486,7 +1486,7 @@ impl Context { vec![param_t("Impl", Type)], 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)); let inherit_t = func( vec![param_t("Super", Class)], @@ -1494,7 +1494,12 @@ impl Context { vec![param_t("Impl", Type), param_t("Additional", Type)], 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)); let trait_t = func( vec![param_t("Requirement", Type)], @@ -1502,7 +1507,7 @@ impl Context { vec![param_t("Impl", Type)], 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_)); let subsume_t = func( vec![param_t("Super", Trait)], @@ -1510,7 +1515,12 @@ impl Context { vec![param_t("Impl", Type), param_t("Additional", Type)], 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)); // decorators let inheritable_t = func1(Class, Class); @@ -1518,6 +1528,7 @@ impl Context { "Inheritable", inheritable_func, inheritable_t, + None, )); self.register_builtin_const("Inheritable", ValueObj::Subr(inheritable)); } diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index b4c4fcc0..4729ecc4 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -1259,6 +1259,7 @@ impl Context { } } + /// FIXME: if trait, returns a freevar pub(crate) fn rec_get_self_t(&self) -> Option { if self.kind.is_method_def() || self.kind.is_type() { // TODO: poly type diff --git a/compiler/erg_compiler/context/instantiate.rs b/compiler/erg_compiler/context/instantiate.rs index 7f9b42a5..f9541704 100644 --- a/compiler/erg_compiler/context/instantiate.rs +++ b/compiler/erg_compiler/context/instantiate.rs @@ -628,11 +628,7 @@ impl Context { .collect(); let return_t = self.instantiate_typespec(&subr.return_t, mode)?; Ok(subr_t( - if subr.arrow.is(TokenKind::FuncArrow) { - SubrKind::Func - } else { - SubrKind::Proc - }, + SubrKind::from(subr.arrow.kind), non_defaults, var_args, defaults, diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index 56d70658..93194b1b 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -649,6 +649,28 @@ impl Context { 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:?}"), } } diff --git a/compiler/erg_compiler/context/tyvar.rs b/compiler/erg_compiler/context/tyvar.rs index 18dcae83..a58a82f2 100644 --- a/compiler/erg_compiler/context/tyvar.rs +++ b/compiler/erg_compiler/context/tyvar.rs @@ -1027,6 +1027,9 @@ impl Context { (Type::MonoProj { .. }, _) => todo!(), (_, Type::MonoProj { .. }) => 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)"), } } diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index 0719e743..bec72111 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -562,7 +562,14 @@ impl ASTLowerer { 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 { ast::Signature::Subr(sig) => self.lower_subr_def(sig, def.body), ast::Signature::Var(sig) => self.lower_var_def(sig, def.body), diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index b03d2b97..8a79e214 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -225,6 +225,20 @@ impl Args { pub fn push_kw(&mut self, arg: KwArg) { 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)] @@ -2862,6 +2876,34 @@ impl Def { pub const fn is_subr(&self) -> bool { 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. diff --git a/compiler/erg_type/lib.rs b/compiler/erg_type/lib.rs index 77852850..67c0e121 100644 --- a/compiler/erg_type/lib.rs +++ b/compiler/erg_type/lib.rs @@ -20,6 +20,7 @@ use erg_common::vis::Field; use erg_common::{enum_unwrap, fmt_option, fmt_set_split_with, set, Str}; use erg_parser::ast::{Block, Params}; +use erg_parser::token::TokenKind; use crate::constructors::{int_interval, mono, mono_q}; use crate::free::{ @@ -135,16 +136,24 @@ pub struct UserConstSubr { name: Str, params: Params, block: Block, - t: Type, + sig_t: Type, + as_type: Option, } 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, + ) -> Self { Self { name, params, block, - t, + sig_t, + as_type, } } } @@ -173,7 +182,8 @@ impl ValueArgs { pub struct BuiltinConstSubr { name: &'static str, subr: fn(ValueArgs, Option) -> EvalValueResult, - t: Type, + sig_t: Type, + as_type: Option, } impl fmt::Display for BuiltinConstSubr { @@ -186,9 +196,15 @@ impl BuiltinConstSubr { pub const fn new( name: &'static str, subr: fn(ValueArgs, Option) -> EvalValueResult, - t: Type, + sig_t: Type, + as_type: Option, ) -> Self { - Self { name, subr, t } + Self { + name, + subr, + sig_t, + as_type, + } } pub fn call(&self, args: ValueArgs, __name__: Option) -> EvalValueResult { @@ -214,10 +230,17 @@ impl fmt::Display for ConstSubr { } impl ConstSubr { - pub fn class(&self) -> Type { + pub fn sig_t(&self) -> &Type { match self { - ConstSubr::User(user) => user.t.clone(), - ConstSubr::Builtin(builtin) => builtin.t.clone(), + ConstSubr::User(user) => &user.sig_t, + 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, } +impl From 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 { pub const fn arrow(&self) -> Str { match self { diff --git a/compiler/erg_type/value.rs b/compiler/erg_type/value.rs index 9b0fe66e..ea68b3c2 100644 --- a/compiler/erg_type/value.rs +++ b/compiler/erg_type/value.rs @@ -14,7 +14,7 @@ use erg_common::rccell::RcCell; use erg_common::serialize::*; use erg_common::set; 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 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 { match self { TypeObj::Builtin(t) => t.contains_intersec(other), @@ -482,7 +489,7 @@ impl ValueObj { Self::Record(rec) => { 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 { // TODO: builtin TypeObj::Builtin(_t) => Type::Type, @@ -771,6 +778,22 @@ impl ValueObj { _ => None, } } + + pub fn as_type(&self) -> Option { + 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 {