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(); .clone();
let args = self.eval_args(&call.args, __name__)?; 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::Attr(_attr) => todo!(),
Accessor::TupleAttr(_attr) => todo!(), Accessor::TupleAttr(_attr) => todo!(),

View file

@ -2,8 +2,11 @@ use std::mem;
use erg_common::Str; 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::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::Type;
use erg_type::ValueArgs; use erg_type::ValueArgs;
@ -20,31 +23,61 @@ fn value_obj_to_t(value: ValueObj) -> TypeObj {
} }
/// Requirement: Type, Impl := Type -> ClassType /// Requirement: Type, Impl := Type -> ClassType
pub fn class_func(mut args: ValueArgs, __name__: Option<Str>) -> ValueObj { pub fn class_func(mut args: ValueArgs, __name__: Option<Str>) -> EvalValueResult<ValueObj> {
let require = args.remove_left_or_key("Requirement").unwrap(); 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 require = value_obj_to_t(require);
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(value_obj_to_t);
let t = mono(__name__.unwrap_or(Str::ever("<Lambda>"))); 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 /// Super: Type, Impl := Type, Additional := Type -> ClassType
pub fn inherit_func(mut args: ValueArgs, __name__: Option<Str>) -> ValueObj { pub fn inherit_func(mut args: ValueArgs, __name__: Option<Str>) -> EvalValueResult<ValueObj> {
let sup = args.remove_left_or_key("Super").unwrap(); 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 sup = value_obj_to_t(sup);
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(value_obj_to_t);
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(value_obj_to_t);
let t = mono(__name__.unwrap_or(Str::ever("<Lambda>"))); 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`) /// 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. /// 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 { pub fn inheritable_func(mut args: ValueArgs, __name__: Option<Str>) -> EvalValueResult<ValueObj> {
let class = args.remove_left_or_key("Class").unwrap(); 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 { match class {
ValueObj::Type(TypeObj::Generated(mut gen)) => { ValueObj::Type(TypeObj::Generated(mut gen)) => {
if let Some(typ) = &mut gen.impls { if let Some(typ) = &mut gen.impls {
@ -59,8 +92,52 @@ pub fn inheritable_func(mut args: ValueArgs, __name__: Option<Str>) -> ValueObj
} else { } else {
gen.impls = Some(Box::new(TypeObj::Builtin(mono("InheritableType")))); gen.impls = Some(Box::new(TypeObj::Builtin(mono("InheritableType"))));
} }
ValueObj::Type(TypeObj::Generated(gen)) Ok(ValueObj::Type(TypeObj::Generated(gen)))
} }
_ => todo!(), _ => 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 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::instantiate::{ConstTemplate, TyVarContext};
use crate::context::{ClassDefType, Context, ContextKind, DefaultInfo, ParamSpec, TraitInstance}; use crate::context::{ClassDefType, Context, ContextKind, DefaultInfo, ParamSpec, TraitInstance};
use crate::varinfo::{Mutability, VarInfo, VarKind}; use crate::varinfo::{Mutability, VarInfo, VarKind};
@ -1496,6 +1496,22 @@ impl Context {
); );
let inherit = ConstSubr::Builtin(BuiltinConstSubr::new("Inherit", inherit_func, inherit_t)); let inherit = ConstSubr::Builtin(BuiltinConstSubr::new("Inherit", inherit_func, inherit_t));
self.register_builtin_const("Inherit", ValueObj::Subr(inherit)); 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 // decorators
let inheritable_t = func1(Class, Class); let inheritable_t = func1(Class, Class);
let inheritable = ConstSubr::Builtin(BuiltinConstSubr::new( let inheritable = ConstSubr::Builtin(BuiltinConstSubr::new(

View file

@ -26,8 +26,8 @@ use crate::free::{
}; };
use crate::typaram::{IntervalOp, TyParam}; use crate::typaram::{IntervalOp, TyParam};
use crate::value::value_set::*; use crate::value::value_set::*;
use crate::value::ValueObj;
use crate::value::ValueObj::{Inf, NegInf}; use crate::value::ValueObj::{Inf, NegInf};
use crate::value::{EvalValueResult, ValueObj};
/// cloneのコストがあるためなるべく.ref_tを使うようにすること /// cloneのコストがあるためなるべく.ref_tを使うようにすること
/// いくつかの構造体は直接Typeを保持していないので、その場合は.tを使う /// いくつかの構造体は直接Typeを保持していないので、その場合は.tを使う
@ -157,7 +157,7 @@ impl ValueArgs {
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct BuiltinConstSubr { pub struct BuiltinConstSubr {
name: &'static str, name: &'static str,
subr: fn(ValueArgs, Option<Str>) -> ValueObj, subr: fn(ValueArgs, Option<Str>) -> EvalValueResult<ValueObj>,
t: Type, t: Type,
} }
@ -170,7 +170,7 @@ impl fmt::Display for BuiltinConstSubr {
impl BuiltinConstSubr { impl BuiltinConstSubr {
pub const fn new( pub const fn new(
name: &'static str, name: &'static str,
subr: fn(ValueArgs, Option<Str>) -> ValueObj, subr: fn(ValueArgs, Option<Str>) -> EvalValueResult<ValueObj>,
t: Type, t: Type,
) -> Self { ) -> Self {
Self { name, subr, t } Self { name, subr, t }
@ -195,7 +195,7 @@ impl fmt::Display for ConstSubr {
} }
impl ConstSubr { impl ConstSubr {
pub fn call(&self, args: ValueArgs, __name__: Option<Str>) -> ValueObj { pub fn call(&self, args: ValueArgs, __name__: Option<Str>) -> EvalValueResult<ValueObj> {
match self { match self {
ConstSubr::User(_user) => todo!(), ConstSubr::User(_user) => todo!(),
ConstSubr::Builtin(builtin) => (builtin.subr)(args, __name__), ConstSubr::Builtin(builtin) => (builtin.subr)(args, __name__),

View file

@ -9,6 +9,7 @@ use std::ops::Neg;
use std::rc::Rc; use std::rc::Rc;
use erg_common::dict::Dict; use erg_common::dict::Dict;
use erg_common::error::ErrorCore;
use erg_common::rccell::RcCell; use erg_common::rccell::RcCell;
use erg_common::serialize::*; use erg_common::serialize::*;
use erg_common::set; use erg_common::set;
@ -22,6 +23,9 @@ use crate::free::fresh_varname;
use crate::typaram::TyParam; use crate::typaram::TyParam;
use crate::{ConstSubr, HasType, Predicate, Type}; use crate::{ConstSubr, HasType, Predicate, Type};
pub type EvalValueError = ErrorCore;
pub type EvalValueResult<T> = Result<T, EvalValueError>;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum TypeKind { pub enum TypeKind {
Class, Class,