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::{
|
crate::{
|
||||||
lexer::{self, Lexer, TokenKind},
|
lexer::{self, Lexer, TokenKind},
|
||||||
parser::{
|
parser::{
|
||||||
self, CommentOr, CtorField, EnumField, Expr, FieldList, Poser, Radix, StructField,
|
self, CommentOr, CtorField, EnumField, Expr, FieldList, ListKind, Poser, Radix,
|
||||||
UnionField,
|
StructField, UnionField,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
core::{
|
core::{
|
||||||
|
@ -60,7 +60,7 @@ fn token_group(kind: TokenKind) -> TokenGroup {
|
||||||
Colon => TG::Colon,
|
Colon => TG::Colon,
|
||||||
Semi | Comma => TG::Comma,
|
Semi | Comma => TG::Comma,
|
||||||
Dot => TG::Dot,
|
Dot => TG::Dot,
|
||||||
Ctor | Tupl | TArrow => TG::Ctor,
|
Ctor | Arr | Tupl | TArrow => TG::Ctor,
|
||||||
LParen | RParen => TG::Paren,
|
LParen | RParen => TG::Paren,
|
||||||
LBrace | RBrace | LBrack | RBrack => TG::Bracket,
|
LBrace | RBrace | LBrack | RBrack => TG::Bracket,
|
||||||
Number | Float => TG::Number,
|
Number | Float => TG::Number,
|
||||||
|
@ -391,35 +391,40 @@ impl<'a> Formatter<'a> {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Expr::Tupl {
|
Expr::List {
|
||||||
pos,
|
pos,
|
||||||
|
kind: term,
|
||||||
ty: Some(&Expr::Slice { pos: spos, size: Some(&Expr::Number { value, .. }), item }),
|
ty: Some(&Expr::Slice { pos: spos, size: Some(&Expr::Number { value, .. }), item }),
|
||||||
fields,
|
fields,
|
||||||
trailing_comma,
|
trailing_comma,
|
||||||
} if value as usize == fields.len() => self.fmt(
|
} if value as usize == fields.len() => self.fmt(
|
||||||
&Expr::Tupl {
|
&Expr::List {
|
||||||
pos,
|
pos,
|
||||||
|
kind: term,
|
||||||
ty: Some(&Expr::Slice { pos: spos, size: None, item }),
|
ty: Some(&Expr::Slice { pos: spos, size: None, item }),
|
||||||
fields,
|
fields,
|
||||||
trailing_comma,
|
trailing_comma,
|
||||||
},
|
},
|
||||||
f,
|
f,
|
||||||
),
|
),
|
||||||
Expr::Tupl { ty, fields, trailing_comma, .. } => {
|
Expr::List { ty, kind: term, fields, trailing_comma, .. } => {
|
||||||
if let Some(ty) = ty {
|
if let Some(ty) = ty {
|
||||||
self.fmt_paren(ty, f, unary)?;
|
self.fmt_paren(ty, f, unary)?;
|
||||||
}
|
}
|
||||||
f.write_str(".(")?;
|
let (start, end) = match term {
|
||||||
self.fmt_list(f, trailing_comma, ")", ",", fields, Self::fmt)
|
ListKind::Tuple => (".(", ")"),
|
||||||
|
ListKind::Array => (".[", "]"),
|
||||||
|
};
|
||||||
|
f.write_str(start)?;
|
||||||
|
self.fmt_list(f, trailing_comma, end, ",", fields, Self::fmt)
|
||||||
}
|
}
|
||||||
Expr::Slice { item, size, .. } => {
|
Expr::Slice { item, size, .. } => {
|
||||||
f.write_str("[")?;
|
f.write_str("[")?;
|
||||||
self.fmt(item, f)?;
|
|
||||||
if let Some(size) = size {
|
if let Some(size) = size {
|
||||||
f.write_str("; ")?;
|
|
||||||
self.fmt(size, f)?;
|
self.fmt(size, f)?;
|
||||||
}
|
}
|
||||||
f.write_str("]")
|
f.write_str("]")?;
|
||||||
|
self.fmt(item, f)
|
||||||
}
|
}
|
||||||
Expr::Index { base, index } => {
|
Expr::Index { base, index } => {
|
||||||
self.fmt(base, f)?;
|
self.fmt(base, f)?;
|
||||||
|
|
|
@ -138,6 +138,7 @@ pub enum TokenKind {
|
||||||
|
|
||||||
Ctor,
|
Ctor,
|
||||||
Tupl,
|
Tupl,
|
||||||
|
Arr,
|
||||||
TArrow,
|
TArrow,
|
||||||
|
|
||||||
Or,
|
Or,
|
||||||
|
@ -347,6 +348,7 @@ gen_token_kind! {
|
||||||
#[punkt]
|
#[punkt]
|
||||||
Ctor = ".{",
|
Ctor = ".{",
|
||||||
Tupl = ".(",
|
Tupl = ".(",
|
||||||
|
Arr = ".[",
|
||||||
TArrow = "=>",
|
TArrow = "=>",
|
||||||
// #define OP: each `#[prec]` delimeters a level of precedence from lowest to highest
|
// #define OP: each `#[prec]` delimeters a level of precedence from lowest to highest
|
||||||
#[ops]
|
#[ops]
|
||||||
|
@ -550,6 +552,7 @@ impl<'a> Lexer<'a> {
|
||||||
}
|
}
|
||||||
b'.' if self.advance_if(b'{') => T::Ctor,
|
b'.' if self.advance_if(b'{') => T::Ctor,
|
||||||
b'.' if self.advance_if(b'(') => T::Tupl,
|
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::TArrow,
|
||||||
b'&' if self.advance_if(b'&') => T::And,
|
b'&' if self.advance_if(b'&') => T::And,
|
||||||
b'|' if self.advance_if(b'|') => T::Or,
|
b'|' if self.advance_if(b'|') => T::Or,
|
||||||
|
|
|
@ -486,14 +486,20 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
body: self.ptr_expr()?,
|
body: self.ptr_expr()?,
|
||||||
},
|
},
|
||||||
T::Ctor => self.ctor(pos, None),
|
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 {
|
T::LBrack => E::Slice {
|
||||||
item: self.ptr_unit_expr()?,
|
size: {
|
||||||
size: self.advance_if(T::Semi).then(|| self.ptr_expr()).trans()?,
|
if self.advance_if(T::RBrack) {
|
||||||
pos: {
|
None
|
||||||
|
} else {
|
||||||
|
let adv = self.ptr_expr()?;
|
||||||
self.expect_advance(T::RBrack)?;
|
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 {
|
T::Band | T::Mul | T::Xor | T::Sub | T::Que | T::Not | T::Dot => E::UnOp {
|
||||||
pos,
|
pos,
|
||||||
|
@ -547,7 +553,7 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let token = self.token;
|
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();
|
self.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,7 +564,8 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
trailing_comma: core::mem::take(&mut self.trailing_sep),
|
trailing_comma: core::mem::take(&mut self.trailing_sep),
|
||||||
},
|
},
|
||||||
T::Ctor => self.ctor(token.start, Some(expr)),
|
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 {
|
T::LBrack => E::Index {
|
||||||
base: self.arena.alloc(expr),
|
base: self.arena.alloc(expr),
|
||||||
index: {
|
index: {
|
||||||
|
@ -586,11 +593,12 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
Some(expr)
|
Some(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tupl(&mut self, pos: Pos, ty: Option<Expr<'a>>) -> Expr<'a> {
|
fn tupl(&mut self, pos: Pos, ty: Option<Expr<'a>>, kind: ListKind) -> Expr<'a> {
|
||||||
Expr::Tupl {
|
Expr::List {
|
||||||
pos,
|
pos,
|
||||||
|
kind,
|
||||||
ty: ty.map(|ty| self.arena.alloc(ty)),
|
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),
|
trailing_comma: core::mem::take(&mut self.trailing_sep),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1029,8 +1037,9 @@ generate_expr! {
|
||||||
trailing_comma: bool,
|
trailing_comma: bool,
|
||||||
},
|
},
|
||||||
/// `[Expr] LIST('.(', ',', ')', Ident [':' Expr])`
|
/// `[Expr] LIST('.(', ',', ')', Ident [':' Expr])`
|
||||||
Tupl {
|
List {
|
||||||
pos: Pos,
|
pos: Pos,
|
||||||
|
kind: ListKind,
|
||||||
ty: Option<&'a Self>,
|
ty: Option<&'a Self>,
|
||||||
fields: &'a [Self],
|
fields: &'a [Self],
|
||||||
trailing_comma: bool,
|
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<'_> {
|
impl Expr<'_> {
|
||||||
pub fn declares(&self, iden: DeclId, source: &str) -> Option<Ident> {
|
pub fn declares(&self, iden: DeclId, source: &str) -> Option<Ident> {
|
||||||
match *self {
|
match *self {
|
||||||
|
|
|
@ -11,7 +11,7 @@ use {
|
||||||
parser::{
|
parser::{
|
||||||
self,
|
self,
|
||||||
idfl::{self},
|
idfl::{self},
|
||||||
CommentOr, CtorField, DeclId, Expr, ExprRef, FieldList, MatchBranch, Pos,
|
CommentOr, CtorField, DeclId, Expr, ExprRef, FieldList, ListKind, MatchBranch, Pos,
|
||||||
},
|
},
|
||||||
ty::{
|
ty::{
|
||||||
self, Arg, ArrayLen, CompState, ConstData, EnumData, EnumField, FTask, FuncData,
|
self, Arg, ArrayLen, CompState, ConstData, EnumData, EnumField, FTask, FuncData,
|
||||||
|
@ -1607,14 +1607,14 @@ impl<'a> Codegen<'a> {
|
||||||
Expr::Directive { name: "inline", args: [func, args @ ..], .. } => {
|
Expr::Directive { name: "inline", args: [func, args @ ..], .. } => {
|
||||||
self.gen_call(func, args, true)
|
self.gen_call(func, args, true)
|
||||||
}
|
}
|
||||||
Expr::Tupl { pos, ty, fields, .. } => {
|
Expr::List { pos, kind, ty, fields, .. } => {
|
||||||
let ty = ty
|
let rty = ty
|
||||||
.map(|ty| self.ty(ty))
|
.map(|ty| self.ty(ty))
|
||||||
.or(ctx.ty.map(|ty| self.tys.inner_of(ty).unwrap_or(ty)))
|
.or(ctx.ty.map(|ty| self.tys.inner_of(ty).unwrap_or(ty)))
|
||||||
.map(ty::Id::expand);
|
.map(ty::Id::expand);
|
||||||
|
|
||||||
match ty {
|
match (rty, kind) {
|
||||||
None => {
|
(None, ListKind::Tuple) => {
|
||||||
let arg_base = self.tys.tmp.args.len();
|
let arg_base = self.tys.tmp.args.len();
|
||||||
let mut values = Vec::with_capacity(fields.len());
|
let mut values = Vec::with_capacity(fields.len());
|
||||||
for field in fields {
|
for field in fields {
|
||||||
|
@ -1651,7 +1651,35 @@ impl<'a> Codegen<'a> {
|
||||||
|
|
||||||
Some(Value::ptr(mem).ty(tupl.into()))
|
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 mem = self.new_stack(pos, s.into());
|
||||||
let mut offs = OffsetIter::new(s, self.tys);
|
let mut offs = OffsetIter::new(s, self.tys);
|
||||||
for field in fields {
|
for field in fields {
|
||||||
|
@ -1683,15 +1711,17 @@ impl<'a> Codegen<'a> {
|
||||||
}
|
}
|
||||||
Some(Value::ptr(mem).ty(s.into()))
|
Some(Value::ptr(mem).ty(s.into()))
|
||||||
}
|
}
|
||||||
Some(ty::Kind::Slice(s)) => {
|
(Some(kty), ListKind::Array) => {
|
||||||
let slice = &self.tys.ins.slices[s];
|
let (len, elem) = if ty.is_none()
|
||||||
let len = slice.len().unwrap_or(fields.len());
|
&& let ty::Kind::Slice(a) = kty
|
||||||
let elem = slice.elem;
|
{
|
||||||
|
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 elem_size = self.tys.size_of(elem);
|
||||||
let aty = slice.len().map_or_else(
|
let aty = self.tys.make_array(elem, len as ArrayLen);
|
||||||
|| self.tys.make_array(elem, len as ArrayLen),
|
|
||||||
|_| s.into(),
|
|
||||||
);
|
|
||||||
|
|
||||||
if len != fields.len() {
|
if len != fields.len() {
|
||||||
return self.error(
|
return self.error(
|
||||||
|
@ -1716,11 +1746,10 @@ impl<'a> Codegen<'a> {
|
||||||
|
|
||||||
Some(Value::ptr(mem).ty(aty))
|
Some(Value::ptr(mem).ty(aty))
|
||||||
}
|
}
|
||||||
Some(t) => self.error(
|
(Some(t), ListKind::Tuple) => self.error(
|
||||||
pos,
|
pos,
|
||||||
fa!(
|
fa!(
|
||||||
"the {}type of the constructor is `{}`, \
|
"the {}type of the constructor is `{}`, but thats not a struct",
|
||||||
but thats not a struct nor slice or array",
|
|
||||||
if ty.is_some() { "" } else { "inferred " },
|
if ty.is_some() { "" } else { "inferred " },
|
||||||
self.ty_display(t.compress()),
|
self.ty_display(t.compress()),
|
||||||
),
|
),
|
||||||
|
|
Loading…
Reference in a new issue