mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
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:
parent
7a53484479
commit
7ebfc6d06d
18 changed files with 235 additions and 121 deletions
|
@ -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 })
|
||||
}
|
||||
|
|
|
@ -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 }]
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -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 }
|
||||
|
||||
|
|
|
@ -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),
|
||||
));
|
||||
|
|
|
@ -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>,
|
||||
}
|
||||
|
|
|
@ -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
|
||||
"#
|
||||
"
|
||||
),
|
||||
),
|
||||
(
|
||||
|
|
|
@ -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());
|
||||
})
|
||||
|
|
|
@ -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>),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>],
|
||||
|
|
|
@ -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>(
|
||||
|
|
|
@ -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>(
|
||||
|
|
|
@ -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!");
|
||||
}
|
||||
|
|
|
@ -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 {}
|
||||
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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!(
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue