Add Trait, Subsume

This commit is contained in:
Shunsuke Shibayama 2022-09-15 11:37:12 +09:00
parent 12f22f8bed
commit bc67677ad6
5 changed files with 116 additions and 16 deletions

View file

@ -274,7 +274,10 @@ impl Context {
})?
.clone();
let args = self.eval_args(&call.args, __name__)?;
Ok(subr.call(args, __name__.cloned()))
subr.call(args, __name__.cloned()).map_err(|mut e| {
e.loc = call.loc();
EvalError::new(e, self.caused_by())
})
}
Accessor::Attr(_attr) => todo!(),
Accessor::TupleAttr(_attr) => todo!(),

View file

@ -2,8 +2,11 @@ use std::mem;
use erg_common::Str;
use erg_common::astr::AtomicStr;
use erg_common::color::{RED, RESET};
use erg_common::error::{ErrorCore, ErrorKind, Location};
use erg_type::constructors::{and, mono};
use erg_type::value::{TypeKind, TypeObj, ValueObj};
use erg_type::value::{EvalValueResult, TypeKind, TypeObj, ValueObj};
use erg_type::Type;
use erg_type::ValueArgs;
@ -20,31 +23,61 @@ fn value_obj_to_t(value: ValueObj) -> TypeObj {
}
/// Requirement: Type, Impl := Type -> ClassType
pub fn class_func(mut args: ValueArgs, __name__: Option<Str>) -> ValueObj {
let require = args.remove_left_or_key("Requirement").unwrap();
pub fn class_func(mut args: ValueArgs, __name__: Option<Str>) -> EvalValueResult<ValueObj> {
let require = args.remove_left_or_key("Requirement").ok_or_else(|| {
ErrorCore::new(
line!() as usize,
ErrorKind::KeyError,
Location::Unknown,
AtomicStr::from(format!("{RED}Requirement{RESET} is not passed")),
None,
)
})?;
let require = value_obj_to_t(require);
let impls = args.remove_left_or_key("Impl");
let impls = impls.map(value_obj_to_t);
let t = mono(__name__.unwrap_or(Str::ever("<Lambda>")));
ValueObj::gen_t(TypeKind::Class, t, require, impls, None)
Ok(ValueObj::gen_t(TypeKind::Class, t, require, impls, None))
}
/// Super: Type, Impl := Type, Additional := Type -> ClassType
pub fn inherit_func(mut args: ValueArgs, __name__: Option<Str>) -> ValueObj {
let sup = args.remove_left_or_key("Super").unwrap();
pub fn inherit_func(mut args: ValueArgs, __name__: Option<Str>) -> EvalValueResult<ValueObj> {
let sup = args.remove_left_or_key("Super").ok_or_else(|| {
ErrorCore::new(
line!() as usize,
ErrorKind::KeyError,
Location::Unknown,
AtomicStr::from(format!("{RED}Super{RESET} is not passed")),
None,
)
})?;
let sup = value_obj_to_t(sup);
let impls = args.remove_left_or_key("Impl");
let impls = impls.map(value_obj_to_t);
let additional = args.remove_left_or_key("Additional");
let additional = additional.map(value_obj_to_t);
let t = mono(__name__.unwrap_or(Str::ever("<Lambda>")));
ValueObj::gen_t(TypeKind::Subclass, t, sup, impls, additional)
Ok(ValueObj::gen_t(
TypeKind::Subclass,
t,
sup,
impls,
additional,
))
}
/// Class: ClassType -> ClassType (with `InheritableType`)
/// 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, __name__: Option<Str>) -> ValueObj {
let class = args.remove_left_or_key("Class").unwrap();
pub fn inheritable_func(mut args: ValueArgs, __name__: Option<Str>) -> EvalValueResult<ValueObj> {
let class = args.remove_left_or_key("Class").ok_or_else(|| {
ErrorCore::new(
line!() as usize,
ErrorKind::KeyError,
Location::Unknown,
AtomicStr::from(format!("{RED}Class{RESET} is not passed")),
None,
)
})?;
match class {
ValueObj::Type(TypeObj::Generated(mut gen)) => {
if let Some(typ) = &mut gen.impls {
@ -59,8 +92,52 @@ pub fn inheritable_func(mut args: ValueArgs, __name__: Option<Str>) -> ValueObj
} else {
gen.impls = Some(Box::new(TypeObj::Builtin(mono("InheritableType"))));
}
ValueObj::Type(TypeObj::Generated(gen))
Ok(ValueObj::Type(TypeObj::Generated(gen)))
}
_ => todo!(),
}
}
/// Requirement: Type, Impl := Type -> ClassType
pub fn trait_func(mut args: ValueArgs, __name__: Option<Str>) -> EvalValueResult<ValueObj> {
let require = args.remove_left_or_key("Requirement").ok_or_else(|| {
ErrorCore::new(
line!() as usize,
ErrorKind::KeyError,
Location::Unknown,
AtomicStr::from(format!("{RED}Requirement{RESET} is not passed")),
None,
)
})?;
let require = value_obj_to_t(require);
let impls = args.remove_left_or_key("Impl");
let impls = impls.map(value_obj_to_t);
let t = mono(__name__.unwrap_or(Str::ever("<Lambda>")));
Ok(ValueObj::gen_t(TypeKind::Trait, t, require, impls, None))
}
/// Super: Type, Impl := Type, Additional := Type -> ClassType
pub fn subsume_func(mut args: ValueArgs, __name__: Option<Str>) -> EvalValueResult<ValueObj> {
let sup = args.remove_left_or_key("Super").ok_or_else(|| {
ErrorCore::new(
line!() as usize,
ErrorKind::KeyError,
Location::Unknown,
AtomicStr::from(format!("{RED}Super{RESET} is not passed")),
None,
)
})?;
let sup = value_obj_to_t(sup);
let impls = args.remove_left_or_key("Impl");
let impls = impls.map(value_obj_to_t);
let additional = args.remove_left_or_key("Additional");
let additional = additional.map(value_obj_to_t);
let t = mono(__name__.unwrap_or(Str::ever("<Lambda>")));
Ok(ValueObj::gen_t(
TypeKind::Subtrait,
t,
sup,
impls,
additional,
))
}

View file

@ -17,7 +17,7 @@ use Type::*;
use erg_parser::ast::VarName;
use crate::context::initialize::const_func::{class_func, inherit_func, inheritable_func};
use crate::context::initialize::const_func::*;
use crate::context::instantiate::{ConstTemplate, TyVarContext};
use crate::context::{ClassDefType, Context, ContextKind, DefaultInfo, ParamSpec, TraitInstance};
use crate::varinfo::{Mutability, VarInfo, VarKind};
@ -1496,6 +1496,22 @@ impl Context {
);
let inherit = ConstSubr::Builtin(BuiltinConstSubr::new("Inherit", inherit_func, inherit_t));
self.register_builtin_const("Inherit", ValueObj::Subr(inherit));
let trait_t = func(
vec![param_t("Requirement", Type)],
None,
vec![param_t("Impl", Type)],
Trait,
);
let trait_ = ConstSubr::Builtin(BuiltinConstSubr::new("Trait", trait_func, trait_t));
self.register_builtin_const("Trait", ValueObj::Subr(trait_));
let subsume_t = func(
vec![param_t("Super", Trait)],
None,
vec![param_t("Impl", Type), param_t("Additional", Type)],
Trait,
);
let subsume = ConstSubr::Builtin(BuiltinConstSubr::new("Subsume", subsume_func, subsume_t));
self.register_builtin_const("Subsume", ValueObj::Subr(subsume));
// decorators
let inheritable_t = func1(Class, Class);
let inheritable = ConstSubr::Builtin(BuiltinConstSubr::new(