feat: add Array.d.er/Bool.d.er/Nat.d.er

This commit is contained in:
Shunsuke Shibayama 2023-02-18 00:24:25 +09:00
parent 9a131ecc53
commit 3aeb63f51b
7 changed files with 134 additions and 15 deletions

View file

@ -315,7 +315,7 @@ impl Context {
nat.register_superclass(Int, &int); nat.register_superclass(Int, &int);
// class("Rational"), // class("Rational"),
// class("Integral"), // class("Integral"),
nat.register_builtin_py_impl( nat.register_py_builtin(
PROC_TIMES, PROC_TIMES,
pr_met( pr_met(
Nat, Nat,
@ -324,9 +324,8 @@ impl Context {
vec![], vec![],
NoneType, NoneType,
), ),
Immutable,
Public,
Some(FUNC_TIMES), Some(FUNC_TIMES),
13,
); );
nat.register_marker_trait(mono(NUM)); nat.register_marker_trait(mono(NUM));
let mut nat_eq = Self::builtin_methods(Some(mono(EQ)), 2); let mut nat_eq = Self::builtin_methods(Some(mono(EQ)), 2);
@ -389,7 +388,7 @@ impl Context {
bool_show.register_builtin_erg_impl(TO_STR, fn0_met(Bool, Str), Immutable, Public); bool_show.register_builtin_erg_impl(TO_STR, fn0_met(Bool, Str), Immutable, Public);
bool_.register_trait(Bool, bool_show); bool_.register_trait(Bool, bool_show);
let t = fn0_met(Bool, Bool); let t = fn0_met(Bool, Bool);
bool_.register_builtin_py_impl(FUNC_INVERT, t, Immutable, Public, Some(FUNC_INVERT)); bool_.register_py_builtin(FUNC_INVERT, t, Some(FUNC_INVERT), 9);
/* Str */ /* Str */
let mut str_ = Self::builtin_mono_class(STR, 10); let mut str_ = Self::builtin_mono_class(STR, 10);
str_.register_superclass(Obj, &obj); str_.register_superclass(Obj, &obj);
@ -729,10 +728,10 @@ impl Context {
array_t(T.clone(), N.clone() + M.clone()), array_t(T.clone(), N.clone() + M.clone()),
) )
.quantify(); .quantify();
array_.register_builtin_py_impl(FUNC_CONCAT, t.clone(), Immutable, Public, Some(OP_ADD)); array_.register_py_builtin(FUNC_CONCAT, t.clone(), Some(OP_ADD), 9);
let t_count = let t_count =
fn_met(arr_t.clone(), vec![kw(KW_X, T.clone())], None, vec![], Nat).quantify(); fn_met(arr_t.clone(), vec![kw(KW_X, T.clone())], None, vec![], Nat).quantify();
array_.register_builtin_py_impl(FUNC_COUNT, t_count, Immutable, Public, Some(FUNC_COUNT)); array_.register_py_builtin(FUNC_COUNT, t_count, Some(FUNC_COUNT), 17);
// Array(T, N)|<: Add(Array(T, M))|. // Array(T, N)|<: Add(Array(T, M))|.
// Output = Array(T, N + M) // Output = Array(T, N + M)
// __add__: (self: Array(T, N), other: Array(T, M)) -> Array(T, N + M) = Array.concat // __add__: (self: Array(T, N), other: Array(T, M)) -> Array(T, N + M) = Array.concat
@ -815,15 +814,18 @@ impl Context {
array_t(T.clone(), TyParam::erased(Nat)), array_t(T.clone(), TyParam::erased(Nat)),
]), ]),
); );
array_.register_builtin_erg_impl(FUNC_PARTITION, t.quantify(), Immutable, Public); array_.register_py_builtin(FUNC_PARTITION, t.quantify(), Some(FUNC_PARTITION), 37);
let t = fn_met( let t = fn_met(
array_t(T.clone(), TyParam::erased(Nat)), array_t(T.clone(), TyParam::erased(Nat)),
vec![], vec![],
None, None,
vec![kw("f", or(func1(T.clone(), Bool), NoneType))], vec![kw(
"same_bucket",
or(func2(T.clone(), T.clone(), Bool), NoneType),
)],
array_t(T.clone(), TyParam::erased(Nat)), array_t(T.clone(), TyParam::erased(Nat)),
); );
array_.register_builtin_erg_impl(FUNC_DEDUP, t.quantify(), Immutable, Public); array_.register_py_builtin(FUNC_DEDUP, t.quantify(), Some(FUNC_DEDUP), 28);
/* Set */ /* Set */
let mut set_ = let mut set_ =
Self::builtin_poly_class(SET, vec![PS::t_nd(TY_T), PS::named_nd(TY_N, Nat)], 10); Self::builtin_poly_class(SET, vec![PS::t_nd(TY_T), PS::named_nd(TY_N, Nat)], 10);

View file

@ -22,7 +22,7 @@ use crate::feature_error;
use crate::ty::constructors::*; use crate::ty::constructors::*;
use crate::ty::free::CanbeFree; use crate::ty::free::CanbeFree;
use crate::ty::free::{Constraint, HasLevel}; use crate::ty::free::{Constraint, HasLevel};
use crate::ty::typaram::{IntervalOp, TyParam, TyParamOrdering}; use crate::ty::typaram::{IntervalOp, OpKind, TyParam, TyParamOrdering};
use crate::ty::value::ValueObj; use crate::ty::value::ValueObj;
use crate::ty::{HasType, ParamTy, Predicate, SubrKind, Type}; use crate::ty::{HasType, ParamTy, Predicate, SubrKind, Type};
use crate::type_feature_error; use crate::type_feature_error;
@ -36,6 +36,35 @@ use crate::hir;
use crate::AccessKind; use crate::AccessKind;
use RegistrationMode::*; use RegistrationMode::*;
pub fn token_kind_to_op_kind(kind: TokenKind) -> Option<OpKind> {
match kind {
TokenKind::Plus => Some(OpKind::Add),
TokenKind::Minus => Some(OpKind::Sub),
TokenKind::Star => Some(OpKind::Mul),
TokenKind::Slash => Some(OpKind::Div),
TokenKind::FloorDiv => Some(OpKind::FloorDiv),
TokenKind::Mod => Some(OpKind::Mod),
TokenKind::Pow => Some(OpKind::Pow),
TokenKind::PrePlus => Some(OpKind::Pos),
TokenKind::PreMinus => Some(OpKind::Neg),
TokenKind::PreBitNot => Some(OpKind::Invert),
TokenKind::Equal => Some(OpKind::Eq),
TokenKind::NotEq => Some(OpKind::Ne),
TokenKind::Less => Some(OpKind::Lt),
TokenKind::LessEq => Some(OpKind::Le),
TokenKind::Gre => Some(OpKind::Gt),
TokenKind::GreEq => Some(OpKind::Ge),
TokenKind::AndOp => Some(OpKind::And),
TokenKind::OrOp => Some(OpKind::Or),
TokenKind::BitAnd => Some(OpKind::BitAnd),
TokenKind::BitOr => Some(OpKind::BitOr),
TokenKind::BitXor => Some(OpKind::BitXor),
TokenKind::Shl => Some(OpKind::Shl),
TokenKind::Shr => Some(OpKind::Shr),
_ => None,
}
}
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum ParamKind { pub enum ParamKind {
NonDefault, NonDefault,
@ -721,6 +750,29 @@ impl Context {
} }
Ok(TyParam::Tuple(tp_tuple)) Ok(TyParam::Tuple(tp_tuple))
} }
ast::ConstExpr::BinOp(bin) => {
let Some(op) = token_kind_to_op_kind(bin.op.kind) else {
return type_feature_error!(
self,
bin.loc(),
&format!("instantiating const expression {bin}")
)
};
let lhs = self.instantiate_const_expr(&bin.lhs, erased_idx, tmp_tv_cache)?;
let rhs = self.instantiate_const_expr(&bin.rhs, erased_idx, tmp_tv_cache)?;
Ok(TyParam::bin(op, lhs, rhs))
}
ast::ConstExpr::UnaryOp(unary) => {
let Some(op) = token_kind_to_op_kind(unary.op.kind) else {
return type_feature_error!(
self,
unary.loc(),
&format!("instantiating const expression {unary}")
)
};
let val = self.instantiate_const_expr(&unary.expr, erased_idx, tmp_tv_cache)?;
Ok(TyParam::unary(op, val))
}
other => type_feature_error!( other => type_feature_error!(
self, self,
other.loc(), other.loc(),

View file

@ -1343,9 +1343,9 @@ impl HasType for Call {
#[inline] #[inline]
fn ref_t(&self) -> &Type { fn ref_t(&self) -> &Type {
if let Some(attr) = self.attr_name.as_ref() { if let Some(attr) = self.attr_name.as_ref() {
attr.ref_t().return_t().unwrap() attr.ref_t().return_t().unwrap_or(Type::FAILURE)
} else { } else {
self.obj.ref_t().return_t().unwrap() self.obj.ref_t().return_t().unwrap_or(Type::FAILURE)
} }
} }
#[inline] #[inline]

View file

@ -0,0 +1,37 @@
.Array: ClassType
.Array.
'''
Concatenates two arrays. Same as `self + other`.
'''
'''erg
assert [1, 2].concat([3, 4]) == [1, 2, 3, 4]
'''
concat: |T: Type, M: Nat, N: Nat|(self: Array(T, M), other: Array(T, N)) -> Array(T, M + N)
'''
Returns the number of elements in the array.
'''
'''erg
assert [1, 2, 3, 1, 2].count(1) == 2
assert ["a", "b", "c"].count("a") == 1
'''
count: |T: Type, N: Nat|(self: Array(T, N), x: T) -> Nat
'''
Remove array duplicates.
If `same_bucket` is not provided, it is used for the equality comparison.
If lhs and rhs are considered to be equal, __lhs__ will be removed.
'''
'''erg
assert [1, 1, 2].dedup() == [1, 2]
assert [0.0, 0.1, 10.0, 20.0, 20.1].dedup((lhs, rhs) -> abs(lhs - rhs) < 1.0) == [0.0, 10.0, 20.1]
'''
dedup: |T: Type|(self: Array(T, _), same_bucket := (T, T) -> Bool) -> Array(T, _)
'''
Create two arrays according to the `predicate` function.
What is returned is a tuple of two arrays, the first containing the elements judged to be `True` and the second containing the elements `False`.
'''
'''erg
assert [-2, -1, 0, 1, 2].partition(x -> x >= 0) == ([0, 1, 2], [-2, -1])
'''
partition: |T: Type|(self: Array(T, _), predicate: T -> Bool) -> (Array(T, _), Array(T, _))

View file

@ -0,0 +1,9 @@
.Bool: ClassType
.Bool.
'''
Same as `not self`.
'''
'''erg
assert False.invert()
'''
invert: (self: .Bool) -> .Bool

View file

@ -0,0 +1,13 @@
.Nat: ClassType
.Nat.
'''
Execute `proc!` `self` times.
'''
'''erg
10.times! do!:
print! "hello"
print_hello!() = print! "hello"
10.times! print_hello!
'''
times!: (self: .Nat, proc!: () => NoneType) => NoneType

View file

@ -1,9 +1,15 @@
class Array(list): class Array(list):
def dedup(self, f=None): def dedup(self, same_bucket=None):
if f == None: if same_bucket is None:
return Array(list(set(self))) return Array(list(set(self)))
else: else:
return Array(list(set(map(f, self)))) removes = []
for (lhs, rhs) in zip(self, self[1:]):
if same_bucket(lhs, rhs):
removes.append(lhs)
for remove in removes:
self.remove(remove)
return self
def push(self, value): def push(self, value):
self.append(value) self.append(value)
return self return self