mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 12:24:45 +00:00
Add Trait
, Subsume
This commit is contained in:
parent
12f22f8bed
commit
bc67677ad6
5 changed files with 116 additions and 16 deletions
|
@ -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!(),
|
||||
|
|
|
@ -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,
|
||||
))
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -26,8 +26,8 @@ use crate::free::{
|
|||
};
|
||||
use crate::typaram::{IntervalOp, TyParam};
|
||||
use crate::value::value_set::*;
|
||||
use crate::value::ValueObj;
|
||||
use crate::value::ValueObj::{Inf, NegInf};
|
||||
use crate::value::{EvalValueResult, ValueObj};
|
||||
|
||||
/// cloneのコストがあるためなるべく.ref_tを使うようにすること
|
||||
/// いくつかの構造体は直接Typeを保持していないので、その場合は.tを使う
|
||||
|
@ -157,7 +157,7 @@ impl ValueArgs {
|
|||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct BuiltinConstSubr {
|
||||
name: &'static str,
|
||||
subr: fn(ValueArgs, Option<Str>) -> ValueObj,
|
||||
subr: fn(ValueArgs, Option<Str>) -> EvalValueResult<ValueObj>,
|
||||
t: Type,
|
||||
}
|
||||
|
||||
|
@ -170,7 +170,7 @@ impl fmt::Display for BuiltinConstSubr {
|
|||
impl BuiltinConstSubr {
|
||||
pub const fn new(
|
||||
name: &'static str,
|
||||
subr: fn(ValueArgs, Option<Str>) -> ValueObj,
|
||||
subr: fn(ValueArgs, Option<Str>) -> EvalValueResult<ValueObj>,
|
||||
t: Type,
|
||||
) -> Self {
|
||||
Self { name, subr, t }
|
||||
|
@ -195,7 +195,7 @@ impl fmt::Display for 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 {
|
||||
ConstSubr::User(_user) => todo!(),
|
||||
ConstSubr::Builtin(builtin) => (builtin.subr)(args, __name__),
|
||||
|
|
|
@ -9,6 +9,7 @@ use std::ops::Neg;
|
|||
use std::rc::Rc;
|
||||
|
||||
use erg_common::dict::Dict;
|
||||
use erg_common::error::ErrorCore;
|
||||
use erg_common::rccell::RcCell;
|
||||
use erg_common::serialize::*;
|
||||
use erg_common::set;
|
||||
|
@ -22,6 +23,9 @@ use crate::free::fresh_varname;
|
|||
use crate::typaram::TyParam;
|
||||
use crate::{ConstSubr, HasType, Predicate, Type};
|
||||
|
||||
pub type EvalValueError = ErrorCore;
|
||||
pub type EvalValueResult<T> = Result<T, EvalValueError>;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum TypeKind {
|
||||
Class,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue