Add SetTypeSpec

This commit is contained in:
Shunsuke Shibayama 2022-10-07 10:59:58 +09:00
parent 3112fb31a9
commit 2cf4b5aba8
6 changed files with 85 additions and 12 deletions

View file

@ -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.
/// * Dict: `[Str: Str]`, etc.
/// * And (Intersection type): Add and Sub and Mul (== Num), etc.
@ -1645,6 +1668,7 @@ pub enum TypeSpec {
PreDeclTy(PreDeclTypeSpec),
/* Composite types */
Array(ArrayTypeSpec),
Set(SetTypeSpec),
Tuple(Vec<TypeSpec>),
// Dict(),
// Option(),
@ -1673,6 +1697,7 @@ impl fmt::Display for TypeSpec {
Self::Not(lhs, rhs) => write!(f, "{lhs} not {rhs}"),
Self::Or(lhs, rhs) => write!(f, "{lhs} or {rhs}"),
Self::Array(arr) => write!(f, "{arr}"),
Self::Set(set) => write!(f, "{set}"),
Self::Tuple(tys) => write!(f, "({})", fmt_vec(tys)),
Self::Enum(elems) => write!(f, "{{{elems}}}"),
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())
}
Self::Array(arr) => arr.loc(),
Self::Set(set) => set.loc(),
// TODO: ユニット
Self::Tuple(tys) => Location::concat(tys.first().unwrap(), tys.last().unwrap()),
Self::Enum(set) => set.loc(),

View file

@ -1647,7 +1647,12 @@ impl Parser {
}
// Dict
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
.try_reduce_shortened_record(l_brace, acc)
.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> {
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);
loop {
match self.peek() {
@ -2598,6 +2616,13 @@ impl Parser {
self.level -= 1;
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) => {
if bin.op.kind.is_range_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))
}
}
}
}