mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 23:04:49 +00:00
parse defs with the new approach
This commit is contained in:
parent
d174cb72ae
commit
fa9ac912a0
3 changed files with 76 additions and 49 deletions
|
@ -7,9 +7,8 @@ extern crate roc_fmt;
|
||||||
mod test_fmt {
|
mod test_fmt {
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use roc_fmt::annotation::{Formattable, Newlines, Parens};
|
use roc_fmt::annotation::{Formattable, Newlines, Parens};
|
||||||
use roc_fmt::def::{fmt_type_def, fmt_value_def};
|
use roc_fmt::def::fmt_toplevel_defs;
|
||||||
use roc_fmt::module::fmt_module;
|
use roc_fmt::module::fmt_module;
|
||||||
use roc_fmt::spaces::fmt_spaces;
|
|
||||||
use roc_fmt::Buf;
|
use roc_fmt::Buf;
|
||||||
use roc_parse::ast::Module;
|
use roc_parse::ast::Module;
|
||||||
use roc_parse::module::{self, module_defs};
|
use roc_parse::module::{self, module_defs};
|
||||||
|
@ -89,7 +88,7 @@ mod test_fmt {
|
||||||
|
|
||||||
match module_defs().parse(arena, state) {
|
match module_defs().parse(arena, state) {
|
||||||
Ok((_, loc_defs, _)) => {
|
Ok((_, loc_defs, _)) => {
|
||||||
fmt_toplevel_defs(buf, loc_defs, 0);
|
fmt_toplevel_defs(buf, &loc_defs, 0);
|
||||||
}
|
}
|
||||||
Err(error) => panic!(
|
Err(error) => panic!(
|
||||||
r"Unexpected parse failure when parsing this for defs formatting:\n\n{:?}\n\nParse error was:\n\n{:?}\n\n",
|
r"Unexpected parse failure when parsing this for defs formatting:\n\n{:?}\n\nParse error was:\n\n{:?}\n\n",
|
||||||
|
|
|
@ -346,7 +346,7 @@ pub struct Defs<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Defs<'a> {
|
impl<'a> Defs<'a> {
|
||||||
pub fn defs<I>(&self) -> impl Iterator<Item = Result<&TypeDef<'a>, &ValueDef<'a>>> {
|
pub fn defs(&self) -> impl Iterator<Item = Result<&TypeDef<'a>, &ValueDef<'a>>> {
|
||||||
self.tags.iter().map(|tag| match tag.split() {
|
self.tags.iter().map(|tag| match tag.split() {
|
||||||
Ok(type_index) => Ok(&self.type_defs[type_index.index()]),
|
Ok(type_index) => Ok(&self.type_defs[type_index.index()]),
|
||||||
Err(value_index) => Err(&self.value_defs[value_index.index()]),
|
Err(value_index) => Err(&self.value_defs[value_index.index()]),
|
||||||
|
|
|
@ -17,6 +17,7 @@ use crate::state::State;
|
||||||
use crate::type_annotation;
|
use crate::type_annotation;
|
||||||
use bumpalo::collections::Vec;
|
use bumpalo::collections::Vec;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
|
use roc_collections::soa::Slice;
|
||||||
use roc_module::called_via::{BinOp, CalledVia, UnaryOp};
|
use roc_module::called_via::{BinOp, CalledVia, UnaryOp};
|
||||||
use roc_region::all::{Loc, Position, Region};
|
use roc_region::all::{Loc, Position, Region};
|
||||||
|
|
||||||
|
@ -924,78 +925,94 @@ fn parse_toplevel_defs_end<'a>(
|
||||||
let region = Region::span_across(&loc_pattern.region, &loc_def_expr.region);
|
let region = Region::span_across(&loc_pattern.region, &loc_def_expr.region);
|
||||||
|
|
||||||
if spaces_before_current.len() <= 1 {
|
if spaces_before_current.len() <= 1 {
|
||||||
|
let comment = match spaces_before_current.get(0) {
|
||||||
|
Some(CommentOrNewline::LineComment(s)) => Some(*s),
|
||||||
|
Some(CommentOrNewline::DocComment(s)) => Some(*s),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
match defs.last() {
|
match defs.last() {
|
||||||
Some((
|
Some(Err(ValueDef::Annotation(ann_pattern, ann_type))) => {
|
||||||
before_ann_spaces,
|
// join this body with the preceding annotation
|
||||||
Def::Value(ValueDef::Annotation(ann_pattern, ann_type)),
|
|
||||||
)) => {
|
let value_def = ValueDef::AnnotatedBody {
|
||||||
return append_body_definition_help(
|
ann_pattern: arena.alloc(*ann_pattern),
|
||||||
arena,
|
ann_type: arena.alloc(*ann_type),
|
||||||
defs,
|
comment,
|
||||||
|
body_pattern: arena.alloc(loc_pattern),
|
||||||
|
body_expr: &*arena.alloc(loc_def_expr),
|
||||||
|
};
|
||||||
|
|
||||||
|
let region = Region::span_across(&ann_pattern.region, ®ion);
|
||||||
|
|
||||||
|
defs.push_value_def(
|
||||||
|
value_def,
|
||||||
region,
|
region,
|
||||||
before_ann_spaces,
|
|
||||||
spaces_before_current,
|
spaces_before_current,
|
||||||
loc_pattern,
|
&[],
|
||||||
loc_def_expr,
|
)
|
||||||
ann_pattern,
|
|
||||||
ann_type,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Some((
|
Some(Ok(TypeDef::Alias {
|
||||||
before_ann_spaces,
|
|
||||||
Def::Type(TypeDef::Alias {
|
|
||||||
header,
|
header,
|
||||||
ann: ann_type,
|
ann: ann_type,
|
||||||
}),
|
})) => {
|
||||||
)) => {
|
|
||||||
// This is a case like
|
// This is a case like
|
||||||
// UserId x : [UserId Int]
|
// UserId x : [UserId Int]
|
||||||
// UserId x = UserId 42
|
// UserId x = UserId 42
|
||||||
// We optimistically parsed the first line as an alias; we now turn it
|
// We optimistically parsed the first line as an alias; we now turn it
|
||||||
// into an annotation.
|
// into an annotation.
|
||||||
|
|
||||||
let loc_name =
|
let loc_name =
|
||||||
arena.alloc(header.name.map(|x| Pattern::Tag(x)));
|
arena.alloc(header.name.map(|x| Pattern::Tag(x)));
|
||||||
let ann_pattern = Pattern::Apply(loc_name, header.vars);
|
let ann_pattern = Pattern::Apply(loc_name, header.vars);
|
||||||
|
|
||||||
let vars_region =
|
let vars_region =
|
||||||
Region::across_all(header.vars.iter().map(|v| &v.region));
|
Region::across_all(header.vars.iter().map(|v| &v.region));
|
||||||
let region_ann_pattern =
|
let region_ann_pattern =
|
||||||
Region::span_across(&loc_name.region, &vars_region);
|
Region::span_across(&loc_name.region, &vars_region);
|
||||||
let loc_ann_pattern = Loc::at(region_ann_pattern, ann_pattern);
|
let loc_ann_pattern = Loc::at(region_ann_pattern, ann_pattern);
|
||||||
|
|
||||||
return append_body_definition_help(
|
let value_def = ValueDef::AnnotatedBody {
|
||||||
arena,
|
ann_pattern: arena.alloc(loc_ann_pattern),
|
||||||
defs,
|
ann_type: arena.alloc(*ann_type),
|
||||||
|
comment,
|
||||||
|
body_pattern: arena.alloc(loc_pattern),
|
||||||
|
body_expr: &*arena.alloc(loc_def_expr),
|
||||||
|
};
|
||||||
|
|
||||||
|
let region = Region::span_across(&header.name.region, ®ion);
|
||||||
|
|
||||||
|
defs.push_value_def(
|
||||||
|
value_def,
|
||||||
region,
|
region,
|
||||||
before_ann_spaces,
|
|
||||||
spaces_before_current,
|
spaces_before_current,
|
||||||
loc_pattern,
|
&[],
|
||||||
loc_def_expr,
|
)
|
||||||
arena.alloc(loc_ann_pattern),
|
|
||||||
ann_type,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
defs.extend(last);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// the previous and current def can't be joined up
|
// the previous and current def can't be joined up
|
||||||
let mut loc_def = Loc::at(
|
let value_def = ValueDef::Body(
|
||||||
region,
|
|
||||||
Def::Value(ValueDef::Body(
|
|
||||||
arena.alloc(loc_pattern),
|
arena.alloc(loc_pattern),
|
||||||
&*arena.alloc(loc_def_expr),
|
&*arena.alloc(loc_def_expr),
|
||||||
)),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if !spaces_before_current.is_empty() {
|
defs.push_value_def(
|
||||||
loc_def = arena
|
value_def,
|
||||||
.alloc(loc_def.value)
|
region,
|
||||||
.with_spaces_before(spaces_before_current, loc_def.region);
|
spaces_before_current,
|
||||||
|
&[],
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// the previous and current def can't be joined up
|
||||||
|
let value_def = ValueDef::Body(
|
||||||
|
arena.alloc(loc_pattern),
|
||||||
|
&*arena.alloc(loc_def_expr),
|
||||||
|
);
|
||||||
|
|
||||||
defs.push(arena.alloc(loc_def));
|
defs.push_value_def(value_def, region, spaces_before_current, &[])
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
parse_toplevel_defs_end(options, column, defs, arena, state)
|
parse_toplevel_defs_end(options, column, defs, arena, state)
|
||||||
|
@ -2290,12 +2307,23 @@ pub fn toplevel_defs<'a>(min_indent: u32) -> impl Parser<'a, Defs<'a>, EExpr<'a>
|
||||||
|
|
||||||
let output = Defs::default();
|
let output = Defs::default();
|
||||||
|
|
||||||
let (_, output, state) =
|
let (_, mut output, state) =
|
||||||
parse_toplevel_defs_end(options, start_column, output, arena, state)?;
|
parse_toplevel_defs_end(options, start_column, output, arena, state)?;
|
||||||
|
|
||||||
let (_, final_space, state) =
|
let (_, final_space, state) =
|
||||||
space0_e(start_column, EExpr::IndentEnd).parse(arena, state)?;
|
space0_e(start_column, EExpr::IndentEnd).parse(arena, state)?;
|
||||||
|
|
||||||
|
// add surrounding whitespace
|
||||||
|
let before = Slice::extend_new(&mut output.spaces, initial_space.iter().copied());
|
||||||
|
let after = Slice::extend_new(&mut output.spaces, final_space.iter().copied());
|
||||||
|
|
||||||
|
debug_assert!(output.space_before[0].is_empty());
|
||||||
|
output.space_before[0] = before;
|
||||||
|
|
||||||
|
let last = output.tags.len() - 1;
|
||||||
|
debug_assert!(output.space_after[last].is_empty() || after.is_empty());
|
||||||
|
output.space_after[last] = after;
|
||||||
|
|
||||||
Ok((MadeProgress, output, state))
|
Ok((MadeProgress, output, state))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue