mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 04:24:43 +00:00
Add SetTypeSpec
This commit is contained in:
parent
3112fb31a9
commit
2cf4b5aba8
6 changed files with 85 additions and 12 deletions
|
@ -785,7 +785,7 @@ impl Context {
|
||||||
let mut module = Self::builtin_poly_class("Module", vec![PS::named_nd("Path", Str)], 2);
|
let mut module = Self::builtin_poly_class("Module", vec![PS::named_nd("Path", Str)], 2);
|
||||||
module.register_superclass(g_module_t.clone(), &generic_module);
|
module.register_superclass(g_module_t.clone(), &generic_module);
|
||||||
|
|
||||||
// *** Array *** //
|
/* Array */
|
||||||
let mut array_ =
|
let mut array_ =
|
||||||
Self::builtin_poly_class("Array", vec![PS::t_nd("T"), PS::named_nd("N", Nat)], 10);
|
Self::builtin_poly_class("Array", vec![PS::t_nd("T"), PS::named_nd("N", Nat)], 10);
|
||||||
array_.register_superclass(Obj, &obj);
|
array_.register_superclass(Obj, &obj);
|
||||||
|
@ -833,15 +833,14 @@ impl Context {
|
||||||
Public,
|
Public,
|
||||||
);
|
);
|
||||||
array_.register_trait(array_t, builtin_mono("Show"), array_show);
|
array_.register_trait(array_t, builtin_mono("Show"), array_show);
|
||||||
|
/* Set */
|
||||||
// *** Set *** //
|
|
||||||
let mut set_ =
|
let mut set_ =
|
||||||
Self::builtin_poly_class("Set", vec![PS::t_nd("T"), PS::named_nd("N", Nat)], 10);
|
Self::builtin_poly_class("Set", vec![PS::t_nd("T"), PS::named_nd("N", Nat)], 10);
|
||||||
set_.register_superclass(Obj, &obj);
|
|
||||||
set_.register_marker_trait(builtin_poly("output", vec![ty_tp(mono_q("T"))]));
|
|
||||||
let n = mono_q_tp("N");
|
let n = mono_q_tp("N");
|
||||||
let m = mono_q_tp("M");
|
let m = mono_q_tp("M");
|
||||||
let set_t = array(mono_q("T"), n.clone());
|
let set_t = array(mono_q("T"), n.clone());
|
||||||
|
set_.register_superclass(Obj, &obj);
|
||||||
|
set_.register_marker_trait(builtin_poly("Output", vec![ty_tp(mono_q("T"))]));
|
||||||
let t = fn_met(
|
let t = fn_met(
|
||||||
set_t.clone(),
|
set_t.clone(),
|
||||||
vec![kw("rhs", array(mono_q("T"), m.clone()))],
|
vec![kw("rhs", array(mono_q("T"), m.clone()))],
|
||||||
|
@ -866,7 +865,7 @@ impl Context {
|
||||||
Const,
|
Const,
|
||||||
Public,
|
Public,
|
||||||
);
|
);
|
||||||
array_.register_trait(
|
set_.register_trait(
|
||||||
set_t.clone(),
|
set_t.clone(),
|
||||||
builtin_poly("Eq", vec![ty_tp(set_t.clone())]),
|
builtin_poly("Eq", vec![ty_tp(set_t.clone())]),
|
||||||
set_eq,
|
set_eq,
|
||||||
|
|
|
@ -1304,7 +1304,9 @@ impl Context {
|
||||||
) -> Option<impl Iterator<Item = (&'a Type, &'a Context)>> {
|
) -> Option<impl Iterator<Item = (&'a Type, &'a Context)>> {
|
||||||
let (_ctx_t, ctx) = self.get_nominal_type_ctx(t)?;
|
let (_ctx_t, ctx) = self.get_nominal_type_ctx(t)?;
|
||||||
Some(ctx.super_traits.iter().map(|sup| {
|
Some(ctx.super_traits.iter().map(|sup| {
|
||||||
let (_t, sup_ctx) = self.get_nominal_type_ctx(sup).unwrap();
|
let (_t, sup_ctx) = self
|
||||||
|
.get_nominal_type_ctx(sup)
|
||||||
|
.unwrap_or_else(|| todo!("{} not found", sup));
|
||||||
(sup, sup_ctx)
|
(sup, sup_ctx)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
@ -784,6 +784,11 @@ impl Context {
|
||||||
let len = self.instantiate_const_expr(&arr.len);
|
let len = self.instantiate_const_expr(&arr.len);
|
||||||
Ok(array(elem_t, len))
|
Ok(array(elem_t, len))
|
||||||
}
|
}
|
||||||
|
TypeSpec::Set(set) => {
|
||||||
|
let elem_t = self.instantiate_typespec(&set.ty, opt_decl_t, tmp_tv_ctx, mode)?;
|
||||||
|
let len = self.instantiate_const_expr(&set.len);
|
||||||
|
Ok(erg_type::constructors::set(elem_t, len))
|
||||||
|
}
|
||||||
// FIXME: unwrap
|
// FIXME: unwrap
|
||||||
TypeSpec::Tuple(tys) => Ok(tuple(
|
TypeSpec::Tuple(tys) => Ok(tuple(
|
||||||
tys.iter()
|
tys.iter()
|
||||||
|
|
|
@ -1630,6 +1630,29 @@ impl ArrayTypeSpec {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct SetTypeSpec {
|
||||||
|
pub ty: Box<TypeSpec>,
|
||||||
|
pub len: ConstExpr,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for SetTypeSpec {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "{{{}; {}}}", self.ty, self.len)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_locational!(SetTypeSpec, ty, len);
|
||||||
|
|
||||||
|
impl SetTypeSpec {
|
||||||
|
pub fn new(ty: TypeSpec, len: ConstExpr) -> Self {
|
||||||
|
Self {
|
||||||
|
ty: Box::new(ty),
|
||||||
|
len,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// * Array: `[Int; 3]`, `[Int, Ratio, Complex]`, etc.
|
/// * Array: `[Int; 3]`, `[Int, Ratio, Complex]`, etc.
|
||||||
/// * Dict: `[Str: Str]`, etc.
|
/// * Dict: `[Str: Str]`, etc.
|
||||||
/// * And (Intersection type): Add and Sub and Mul (== Num), etc.
|
/// * And (Intersection type): Add and Sub and Mul (== Num), etc.
|
||||||
|
@ -1645,6 +1668,7 @@ pub enum TypeSpec {
|
||||||
PreDeclTy(PreDeclTypeSpec),
|
PreDeclTy(PreDeclTypeSpec),
|
||||||
/* Composite types */
|
/* Composite types */
|
||||||
Array(ArrayTypeSpec),
|
Array(ArrayTypeSpec),
|
||||||
|
Set(SetTypeSpec),
|
||||||
Tuple(Vec<TypeSpec>),
|
Tuple(Vec<TypeSpec>),
|
||||||
// Dict(),
|
// Dict(),
|
||||||
// Option(),
|
// Option(),
|
||||||
|
@ -1673,6 +1697,7 @@ impl fmt::Display for TypeSpec {
|
||||||
Self::Not(lhs, rhs) => write!(f, "{lhs} not {rhs}"),
|
Self::Not(lhs, rhs) => write!(f, "{lhs} not {rhs}"),
|
||||||
Self::Or(lhs, rhs) => write!(f, "{lhs} or {rhs}"),
|
Self::Or(lhs, rhs) => write!(f, "{lhs} or {rhs}"),
|
||||||
Self::Array(arr) => write!(f, "{arr}"),
|
Self::Array(arr) => write!(f, "{arr}"),
|
||||||
|
Self::Set(set) => write!(f, "{set}"),
|
||||||
Self::Tuple(tys) => write!(f, "({})", fmt_vec(tys)),
|
Self::Tuple(tys) => write!(f, "({})", fmt_vec(tys)),
|
||||||
Self::Enum(elems) => write!(f, "{{{elems}}}"),
|
Self::Enum(elems) => write!(f, "{{{elems}}}"),
|
||||||
Self::Interval { op, lhs, rhs } => write!(f, "{lhs}{}{rhs}", op.inspect()),
|
Self::Interval { op, lhs, rhs } => write!(f, "{lhs}{}{rhs}", op.inspect()),
|
||||||
|
@ -1690,6 +1715,7 @@ impl Locational for TypeSpec {
|
||||||
Location::concat(lhs.as_ref(), rhs.as_ref())
|
Location::concat(lhs.as_ref(), rhs.as_ref())
|
||||||
}
|
}
|
||||||
Self::Array(arr) => arr.loc(),
|
Self::Array(arr) => arr.loc(),
|
||||||
|
Self::Set(set) => set.loc(),
|
||||||
// TODO: ユニット
|
// TODO: ユニット
|
||||||
Self::Tuple(tys) => Location::concat(tys.first().unwrap(), tys.last().unwrap()),
|
Self::Tuple(tys) => Location::concat(tys.first().unwrap(), tys.last().unwrap()),
|
||||||
Self::Enum(set) => set.loc(),
|
Self::Enum(set) => set.loc(),
|
||||||
|
|
|
@ -1647,7 +1647,12 @@ impl Parser {
|
||||||
}
|
}
|
||||||
// Dict
|
// Dict
|
||||||
Expr::TypeAsc(_) => todo!(),
|
Expr::TypeAsc(_) => todo!(),
|
||||||
Expr::Accessor(acc) if self.cur_is(Semi) => {
|
// TODO: {X; Y} will conflict with Set
|
||||||
|
Expr::Accessor(acc)
|
||||||
|
if self.cur_is(Semi)
|
||||||
|
&& !self.nth_is(1, TokenKind::NatLit)
|
||||||
|
&& !self.nth_is(1, UBar) =>
|
||||||
|
{
|
||||||
let record = self
|
let record = self
|
||||||
.try_reduce_shortened_record(l_brace, acc)
|
.try_reduce_shortened_record(l_brace, acc)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
|
@ -1792,6 +1797,19 @@ impl Parser {
|
||||||
|
|
||||||
fn try_reduce_set(&mut self, l_brace: Token, first_elem: Expr) -> ParseResult<Set> {
|
fn try_reduce_set(&mut self, l_brace: Token, first_elem: Expr) -> ParseResult<Set> {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
|
if self.cur_is(Semi) {
|
||||||
|
self.skip();
|
||||||
|
let len = self
|
||||||
|
.try_reduce_expr(false, false)
|
||||||
|
.map_err(|_| self.stack_dec())?;
|
||||||
|
let r_brace = self.lpop();
|
||||||
|
return Ok(Set::WithLength(SetWithLength::new(
|
||||||
|
l_brace,
|
||||||
|
r_brace,
|
||||||
|
PosArg::new(first_elem),
|
||||||
|
len,
|
||||||
|
)));
|
||||||
|
}
|
||||||
let mut args = Args::new(vec![PosArg::new(first_elem)], vec![], None);
|
let mut args = Args::new(vec![PosArg::new(first_elem)], vec![], None);
|
||||||
loop {
|
loop {
|
||||||
match self.peek() {
|
match self.peek() {
|
||||||
|
@ -2598,6 +2616,13 @@ impl Parser {
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(TypeSpec::Array(array))
|
Ok(TypeSpec::Array(array))
|
||||||
}
|
}
|
||||||
|
Expr::Set(set) => {
|
||||||
|
let set = self
|
||||||
|
.convert_set_to_set_type_spec(set)
|
||||||
|
.map_err(|_| self.stack_dec())?;
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(TypeSpec::Set(set))
|
||||||
|
}
|
||||||
Expr::BinOp(bin) => {
|
Expr::BinOp(bin) => {
|
||||||
if bin.op.kind.is_range_op() {
|
if bin.op.kind.is_range_op() {
|
||||||
let op = bin.op;
|
let op = bin.op;
|
||||||
|
@ -2761,4 +2786,22 @@ impl Parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn convert_set_to_set_type_spec(&mut self, set: Set) -> ParseResult<SetTypeSpec> {
|
||||||
|
debug_call_info!(self);
|
||||||
|
match set {
|
||||||
|
Set::Normal(arr) => {
|
||||||
|
// TODO: add hint
|
||||||
|
self.errs
|
||||||
|
.push(ParseError::simple_syntax_error(line!() as usize, arr.loc()));
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
Set::WithLength(set) => {
|
||||||
|
let t_spec = self.convert_rhs_to_type_spec(set.elem.expr)?;
|
||||||
|
let len = self.validate_const_expr(*set.len)?;
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(SetTypeSpec::new(t_spec, len))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,7 @@ assert {1, 2, 3} == {1, 2, 3}
|
||||||
b = {"a", "a", "b", "b", "a", "b"} # {"a", "b"} in no particular order
|
b = {"a", "a", "b", "b", "a", "b"} # {"a", "b"} in no particular order
|
||||||
assert {"a", "b"} == {"a", "b"}
|
assert {"a", "b"} == {"a", "b"}
|
||||||
|
|
||||||
c: {Int} = {-1, 1, -1, 1} # {-1, 1}
|
c: {Int; _} = {-1, 1, -1, 1} # {-1, 1}
|
||||||
|
|
||||||
# If the object does not implement `Eq`, a compile error will occur
|
# If the object does not implement `Eq`, a compile error will occur
|
||||||
A = Class { i = Int }
|
print! {1.0, 1.0} # compile error
|
||||||
B = Class { i = Int }
|
|
||||||
print! {A, B} # compile error
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue