Merge branch 'main' into store-all-space-between-annotation-body

This commit is contained in:
Aidan 2024-07-29 09:42:33 -04:00
commit 125990855f
306 changed files with 12149 additions and 8820 deletions

View file

@ -21,6 +21,12 @@ pub struct Spaces<'a, T> {
pub after: &'a [CommentOrNewline<'a>],
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct SpacesBefore<'a, T> {
pub before: &'a [CommentOrNewline<'a>],
pub item: T,
}
#[derive(Copy, Clone, PartialEq)]
pub enum Spaced<'a, T> {
Item(T),
@ -1204,6 +1210,21 @@ impl<'a> Defs<'a> {
})
}
pub fn loc_defs<'b>(
&'b self,
) -> impl Iterator<Item = Result<Loc<TypeDef<'a>>, Loc<ValueDef<'a>>>> + 'b {
self.tags
.iter()
.enumerate()
.map(|(i, tag)| match tag.split() {
Ok(type_index) => Ok(Loc::at(self.regions[i], self.type_defs[type_index.index()])),
Err(value_index) => Err(Loc::at(
self.regions[i],
self.value_defs[value_index.index()],
)),
})
}
pub fn list_value_defs(&self) -> impl Iterator<Item = (usize, &ValueDef<'a>)> {
self.tags
.iter()
@ -2072,6 +2093,28 @@ pub trait Spaceable<'a> {
fn before(&'a self, _: &'a [CommentOrNewline<'a>]) -> Self;
fn after(&'a self, _: &'a [CommentOrNewline<'a>]) -> Self;
fn maybe_before(self, arena: &'a Bump, spaces: &'a [CommentOrNewline<'a>]) -> Self
where
Self: Sized + 'a,
{
if spaces.is_empty() {
self
} else {
arena.alloc(self).before(spaces)
}
}
fn maybe_after(self, arena: &'a Bump, spaces: &'a [CommentOrNewline<'a>]) -> Self
where
Self: Sized + 'a,
{
if spaces.is_empty() {
self
} else {
arena.alloc(self).after(spaces)
}
}
fn with_spaces_before(&'a self, spaces: &'a [CommentOrNewline<'a>], region: Region) -> Loc<Self>
where
Self: Sized,

View file

@ -333,7 +333,7 @@ where
let start = state.pos();
match spaces().parse(arena, state, min_indent) {
Ok((progress, spaces, state)) => {
if progress == NoProgress || state.column() >= min_indent {
if spaces.is_empty() || state.column() >= min_indent {
Ok((progress, spaces, state))
} else {
Err((progress, indent_problem(start)))
@ -344,6 +344,60 @@ where
}
}
pub fn require_newline_or_eof<'a, E>(newline_problem: fn(Position) -> E) -> impl Parser<'a, (), E>
where
E: 'a + SpaceProblem,
{
move |arena: &'a Bump, state: State<'a>, min_indent| {
// TODO: we can do this more efficiently by stopping as soon as we see a '#' or a newline
let (_, res, _) = space0_e(newline_problem).parse(arena, state.clone(), min_indent)?;
if !res.is_empty() || state.has_reached_end() {
Ok((NoProgress, (), state))
} else {
Err((NoProgress, newline_problem(state.pos())))
}
}
}
pub fn loc_space0_e<'a, E>(
indent_problem: fn(Position) -> E,
) -> impl Parser<'a, Loc<&'a [CommentOrNewline<'a>]>, E>
where
E: 'a + SpaceProblem,
{
move |arena, state: State<'a>, min_indent: u32| {
let mut newlines = Vec::new_in(arena);
let start = state.pos();
let mut comment_start = None;
let mut comment_end = None;
let res = consume_spaces(state, |start, space, end| {
newlines.push(space);
if !matches!(space, CommentOrNewline::Newline) {
if comment_start.is_none() {
comment_start = Some(start);
}
comment_end = Some(end);
}
});
match res {
Ok((progress, state)) => {
if newlines.is_empty() || state.column() >= min_indent {
let start = comment_start.unwrap_or(state.pos());
let end = comment_end.unwrap_or(state.pos());
let region = Region::new(start, end);
Ok((progress, Loc::at(region, newlines.into_bump_slice()), state))
} else {
Err((progress, indent_problem(start)))
}
}
Err((progress, err)) => Err((progress, err)),
}
}
}
fn begins_with_crlf(bytes: &[u8]) -> bool {
bytes.len() >= 2 && bytes[0] == b'\r' && bytes[1] == b'\n'
}
@ -387,7 +441,7 @@ where
F: FnMut(Position, CommentOrNewline<'a>, Position),
{
let mut progress = NoProgress;
let mut found_newline = false;
let mut found_newline = state.is_at_start_of_file();
loop {
let whitespace = fast_eat_whitespace(state.bytes());
if whitespace > 0 {

File diff suppressed because it is too large Load diff

View file

@ -17,6 +17,7 @@ pub mod module;
pub mod number_literal;
pub mod pattern;
pub mod problems;
pub mod remove_spaces;
pub mod src64;
pub mod state;
pub mod string_literal;

View file

@ -330,6 +330,7 @@ pub enum EExpr<'a> {
Start(Position),
End(Position),
BadExprEnd(Position),
StmtAfterExpr(Position),
Space(BadInputError, Position),
Dot(Position),
@ -355,6 +356,8 @@ pub enum EExpr<'a> {
QualifiedTag(Position),
BackpassComma(Position),
BackpassArrow(Position),
BackpassContinue(Position),
DbgContinue(Position),
When(EWhen<'a>, Position),
If(EIf<'a>, Position),
@ -383,6 +386,7 @@ pub enum EExpr<'a> {
IndentEnd(Position),
UnexpectedComma(Position),
UnexpectedTopLevelExpr(Position),
}
#[derive(Debug, Clone, PartialEq, Eq)]
@ -851,8 +855,9 @@ where
let cur_indent = INDENT.with(|i| *i.borrow());
println!(
"{:<5?}: {}{:<50}",
"{:<5?}:{:<2} {}{:<50}",
state.pos(),
min_indent,
&indent_text[..cur_indent * 2],
self.message
);
@ -868,8 +873,9 @@ where
};
println!(
"{:<5?}: {}{:<50} {:<15} {:?}",
"{:<5?}:{:<2} {}{:<50} {:<15} {:?}",
state.pos(),
min_indent,
&indent_text[..cur_indent * 2],
self.message,
format!("{:?}", progress),

File diff suppressed because it is too large Load diff

View file

@ -129,6 +129,10 @@ impl<'a> State<'a> {
pub fn len_region(&self, length: u32) -> Region {
Region::new(self.pos(), self.pos().bump_column(length))
}
pub fn is_at_start_of_file(&self) -> bool {
self.offset == 0
}
}
impl<'a> fmt::Debug for State<'a> {

View file

@ -22,7 +22,7 @@ pub fn parse_loc_with<'a>(
arena: &'a Bump,
input: &'a str,
) -> Result<Loc<ast::Expr<'a>>, SourceError<'a, SyntaxError<'a>>> {
let state = State::new(input.trim().as_bytes());
let state = State::new(input.as_bytes());
match crate::expr::test_parse_expr(0, arena, state.clone()) {
Ok(loc_expr) => Ok(loc_expr),
@ -31,7 +31,7 @@ pub fn parse_loc_with<'a>(
}
pub fn parse_defs_with<'a>(arena: &'a Bump, input: &'a str) -> Result<Defs<'a>, SyntaxError<'a>> {
let state = State::new(input.trim().as_bytes());
let state = State::new(input.as_bytes());
parse_module_defs(arena, state, Defs::default())
}
@ -40,7 +40,7 @@ pub fn parse_header_with<'a>(
arena: &'a Bump,
input: &'a str,
) -> Result<ast::Module<'a>, SyntaxError<'a>> {
let state = State::new(input.trim().as_bytes());
let state = State::new(input.as_bytes());
match crate::module::parse_header(arena, state.clone()) {
Ok((header, _)) => Ok(header),