Support both inline and header imports

Load will now convert header imports to inline import defs, so that
we can support both temporarily.
This commit is contained in:
Agus Zubiaga 2024-04-20 18:57:53 -03:00
parent 7a53484479
commit 7ebfc6d06d
No known key found for this signature in database
18 changed files with 235 additions and 121 deletions

View file

@ -8,11 +8,9 @@ use roc_fmt::def::fmt_defs;
use roc_fmt::module::fmt_module;
use roc_fmt::spaces::RemoveSpaces;
use roc_fmt::{Ast, Buf};
use roc_parse::{
module::{self, module_defs},
parser::{Parser, SyntaxError},
state::State,
};
use roc_parse::ast::Defs;
use roc_parse::module::parse_module_defs;
use roc_parse::{module, parser::SyntaxError, state::State};
#[derive(Copy, Clone, Debug)]
pub enum FormatMode {
@ -228,7 +226,7 @@ fn parse_all<'a>(arena: &'a Bump, src: &'a str) -> Result<Ast<'a>, SyntaxError<'
let (module, state) = module::parse_header(arena, State::new(src.as_bytes()))
.map_err(|e| SyntaxError::Header(e.problem))?;
let (_, defs, _) = module_defs().parse(arena, state, 0).map_err(|(_, e)| e)?;
let defs = parse_module_defs(arena, state, Defs::default())?;
Ok(Ast { module, defs })
}

View file

@ -821,6 +821,7 @@ mod cli_run {
#[test]
#[cfg_attr(windows, ignore)]
#[serial(cli_platform)]
#[ignore = "Disabled until https://github.com/roc-lang/basic-cli/pull/183 lands"]
fn cli_file_check() {
let path = file_path_from_root("examples/cli", "fileBROKEN.roc");
let out = run_roc([CMD_CHECK, path.to_str().unwrap()], &[], &[]);
@ -1439,7 +1440,7 @@ mod cli_run {
r#"
UNUSED IMPORT in ...nown_bad/UnusedImportButWithALongFileNameForTesting.roc
Nothing from Symbol is used in this module.
Symbol is imported but not used.
3 imports [Symbol.{ Ident }]
^^^^^^^^^^^^^^^^
@ -1483,7 +1484,7 @@ mod cli_run {
r#"
UNUSED IMPORT in tests/known_bad/UnusedImport.roc
Nothing from Symbol is used in this module.
Symbol is imported but not used.
3 imports [Symbol.{ Ident }]
^^^^^^^^^^^^^^^^

View file

@ -4561,7 +4561,7 @@ mod test_reporting {
test_report!(
comment_with_control_character,
"# comment with a \x07\n",
@r"
@r###"
ASCII CONTROL CHARACTER in tmp/comment_with_control_character/Test.roc
I encountered an ASCII control character:
@ -4570,7 +4570,7 @@ mod test_reporting {
^
ASCII control characters are not allowed.
"
"###
);
test_report!(
@ -4919,9 +4919,9 @@ mod test_reporting {
dict_type_formatting,
indoc!(
r#"
app "dict" imports [ Dict ] provides [main] to "./platform"
app "dict" imports [] provides [main] to "./platform"
myDict : Dict.Dict Num.I64 Str
myDict : Dict Num.I64 Str
myDict = Dict.insert (Dict.empty {}) "foo" 42
main = myDict
@ -4932,7 +4932,7 @@ mod test_reporting {
Something is off with the body of the `myDict` definition:
3 myDict : Dict.Dict Num.I64 Str
3 myDict : Dict Num.I64 Str
4 myDict = Dict.insert (Dict.empty {}) "foo" 42
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -9310,7 +9310,7 @@ In roc, functions are always written as a lambda, like{}
type_error_in_apply_is_circular,
indoc!(
r#"
app "test" imports [Set] provides [go] to "./platform"
app "test" imports [] provides [go] to "./platform"
S a : { set : Set.Set a }

View file

@ -49,10 +49,11 @@ use roc_mono::{drop_specialization, inc_dec};
use roc_packaging::cache::RocCacheDir;
use roc_parse::ast::{self, CommentOrNewline, ExtractSpaces, Spaced, ValueDef};
use roc_parse::header::{
ExposedName, HeaderType, PackageEntry, PackageHeader, PlatformHeader, To, TypedIdent,
ExposedName, HeaderType, ImportsKeywordItem, PackageEntry, PackageHeader, PlatformHeader, To,
TypedIdent,
};
use roc_parse::module::module_defs;
use roc_parse::parser::{FileError, Parser, SourceError, SyntaxError};
use roc_parse::module::parse_module_defs;
use roc_parse::parser::{FileError, SourceError, SyntaxError};
use roc_problem::Severity;
use roc_region::all::{LineInfo, Loc, Region};
#[cfg(not(target_family = "wasm"))]
@ -3520,6 +3521,7 @@ fn load_builtin_module_help<'a>(
generates_with: &[],
},
module_comments: comments,
header_imports: Some(header.imports),
};
(info, parse_state)
@ -3842,6 +3844,7 @@ fn parse_header<'a>(
exposes: unspace(arena, header.exposes.item.items),
},
module_comments: comments,
header_imports: Some(header.imports),
};
let (module_id, module_name, header) =
@ -3890,6 +3893,7 @@ fn parse_header<'a>(
generates_with: unspace(arena, header.generates_with.item.items),
},
module_comments: comments,
header_imports: Some(header.imports),
};
let (module_id, _, header) =
@ -3941,6 +3945,7 @@ fn parse_header<'a>(
to_platform: header.provides.to.value,
},
module_comments: comments,
header_imports: header.imports,
};
let (module_id, _, resolved_header) =
@ -4209,6 +4214,7 @@ struct HeaderInfo<'a> {
packages: &'a [Loc<PackageEntry<'a>>],
header_type: HeaderType<'a>,
module_comments: &'a [CommentOrNewline<'a>],
header_imports: Option<ImportsKeywordItem<'a>>,
}
fn build_header<'a>(
@ -4224,6 +4230,7 @@ fn build_header<'a>(
packages,
header_type,
module_comments: header_comments,
header_imports,
} = info;
let declared_name: ModuleName = match &header_type {
@ -4293,6 +4300,7 @@ fn build_header<'a>(
header_comments,
module_timing,
opt_shorthand,
header_imports,
},
))
}
@ -4906,6 +4914,7 @@ fn build_package_header<'a>(
packages,
header_type,
module_comments: comments,
header_imports: None,
};
build_header(info, parse_state, module_ids, module_timing)
@ -4962,6 +4971,7 @@ fn build_platform_header<'a>(
packages: &[],
header_type,
module_comments: comments,
header_imports: Some(header.imports),
};
build_header(info, parse_state, module_ids, module_timing)
@ -5163,9 +5173,13 @@ fn parse<'a>(
let parse_start = Instant::now();
let source = header.parse_state.original_bytes();
let parse_state = header.parse_state;
let parsed_defs = match module_defs().parse(arena, parse_state.clone(), 0) {
Ok((_, success, _state)) => success,
Err((_, fail)) => {
let header_import_defs =
roc_parse::ast::Module::header_imports_to_defs(arena, header.header_imports);
let parsed_defs = match parse_module_defs(arena, parse_state.clone(), header_import_defs) {
Ok(success) => success,
Err(fail) => {
return Err(LoadingProblem::ParsingFailed(
fail.into_file_error(header.module_path, &parse_state),
));

View file

@ -92,6 +92,7 @@ pub(crate) struct ModuleHeader<'a> {
pub(crate) parse_state: roc_parse::state::State<'a>,
pub(crate) header_type: HeaderType<'a>,
pub(crate) header_comments: &'a [CommentOrNewline<'a>],
pub(crate) header_imports: Option<roc_parse::header::ImportsKeywordItem<'a>>,
pub(crate) module_timing: ModuleTiming,
pub(crate) opt_shorthand: Option<&'a str>,
}

View file

@ -1412,12 +1412,12 @@ fn alias_using_builtin_name() {
(
"BoolExtra.roc",
indoc!(
r#"
r"
interface BoolExtra exposes [toNum] imports []
toNum = \value ->
if value then 1 else 0
"#
"
),
),
(

View file

@ -1,6 +1,10 @@
use bumpalo::Bump;
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use roc_parse::{module, module::module_defs, parser::Parser, state::State};
use roc_parse::{
ast::Defs,
module::{self, parse_module_defs},
state::State,
};
use std::path::PathBuf;
pub fn parse_benchmark(c: &mut Criterion) {
@ -18,11 +22,7 @@ pub fn parse_benchmark(c: &mut Criterion) {
let (_actual, state) =
module::parse_header(&arena, State::new(src.as_bytes())).unwrap();
let min_indent = 0;
let res = module_defs()
.parse(&arena, state, min_indent)
.map(|tuple| tuple.1)
.unwrap();
let res = parse_module_defs(&arena, state, Defs::default()).unwrap();
black_box(res.len());
})
@ -43,11 +43,7 @@ pub fn parse_benchmark(c: &mut Criterion) {
let (_actual, state) =
module::parse_header(&arena, State::new(src.as_bytes())).unwrap();
let min_indent = 0;
let res = module_defs()
.parse(&arena, state, min_indent)
.map(|tuple| tuple.1)
.unwrap();
let res = parse_module_defs(&arena, state, Defs::default()).unwrap();
black_box(res.len());
})

View file

@ -98,6 +98,115 @@ pub struct Module<'a> {
pub header: Header<'a>,
}
impl<'a> Module<'a> {
pub fn header_imports_to_defs(
arena: &'a Bump,
imports: Option<
header::KeywordItem<'a, header::ImportsKeyword, header::ImportsCollection<'a>>,
>,
) -> Defs<'a> {
let mut defs = Defs::default();
if let Some(imports) = imports {
let len = imports.item.len();
for (index, import) in imports.item.iter().enumerate() {
let spaced = import.extract_spaces();
let value_def = match spaced.item {
header::ImportsEntry::Package(pkg_name, name, exposed) => {
Self::header_import_to_value_def(
Some(pkg_name),
name,
exposed,
import.region,
)
}
header::ImportsEntry::Module(name, exposed) => {
Self::header_import_to_value_def(None, name, exposed, import.region)
}
header::ImportsEntry::IngestedFile(path, typed_ident) => {
ValueDef::IngestedFileImport(IngestedFileImport {
before_path: &[],
path: Loc {
value: path,
region: import.region,
},
name: header::KeywordItem {
keyword: Spaces {
before: &[],
item: ImportAsKeyword,
after: &[],
},
item: Loc {
value: typed_ident,
region: import.region,
},
},
})
}
};
defs.push_value_def(
value_def,
import.region,
if index == 0 {
let mut before = vec![CommentOrNewline::Newline, CommentOrNewline::Newline];
before.extend(spaced.before);
arena.alloc(before)
} else {
spaced.before
},
if index == len - 1 {
let mut after = spaced.after.to_vec();
after.push(CommentOrNewline::Newline);
after.push(CommentOrNewline::Newline);
arena.alloc(after)
} else {
spaced.after
},
);
}
}
defs
}
fn header_import_to_value_def(
pkg_name: Option<&'a str>,
name: header::ModuleName<'a>,
exposed: Collection<'a, Loc<Spaced<'a, header::ExposedName<'a>>>>,
region: Region,
) -> ValueDef<'a> {
use crate::header::KeywordItem;
let new_exposed = if exposed.is_empty() {
None
} else {
Some(KeywordItem {
keyword: Spaces {
before: &[],
item: ImportExposingKeyword,
after: &[],
},
item: exposed,
})
};
ValueDef::ModuleImport(ModuleImport {
before_name: &[],
name: Loc {
region,
value: ImportedModuleName {
package: pkg_name,
name,
},
},
alias: None,
exposed: new_exposed,
})
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Header<'a> {
Interface(InterfaceHeader<'a>),

View file

@ -2442,41 +2442,42 @@ fn assigned_expr_field_to_pattern_help<'a>(
})
}
pub fn toplevel_defs<'a>() -> impl Parser<'a, Defs<'a>, EExpr<'a>> {
move |arena, state: State<'a>, min_indent: u32| {
let (_, initial_space, state) =
space0_e(EExpr::IndentEnd).parse(arena, state, min_indent)?;
pub fn parse_top_level_defs<'a>(
arena: &'a bumpalo::Bump,
state: State<'a>,
mut output: Defs<'a>,
) -> ParseResult<'a, Defs<'a>, EExpr<'a>> {
let (_, initial_space, state) = space0_e(EExpr::IndentEnd).parse(arena, state, 0)?;
let start_column = state.column();
let start_column = state.column();
let options = ExprParseOptions {
accept_multi_backpassing: true,
check_for_arrow: true,
suffixed_found: false,
};
let options = ExprParseOptions {
accept_multi_backpassing: true,
check_for_arrow: true,
suffixed_found: false,
};
let mut output = Defs::default();
let before = Slice::extend_new(&mut output.spaces, initial_space.iter().copied());
let existing_len = output.tags.len();
let (_, mut output, state) = parse_defs_end(options, start_column, output, arena, state)?;
let before = Slice::extend_new(&mut output.spaces, initial_space.iter().copied());
let (_, final_space, state) =
space0_e(EExpr::IndentEnd).parse(arena, state, start_column)?;
let (_, mut output, state) = parse_defs_end(options, start_column, output, arena, state)?;
if !output.tags.is_empty() {
// add surrounding whitespace
let after = Slice::extend_new(&mut output.spaces, final_space.iter().copied());
let (_, final_space, state) = space0_e(EExpr::IndentEnd).parse(arena, state, start_column)?;
debug_assert!(output.space_before[0].is_empty());
output.space_before[0] = before;
if output.tags.len() > existing_len {
// add surrounding whitespace
let after = Slice::extend_new(&mut output.spaces, final_space.iter().copied());
let last = output.tags.len() - 1;
debug_assert!(output.space_after[last].is_empty() || after.is_empty());
output.space_after[last] = after;
}
debug_assert!(output.space_before[existing_len].is_empty());
output.space_before[existing_len] = before;
Ok((MadeProgress, output, state))
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))
}
// PARSER HELPERS

View file

@ -211,7 +211,6 @@ keywords! {
RequiresKeyword => "requires",
ProvidesKeyword => "provides",
ToKeyword => "to",
// [modules-revamp] TODO: Remove
ImportsKeyword => "imports",
}
@ -230,6 +229,9 @@ pub struct InterfaceHeader<'a> {
pub imports: KeywordItem<'a, ImportsKeyword, Collection<'a, Loc<Spaced<'a, ImportsEntry<'a>>>>>,
}
pub type ImportsKeywordItem<'a> = KeywordItem<'a, ImportsKeyword, ImportsCollection<'a>>;
pub type ImportsCollection<'a> = Collection<'a, Loc<Spaced<'a, ImportsEntry<'a>>>>;
#[derive(Clone, Debug, PartialEq)]
pub struct HostedHeader<'a> {
pub before_name: &'a [CommentOrNewline<'a>],

View file

@ -28,12 +28,19 @@ fn end_of_file<'a>() -> impl Parser<'a, (), SyntaxError<'a>> {
}
}
#[inline(always)]
pub fn module_defs<'a>() -> impl Parser<'a, Defs<'a>, SyntaxError<'a>> {
skip_second!(
specialize_err(SyntaxError::Expr, crate::expr::toplevel_defs(),),
end_of_file()
)
pub fn parse_module_defs<'a>(
arena: &'a bumpalo::Bump,
state: State<'a>,
defs: Defs<'a>,
) -> Result<Defs<'a>, SyntaxError<'a>> {
let min_indent = 0;
match crate::expr::parse_top_level_defs(arena, state.clone(), defs) {
Ok((_, defs, state)) => match end_of_file().parse(arena, state, min_indent) {
Ok(_) => Ok(defs),
Err((_, fail)) => Err(fail),
},
Err((_, fail)) => Err(SyntaxError::Expr(fail, state.pos())),
}
}
pub fn parse_header<'a>(

View file

@ -1,7 +1,6 @@
use crate::ast;
use crate::ast::Defs;
use crate::module::module_defs;
use crate::parser::Parser;
use crate::module::parse_module_defs;
use crate::parser::SourceError;
use crate::parser::SyntaxError;
use crate::state::State;
@ -34,12 +33,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 min_indent = 0;
match module_defs().parse(arena, state, min_indent) {
Ok(tuple) => Ok(tuple.1),
Err(tuple) => Err(tuple.1),
}
parse_module_defs(arena, state, Defs::default())
}
pub fn parse_header_with<'a>(

View file

@ -22,8 +22,8 @@ mod test_parse {
use roc_parse::ast::StrSegment::*;
use roc_parse::ast::{self, EscapedChar};
use roc_parse::ast::{CommentOrNewline, StrLiteral::*};
use roc_parse::module::module_defs;
use roc_parse::parser::{Parser, SyntaxError};
use roc_parse::module::parse_module_defs;
use roc_parse::parser::SyntaxError;
use roc_parse::state::State;
use roc_parse::test_helpers::parse_expr_with;
use roc_region::all::{Loc, Region};
@ -352,9 +352,7 @@ mod test_parse {
List.map list isTest
"
);
let actual = module_defs()
.parse(&arena, State::new(src.as_bytes()), 0)
.map(|tuple| tuple.1);
let actual = parse_module_defs(&arena, State::new(src.as_bytes()), ast::Defs::default());
// It should occur twice in the debug output - once for the pattern,
// and then again for the lookup.
@ -378,13 +376,12 @@ mod test_parse {
);
let state = State::new(src.as_bytes());
let parser = module_defs();
let parsed = parser.parse(arena, state, 0);
let parsed = parse_module_defs(arena, state, ast::Defs::default());
match parsed {
Ok((_, _, _state)) => {
Ok(_) => {
// dbg!(_state);
}
Err((_, _fail)) => {
Err(_) => {
// dbg!(_fail, _state);
panic!("Failed to parse!");
}

View file

@ -3448,7 +3448,7 @@ mod solve_expr {
infer_eq_without_problem(
indoc!(
r#"
app "test" imports [Result.{ Result }] provides [main] to "./platform"
app "test" imports [] provides [main] to "./platform"
boom = \_ -> boom {}

View file

@ -355,7 +355,7 @@ fn encode_use_stdlib() {
indoc!(
r#"
app "test"
imports [Encode, TotallyNotJson]
imports [TotallyNotJson]
provides [main] to "./platform"
HelloWorld := {} implements [Encoding {toEncoder}]
@ -383,7 +383,7 @@ fn encode_use_stdlib_without_wrapping_custom() {
indoc!(
r#"
app "test"
imports [Encode, TotallyNotJson]
imports [TotallyNotJson]
provides [main] to "./platform"
HelloWorld := {} implements [Encoding {toEncoder}]
@ -433,7 +433,7 @@ fn to_encoder_encode_custom_has_capture() {
indoc!(
r#"
app "test"
imports [Encode, TotallyNotJson]
imports [TotallyNotJson]
provides [main] to "./platform"
HelloWorld := Str implements [Encoding {toEncoder}]
@ -473,7 +473,7 @@ mod encode_immediate {
assert_evals_to!(
indoc!(
r#"
app "test" imports [Encode, TotallyNotJson] provides [main] to "./platform"
app "test" imports [TotallyNotJson] provides [main] to "./platform"
main =
when Str.fromUtf8 (Encode.toBytes "foo" TotallyNotJson.json) is
@ -492,7 +492,7 @@ mod encode_immediate {
assert_evals_to!(
indoc!(
r#"
app "test" imports [Encode, TotallyNotJson] provides [main] to "./platform"
app "test" imports [TotallyNotJson] provides [main] to "./platform"
main =
when Str.fromUtf8 (Encode.toBytes [1, 2, 3] TotallyNotJson.json) is
@ -511,7 +511,7 @@ mod encode_immediate {
assert_evals_to!(
indoc!(
r#"
app "test" imports [Encode, TotallyNotJson] provides [main] to "./platform"
app "test" imports [TotallyNotJson] provides [main] to "./platform"
main =
when Str.fromUtf8 (Encode.toBytes Bool.false TotallyNotJson.json) is
@ -532,7 +532,7 @@ mod encode_immediate {
assert_evals_to!(
&format!(indoc!(
r#"
app "test" imports [Encode, TotallyNotJson] provides [main] to "./platform"
app "test" imports [TotallyNotJson] provides [main] to "./platform"
main =
when Str.fromUtf8 (Encode.toBytes {}{} TotallyNotJson.json) is
@ -572,7 +572,7 @@ fn encode_derived_record_one_field_string() {
indoc!(
r#"
app "test"
imports [Encode, TotallyNotJson]
imports [TotallyNotJson]
provides [main] to "./platform"
main =
@ -595,7 +595,7 @@ fn encode_derived_record_two_fields_strings() {
indoc!(
r#"
app "test"
imports [Encode, TotallyNotJson]
imports [TotallyNotJson]
provides [main] to "./platform"
main =
@ -619,7 +619,7 @@ fn encode_derived_nested_record_string() {
indoc!(
r#"
app "test"
imports [Encode, TotallyNotJson]
imports [TotallyNotJson]
provides [main] to "./platform"
main =
@ -643,7 +643,7 @@ fn encode_derived_tag_one_payload_string() {
indoc!(
r#"
app "test"
imports [Encode, TotallyNotJson]
imports [TotallyNotJson]
provides [main] to "./platform"
main =
@ -666,7 +666,7 @@ fn encode_derived_tag_two_payloads_string() {
indoc!(
r#"
app "test"
imports [Encode, TotallyNotJson]
imports [TotallyNotJson]
provides [main] to "./platform"
main =
@ -689,7 +689,7 @@ fn encode_derived_nested_tag_string() {
indoc!(
r#"
app "test"
imports [Encode, TotallyNotJson]
imports [TotallyNotJson]
provides [main] to "./platform"
main =
@ -714,7 +714,7 @@ fn encode_derived_nested_record_tag_record() {
indoc!(
r#"
app "test"
imports [Encode, TotallyNotJson]
imports [TotallyNotJson]
provides [main] to "./platform"
main =
@ -738,7 +738,7 @@ fn encode_derived_list_string() {
indoc!(
r#"
app "test"
imports [Encode, TotallyNotJson]
imports [TotallyNotJson]
provides [main] to "./platform"
main =
@ -763,7 +763,7 @@ fn encode_derived_list_of_records() {
indoc!(
r#"
app "test"
imports [Encode, TotallyNotJson]
imports [TotallyNotJson]
provides [main] to "./platform"
main =
@ -787,7 +787,7 @@ fn encode_derived_list_of_lists_of_strings() {
indoc!(
r#"
app "test"
imports [Encode, TotallyNotJson]
imports [TotallyNotJson]
provides [main] to "./platform"
main =
@ -812,7 +812,7 @@ fn encode_derived_record_with_many_types() {
indoc!(
r#"
app "test"
imports [Encode, TotallyNotJson]
imports [TotallyNotJson]
provides [main] to "./platform"
main =
@ -839,7 +839,7 @@ fn encode_derived_tuple_two_fields() {
indoc!(
r#"
app "test"
imports [Encode, TotallyNotJson]
imports [TotallyNotJson]
provides [main] to "./platform"
main =
@ -862,7 +862,7 @@ fn encode_derived_tuple_of_tuples() {
indoc!(
r#"
app "test"
imports [Encode, TotallyNotJson]
imports [TotallyNotJson]
provides [main] to "./platform"
main =
@ -886,7 +886,7 @@ fn encode_derived_generic_record_with_different_field_types() {
indoc!(
r#"
app "test"
imports [Encode, TotallyNotJson]
imports [TotallyNotJson]
provides [main] to "./platform"
Q a b := {a: a, b: b} implements [Encoding]
@ -912,7 +912,7 @@ fn encode_derived_generic_tag_with_different_field_types() {
indoc!(
r#"
app "test"
imports [Encode, TotallyNotJson]
imports [TotallyNotJson]
provides [main] to "./platform"
Q a b := [A a, B b] implements [Encoding]
@ -940,7 +940,7 @@ fn specialize_unique_newtype_records() {
indoc!(
r#"
app "test"
imports [Encode, TotallyNotJson]
imports [TotallyNotJson]
provides [main] to "./platform"
main =

View file

@ -2,7 +2,7 @@ use bumpalo::Bump;
use roc_fmt::{annotation::Formattable, module::fmt_module};
use roc_parse::{
ast::{Defs, Expr, Malformed, Module},
module::module_defs,
module::parse_module_defs,
parser::{Parser, SyntaxError},
state::State,
test_helpers::{parse_defs_with, parse_expr_with, parse_header_with},
@ -170,9 +170,7 @@ impl<'a> Input<'a> {
.parse(arena, state.clone(), min_indent)
.map_err(|(_, fail)| SyntaxError::Header(fail))?;
let (_, module_defs, _state) = module_defs()
.parse(arena, state, min_indent)
.map_err(|(_, fail)| fail)?;
let module_defs = parse_module_defs(arena, state, Defs::default()).unwrap();
Ok(Output::Full {
header,

View file

@ -7,9 +7,8 @@ mod test_fmt {
use roc_fmt::def::fmt_defs;
use roc_fmt::module::fmt_module;
use roc_fmt::Buf;
use roc_parse::ast::Module;
use roc_parse::module::{self, module_defs};
use roc_parse::parser::Parser;
use roc_parse::ast::{Defs, Module};
use roc_parse::module::{self, parse_module_defs};
use roc_parse::state::State;
use roc_test_utils::assert_multiline_str_eq;
use roc_test_utils_dir::workspace_root;
@ -39,8 +38,8 @@ mod test_fmt {
) {
fmt_module(buf, module);
match module_defs().parse(arena, state, 0) {
Ok((_, loc_defs, _)) => {
match parse_module_defs(arena, state, Defs::default()) {
Ok(loc_defs) => {
fmt_defs(buf, &loc_defs, 0);
}
Err(error) => panic!(

View file

@ -2,6 +2,7 @@ use bumpalo::Bump;
use roc_fmt::Buf;
use roc_parse::{
ast::{Defs, Module},
module::parse_module_defs,
parser::SyntaxError,
};
use roc_region::all::Loc;
@ -20,16 +21,12 @@ pub struct Ast<'a> {
impl<'a> Ast<'a> {
pub fn parse(arena: &'a Bump, src: &'a str) -> Result<Ast<'a>, SyntaxError<'a>> {
use roc_parse::{
module::{module_defs, parse_header},
parser::Parser,
state::State,
};
use roc_parse::{module::parse_header, state::State};
let (module, state) = parse_header(arena, State::new(src.as_bytes()))
.map_err(|e| SyntaxError::Header(e.problem))?;
let (_, defs, _) = module_defs().parse(arena, state, 0).map_err(|(_, e)| e)?;
let defs = parse_module_defs(arena, state, Defs::default())?;
Ok(Ast {
module,