diff --git a/compiler/erg_compiler/context/eval.rs b/compiler/erg_compiler/context/eval.rs index 852a6f74..d8a3fdba 100644 --- a/compiler/erg_compiler/context/eval.rs +++ b/compiler/erg_compiler/context/eval.rs @@ -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!(), diff --git a/compiler/erg_compiler/context/initialize/const_func.rs b/compiler/erg_compiler/context/initialize/const_func.rs index 71a7bb1a..95ffec9d 100644 --- a/compiler/erg_compiler/context/initialize/const_func.rs +++ b/compiler/erg_compiler/context/initialize/const_func.rs @@ -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) -> ValueObj { - let require = args.remove_left_or_key("Requirement").unwrap(); +pub fn class_func(mut args: ValueArgs, __name__: Option) -> EvalValueResult { + 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(""))); - 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) -> ValueObj { - let sup = args.remove_left_or_key("Super").unwrap(); +pub fn inherit_func(mut args: ValueArgs, __name__: Option) -> EvalValueResult { + 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(""))); - 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) -> ValueObj { - let class = args.remove_left_or_key("Class").unwrap(); +pub fn inheritable_func(mut args: ValueArgs, __name__: Option) -> EvalValueResult { + 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) -> 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) -> EvalValueResult { + 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(""))); + 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) -> EvalValueResult { + 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(""))); + Ok(ValueObj::gen_t( + TypeKind::Subtrait, + t, + sup, + impls, + additional, + )) +} diff --git a/compiler/erg_compiler/context/initialize/mod.rs b/compiler/erg_compiler/context/initialize/mod.rs index 9601c60d..eedc903b 100644 --- a/compiler/erg_compiler/context/initialize/mod.rs +++ b/compiler/erg_compiler/context/initialize/mod.rs @@ -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( diff --git a/compiler/erg_type/lib.rs b/compiler/erg_type/lib.rs index 8454e5ec..da3dcd6f 100644 --- a/compiler/erg_type/lib.rs +++ b/compiler/erg_type/lib.rs @@ -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) -> ValueObj, + subr: fn(ValueArgs, Option) -> EvalValueResult, t: Type, } @@ -170,7 +170,7 @@ impl fmt::Display for BuiltinConstSubr { impl BuiltinConstSubr { pub const fn new( name: &'static str, - subr: fn(ValueArgs, Option) -> ValueObj, + subr: fn(ValueArgs, Option) -> EvalValueResult, 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) -> ValueObj { + pub fn call(&self, args: ValueArgs, __name__: Option) -> EvalValueResult { match self { ConstSubr::User(_user) => todo!(), ConstSubr::Builtin(builtin) => (builtin.subr)(args, __name__), diff --git a/compiler/erg_type/value.rs b/compiler/erg_type/value.rs index 9bb7fe1c..9b0fe66e 100644 --- a/compiler/erg_type/value.rs +++ b/compiler/erg_type/value.rs @@ -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 = Result; + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum TypeKind { Class,