changing the array sintax to be distinc from tuple
the arrays can be declared in a more natural way type of the element can aso be inferred form the first element Signed-off-by: Jakub Doka <jakub.doka2@gmail.com>
This commit is contained in:
parent
6e8eb059f6
commit
8ad58ee6b6
File diff suppressed because one or more lines are too long
|
@ -2,8 +2,8 @@ use {
|
|||
crate::{
|
||||
lexer::{self, Lexer, TokenKind},
|
||||
parser::{
|
||||
self, CommentOr, CtorField, EnumField, Expr, FieldList, Poser, Radix, StructField,
|
||||
UnionField,
|
||||
self, CommentOr, CtorField, EnumField, Expr, FieldList, ListKind, Poser, Radix,
|
||||
StructField, UnionField,
|
||||
},
|
||||
},
|
||||
core::{
|
||||
|
@ -60,7 +60,7 @@ fn token_group(kind: TokenKind) -> TokenGroup {
|
|||
Colon => TG::Colon,
|
||||
Semi | Comma => TG::Comma,
|
||||
Dot => TG::Dot,
|
||||
Ctor | Tupl | TArrow => TG::Ctor,
|
||||
Ctor | Arr | Tupl | TArrow => TG::Ctor,
|
||||
LParen | RParen => TG::Paren,
|
||||
LBrace | RBrace | LBrack | RBrack => TG::Bracket,
|
||||
Number | Float => TG::Number,
|
||||
|
@ -391,35 +391,40 @@ impl<'a> Formatter<'a> {
|
|||
},
|
||||
)
|
||||
}
|
||||
Expr::Tupl {
|
||||
Expr::List {
|
||||
pos,
|
||||
kind: term,
|
||||
ty: Some(&Expr::Slice { pos: spos, size: Some(&Expr::Number { value, .. }), item }),
|
||||
fields,
|
||||
trailing_comma,
|
||||
} if value as usize == fields.len() => self.fmt(
|
||||
&Expr::Tupl {
|
||||
&Expr::List {
|
||||
pos,
|
||||
kind: term,
|
||||
ty: Some(&Expr::Slice { pos: spos, size: None, item }),
|
||||
fields,
|
||||
trailing_comma,
|
||||
},
|
||||
f,
|
||||
),
|
||||
Expr::Tupl { ty, fields, trailing_comma, .. } => {
|
||||
Expr::List { ty, kind: term, fields, trailing_comma, .. } => {
|
||||
if let Some(ty) = ty {
|
||||
self.fmt_paren(ty, f, unary)?;
|
||||
}
|
||||
f.write_str(".(")?;
|
||||
self.fmt_list(f, trailing_comma, ")", ",", fields, Self::fmt)
|
||||
let (start, end) = match term {
|
||||
ListKind::Tuple => (".(", ")"),
|
||||
ListKind::Array => (".[", "]"),
|
||||
};
|
||||
f.write_str(start)?;
|
||||
self.fmt_list(f, trailing_comma, end, ",", fields, Self::fmt)
|
||||
}
|
||||
Expr::Slice { item, size, .. } => {
|
||||
f.write_str("[")?;
|
||||
self.fmt(item, f)?;
|
||||
if let Some(size) = size {
|
||||
f.write_str("; ")?;
|
||||
self.fmt(size, f)?;
|
||||
}
|
||||
f.write_str("]")
|
||||
f.write_str("]")?;
|
||||
self.fmt(item, f)
|
||||
}
|
||||
Expr::Index { base, index } => {
|
||||
self.fmt(base, f)?;
|
||||
|
|
|
@ -138,6 +138,7 @@ pub enum TokenKind {
|
|||
|
||||
Ctor,
|
||||
Tupl,
|
||||
Arr,
|
||||
TArrow,
|
||||
|
||||
Or,
|
||||
|
@ -347,6 +348,7 @@ gen_token_kind! {
|
|||
#[punkt]
|
||||
Ctor = ".{",
|
||||
Tupl = ".(",
|
||||
Arr = ".[",
|
||||
TArrow = "=>",
|
||||
// #define OP: each `#[prec]` delimeters a level of precedence from lowest to highest
|
||||
#[ops]
|
||||
|
@ -550,6 +552,7 @@ impl<'a> Lexer<'a> {
|
|||
}
|
||||
b'.' if self.advance_if(b'{') => T::Ctor,
|
||||
b'.' if self.advance_if(b'(') => T::Tupl,
|
||||
b'.' if self.advance_if(b'[') => T::Arr,
|
||||
b'=' if self.advance_if(b'>') => T::TArrow,
|
||||
b'&' if self.advance_if(b'&') => T::And,
|
||||
b'|' if self.advance_if(b'|') => T::Or,
|
||||
|
|
|
@ -486,14 +486,20 @@ impl<'a, 'b> Parser<'a, 'b> {
|
|||
body: self.ptr_expr()?,
|
||||
},
|
||||
T::Ctor => self.ctor(pos, None),
|
||||
T::Tupl => self.tupl(pos, None),
|
||||
T::Tupl => self.tupl(pos, None, ListKind::Tuple),
|
||||
T::Arr => self.tupl(pos, None, ListKind::Array),
|
||||
T::LBrack => E::Slice {
|
||||
item: self.ptr_unit_expr()?,
|
||||
size: self.advance_if(T::Semi).then(|| self.ptr_expr()).trans()?,
|
||||
pos: {
|
||||
size: {
|
||||
if self.advance_if(T::RBrack) {
|
||||
None
|
||||
} else {
|
||||
let adv = self.ptr_expr()?;
|
||||
self.expect_advance(T::RBrack)?;
|
||||
pos
|
||||
Some(adv)
|
||||
}
|
||||
},
|
||||
item: self.ptr_unit_expr()?,
|
||||
pos,
|
||||
},
|
||||
T::Band | T::Mul | T::Xor | T::Sub | T::Que | T::Not | T::Dot => E::UnOp {
|
||||
pos,
|
||||
|
@ -547,7 +553,7 @@ impl<'a, 'b> Parser<'a, 'b> {
|
|||
|
||||
loop {
|
||||
let token = self.token;
|
||||
if matches!(token.kind, T::LParen | T::Ctor | T::Dot | T::Tupl | T::LBrack) {
|
||||
if matches!(token.kind, T::LParen | T::Ctor | T::Dot | T::Tupl | T::Arr | T::LBrack) {
|
||||
self.next();
|
||||
}
|
||||
|
||||
|
@ -558,7 +564,8 @@ impl<'a, 'b> Parser<'a, 'b> {
|
|||
trailing_comma: core::mem::take(&mut self.trailing_sep),
|
||||
},
|
||||
T::Ctor => self.ctor(token.start, Some(expr)),
|
||||
T::Tupl => self.tupl(token.start, Some(expr)),
|
||||
T::Tupl => self.tupl(token.start, Some(expr), ListKind::Tuple),
|
||||
T::Arr => self.tupl(token.start, Some(expr), ListKind::Array),
|
||||
T::LBrack => E::Index {
|
||||
base: self.arena.alloc(expr),
|
||||
index: {
|
||||
|
@ -586,11 +593,12 @@ impl<'a, 'b> Parser<'a, 'b> {
|
|||
Some(expr)
|
||||
}
|
||||
|
||||
fn tupl(&mut self, pos: Pos, ty: Option<Expr<'a>>) -> Expr<'a> {
|
||||
Expr::Tupl {
|
||||
fn tupl(&mut self, pos: Pos, ty: Option<Expr<'a>>, kind: ListKind) -> Expr<'a> {
|
||||
Expr::List {
|
||||
pos,
|
||||
kind,
|
||||
ty: ty.map(|ty| self.arena.alloc(ty)),
|
||||
fields: self.collect_list(TokenKind::Comma, TokenKind::RParen, Self::expr),
|
||||
fields: self.collect_list(TokenKind::Comma, kind.term(), Self::expr),
|
||||
trailing_comma: core::mem::take(&mut self.trailing_sep),
|
||||
}
|
||||
}
|
||||
|
@ -1029,8 +1037,9 @@ generate_expr! {
|
|||
trailing_comma: bool,
|
||||
},
|
||||
/// `[Expr] LIST('.(', ',', ')', Ident [':' Expr])`
|
||||
Tupl {
|
||||
List {
|
||||
pos: Pos,
|
||||
kind: ListKind,
|
||||
ty: Option<&'a Self>,
|
||||
fields: &'a [Self],
|
||||
trailing_comma: bool,
|
||||
|
@ -1091,6 +1100,20 @@ generate_expr! {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum ListKind {
|
||||
Tuple,
|
||||
Array,
|
||||
}
|
||||
impl ListKind {
|
||||
fn term(self) -> TokenKind {
|
||||
match self {
|
||||
ListKind::Tuple => TokenKind::RParen,
|
||||
ListKind::Array => TokenKind::RBrack,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Expr<'_> {
|
||||
pub fn declares(&self, iden: DeclId, source: &str) -> Option<Ident> {
|
||||
match *self {
|
||||
|
|
|
@ -11,7 +11,7 @@ use {
|
|||
parser::{
|
||||
self,
|
||||
idfl::{self},
|
||||
CommentOr, CtorField, DeclId, Expr, ExprRef, FieldList, MatchBranch, Pos,
|
||||
CommentOr, CtorField, DeclId, Expr, ExprRef, FieldList, ListKind, MatchBranch, Pos,
|
||||
},
|
||||
ty::{
|
||||
self, Arg, ArrayLen, CompState, ConstData, EnumData, EnumField, FTask, FuncData,
|
||||
|
@ -1607,14 +1607,14 @@ impl<'a> Codegen<'a> {
|
|||
Expr::Directive { name: "inline", args: [func, args @ ..], .. } => {
|
||||
self.gen_call(func, args, true)
|
||||
}
|
||||
Expr::Tupl { pos, ty, fields, .. } => {
|
||||
let ty = ty
|
||||
Expr::List { pos, kind, ty, fields, .. } => {
|
||||
let rty = ty
|
||||
.map(|ty| self.ty(ty))
|
||||
.or(ctx.ty.map(|ty| self.tys.inner_of(ty).unwrap_or(ty)))
|
||||
.map(ty::Id::expand);
|
||||
|
||||
match ty {
|
||||
None => {
|
||||
match (rty, kind) {
|
||||
(None, ListKind::Tuple) => {
|
||||
let arg_base = self.tys.tmp.args.len();
|
||||
let mut values = Vec::with_capacity(fields.len());
|
||||
for field in fields {
|
||||
|
@ -1651,7 +1651,35 @@ impl<'a> Codegen<'a> {
|
|||
|
||||
Some(Value::ptr(mem).ty(tupl.into()))
|
||||
}
|
||||
Some(ty::Kind::Struct(s)) => {
|
||||
(None, ListKind::Array) => {
|
||||
let mut array_meta = None::<(ty::Id, Nid)>;
|
||||
let mut offset = 0;
|
||||
for field in fields {
|
||||
let (elem, mem) = match array_meta {
|
||||
Some((ty, mem)) => {
|
||||
(self.checked_expr(field, ty, "array element")?, mem)
|
||||
}
|
||||
None => {
|
||||
let expr = self.expr(field)?;
|
||||
let aty = self.tys.make_array(expr.ty, fields.len() as _);
|
||||
let mem = self.new_stack(pos, aty);
|
||||
array_meta = Some((expr.ty, mem));
|
||||
(expr, mem)
|
||||
}
|
||||
};
|
||||
let mem = self.offset(mem, offset);
|
||||
self.store_mem(mem, elem.ty, elem.id);
|
||||
offset += self.tys.size_of(elem.ty);
|
||||
}
|
||||
|
||||
let Some((_, mem)) = array_meta else {
|
||||
return self.error(pos, "can not infer the type of the array element, \
|
||||
array is empty, has no explicit type, and type is not obvious from the context");
|
||||
};
|
||||
|
||||
Some(Value::ptr(mem).ty(self.ci.nodes[mem].ty))
|
||||
}
|
||||
(Some(ty::Kind::Struct(s)), ListKind::Tuple) => {
|
||||
let mem = self.new_stack(pos, s.into());
|
||||
let mut offs = OffsetIter::new(s, self.tys);
|
||||
for field in fields {
|
||||
|
@ -1683,15 +1711,17 @@ impl<'a> Codegen<'a> {
|
|||
}
|
||||
Some(Value::ptr(mem).ty(s.into()))
|
||||
}
|
||||
Some(ty::Kind::Slice(s)) => {
|
||||
let slice = &self.tys.ins.slices[s];
|
||||
let len = slice.len().unwrap_or(fields.len());
|
||||
let elem = slice.elem;
|
||||
(Some(kty), ListKind::Array) => {
|
||||
let (len, elem) = if ty.is_none()
|
||||
&& let ty::Kind::Slice(a) = kty
|
||||
{
|
||||
let arr = &self.tys.ins.slices[a];
|
||||
(arr.len().unwrap_or(fields.len()), arr.elem)
|
||||
} else {
|
||||
(fields.len(), kty.compress())
|
||||
};
|
||||
let elem_size = self.tys.size_of(elem);
|
||||
let aty = slice.len().map_or_else(
|
||||
|| self.tys.make_array(elem, len as ArrayLen),
|
||||
|_| s.into(),
|
||||
);
|
||||
let aty = self.tys.make_array(elem, len as ArrayLen);
|
||||
|
||||
if len != fields.len() {
|
||||
return self.error(
|
||||
|
@ -1716,11 +1746,10 @@ impl<'a> Codegen<'a> {
|
|||
|
||||
Some(Value::ptr(mem).ty(aty))
|
||||
}
|
||||
Some(t) => self.error(
|
||||
(Some(t), ListKind::Tuple) => self.error(
|
||||
pos,
|
||||
fa!(
|
||||
"the {}type of the constructor is `{}`, \
|
||||
but thats not a struct nor slice or array",
|
||||
"the {}type of the constructor is `{}`, but thats not a struct",
|
||||
if ty.is_some() { "" } else { "inferred " },
|
||||
self.ty_display(t.compress()),
|
||||
),
|
||||
|
|
Loading…
Reference in a new issue