Move syntax tests to a dedicated crate

* test_fmt moves out of fmt crate
* test_parse _mostly_ moves out of parse crate and into `test_snapshots.rs` (some simple tests remain)
* now there's only two fuzz targets, fuzz_expr and fuzz_module, that cover both parsing and formatting
* added a system to auto-add new snapshot entries for new test files
* took some commented-out tests in `test_parse` and converted them to snapshot tests
* moved test_fmt's verification of formatting consistency into test_snapshots
* fixed a huge derp on my part where the fmt fuzzer in #4758 was completely useless (broken by refactoring just prior to submitting the PR)
* fixed a formatting bug found by fuzzing (bound_variable.expr.roc) - that I missed earlier due to ^^^ that derp
* no longer have roc_test_utils as a dependency in fmt - which was causing problems for the wasm build
This commit is contained in:
Joshua Warner 2022-12-26 12:50:31 -08:00
parent f0b3c3eb08
commit bfeddc470a
No known key found for this signature in database
GPG key ID: 89AD497003F93FDD
701 changed files with 1929 additions and 1516 deletions

View file

@ -1,3 +0,0 @@
target
corpus
artifacts

View file

@ -1,424 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "addr2line"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "ahash"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
dependencies = [
"getrandom",
"once_cell",
"version_check",
]
[[package]]
name = "arbitrary"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db55d72333851e17d572bec876e390cd3b11eb1ef53ae821dd9f3b653d2b4569"
[[package]]
name = "backtrace"
version = "0.3.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]]
name = "bitmaps"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2"
dependencies = [
"typenum",
]
[[package]]
name = "bitvec"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
dependencies = [
"funty",
"radium",
"tap",
"wyz",
]
[[package]]
name = "bumpalo"
version = "3.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
[[package]]
name = "cc"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "doc-comment"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
[[package]]
name = "encode_unicode"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "funty"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
[[package]]
name = "getrandom"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "gimli"
version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
dependencies = [
"ahash",
"bumpalo",
]
[[package]]
name = "heck"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
[[package]]
name = "im"
version = "15.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9"
dependencies = [
"bitmaps",
"rand_core",
"rand_xoshiro",
"sized-chunks",
"typenum",
"version_check",
]
[[package]]
name = "im-rc"
version = "15.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe"
dependencies = [
"bitmaps",
"rand_core",
"rand_xoshiro",
"sized-chunks",
"typenum",
"version_check",
]
[[package]]
name = "libc"
version = "0.2.131"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04c3b4822ccebfa39c02fc03d1534441b22ead323fa0f48bb7ddd8e6ba076a40"
[[package]]
name = "libfuzzer-sys"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee8c42ab62f43795ed77a965ed07994c5584cdc94fd0ebf14b22ac1524077acc"
dependencies = [
"arbitrary",
"cc",
]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "miniz_oxide"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc"
dependencies = [
"adler",
]
[[package]]
name = "object"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
[[package]]
name = "proc-macro2"
version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
[[package]]
name = "radium"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
[[package]]
name = "rand_core"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
[[package]]
name = "rand_xoshiro"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa"
dependencies = [
"rand_core",
]
[[package]]
name = "roc_collections"
version = "0.0.1"
dependencies = [
"bitvec",
"bumpalo",
"fnv",
"hashbrown",
"im",
"im-rc",
"wyhash",
]
[[package]]
name = "roc_error_macros"
version = "0.0.1"
[[package]]
name = "roc_ident"
version = "0.0.1"
[[package]]
name = "roc_module"
version = "0.0.1"
dependencies = [
"bumpalo",
"roc_collections",
"roc_error_macros",
"roc_ident",
"roc_region",
"snafu",
"static_assertions",
]
[[package]]
name = "roc_parse"
version = "0.0.1"
dependencies = [
"bumpalo",
"encode_unicode",
"roc_collections",
"roc_module",
"roc_region",
]
[[package]]
name = "roc_parse-fuzz"
version = "0.0.0"
dependencies = [
"bumpalo",
"libfuzzer-sys",
"roc_parse",
]
[[package]]
name = "roc_region"
version = "0.0.1"
dependencies = [
"static_assertions",
]
[[package]]
name = "rustc-demangle"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
[[package]]
name = "sized-chunks"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e"
dependencies = [
"bitmaps",
"typenum",
]
[[package]]
name = "snafu"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5177903bf45656592d9eb5c0e22f408fc023aae51dbe2088889b71633ba451f2"
dependencies = [
"backtrace",
"doc-comment",
"snafu-derive",
]
[[package]]
name = "snafu-derive"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "410b26ed97440d90ced3e2488c868d56a86e2064f5d7d6f417909b286afe25e5"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "syn"
version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tap"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]]
name = "typenum"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
[[package]]
name = "unicode-ident"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf"
[[package]]
name = "version_check"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wyhash"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf6e163c25e3fac820b4b453185ea2dea3b6a3e0a721d4d23d75bd33734c295"
dependencies = [
"rand_core",
]
[[package]]
name = "wyz"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30b31594f29d27036c383b53b59ed3476874d518f0efb151b27a4c275141390e"
dependencies = [
"tap",
]

View file

@ -1,38 +0,0 @@
[package]
name = "roc_parse-fuzz"
version = "0.0.0"
authors = ["Automatically generated"]
publish = false
edition = "2021"
[package.metadata]
cargo-fuzz = true
[dependencies]
libfuzzer-sys = "0.3"
bumpalo = { version = "3.6.1", features = ["collections"] }
[dependencies.roc_parse]
path = ".."
# Prevent this from interfering with workspaces
[workspace]
members = ["."]
[[bin]]
name = "fuzz_expr"
path = "fuzz_targets/fuzz_expr.rs"
test = false
doc = false
[[bin]]
name = "fuzz_defs"
path = "fuzz_targets/fuzz_defs.rs"
test = false
doc = false
[[bin]]
name = "fuzz_header"
path = "fuzz_targets/fuzz_header.rs"
test = false
doc = false

View file

@ -1,13 +0,0 @@
# fuzz
To setup fuzzing you will need to install cargo-fuzz and run with rust nightly:
```sh
$ cargo install cargo-fuzz
$ cargo +nightly fuzz run -j<cores> <target> -- -dict=dict.txt
```
The different targets can be found by running `cargo fuzz list`.
When a bug is found, it will be reported with commands to run it again and look for a minimized version.
If you are going to file a bug, please minimize the input before filing the bug.

View file

@ -1,40 +0,0 @@
"if"
"then"
"else"
"when"
"as"
"is"
"expect"
"dbg"
"has"
"app"
"platform"
"package"
"provides"
"requires"
"exposes"
"imports"
"effects"
"interface"
"|>"
"=="
"!="
"&&"
"||"
"+"
"*"
"-"
"//"
"/"
"<="
"<"
">="
">"
"^"
"%"
":="
":"
"@"
"->"

View file

@ -1,11 +0,0 @@
#![no_main]
use bumpalo::Bump;
use libfuzzer_sys::fuzz_target;
use roc_parse::test_helpers::parse_defs_with;
fuzz_target!(|data: &[u8]| {
if let Ok(input) = std::str::from_utf8(data) {
let arena = Bump::new();
let _actual = parse_defs_with(&arena, input.trim());
}
});

View file

@ -1,11 +0,0 @@
#![no_main]
use bumpalo::Bump;
use libfuzzer_sys::fuzz_target;
use roc_parse::test_helpers::parse_expr_with;
fuzz_target!(|data: &[u8]| {
if let Ok(input) = std::str::from_utf8(data) {
let arena = Bump::new();
let _actual = parse_expr_with(&arena, input.trim());
}
});

View file

@ -1,11 +0,0 @@
#![no_main]
use bumpalo::Bump;
use libfuzzer_sys::fuzz_target;
use roc_parse::test_helpers::parse_header_with;
fuzz_target!(|data: &[u8]| {
if let Ok(input) = std::str::from_utf8(data) {
let arena = Bump::new();
let _actual = parse_header_with(&arena, input.trim());
}
});

View file

@ -0,0 +1,384 @@
app "generator"
packages {
pf: "https://github.com/roc-lang/basic-cli/releases/download/0.1.1/zAoiC9xtQPHywYk350_b7ust04BmWLW00sjb9ZPtSQk.tar.br",
}
imports [
pf.Stdout,
pf.File,
pf.Path,
pf.Task.{ Task },
]
provides [main] to pf
RenderTree : [
Text Str,
Items (List RenderTree),
Line (List RenderTree),
Indent (List RenderTree),
Import {modu: List Str, name: Str},
]
renderFile : RenderTree -> Str
renderFile = \tree ->
render (Items [
formatImports (findImports tree),
tree
])
findImports : RenderTree -> Set { modu: (List Str), name: Str }
findImports = \tree ->
when tree is
Text _ -> Set.empty
Items list | Indent list | Line list ->
List.walk list Set.empty \acc, item -> Set.union acc (findImports item)
Import import -> Set.single import
formatImports : Set { modu: (List Str), name: Str } -> RenderTree
formatImports = \set ->
if hasDupImports set then
crash "Duplicate imports!"
else
Items (
set
|> Set.toList
# TODO: Sort by module name
|> List.map \{ modu, name } ->
Line [
Text "use ",
Text (Str.joinWith (List.map modu \m -> Str.concat m "::") ""),
Text name,
Text ";",
]
)
hasDupImports : Set { modu: (List Str), name: Str } -> Bool
hasDupImports = \set ->
nameSet =
set
|> Set.toList
|> List.map \{ modu: _, name } -> name
|> Set.fromList
Set.len nameSet != Set.len nameSet
render : RenderTree -> Str
render = \tree ->
Tuple text _ = renderInner tree 0 Bool.true
text
renderGroup : List RenderTree, Nat, Bool -> [Tuple Str Bool]
renderGroup = \list, indent, newlineBefore ->
List.walk list (Tuple "" newlineBefore) \(Tuple text nlb), item ->
Tuple ntext nla = renderInner item indent nlb
(Tuple
(Str.concat text ntext)
nla
)
renderInner : RenderTree, Nat, Bool -> [Tuple Str Bool]
renderInner = \tree, indent, newlineBefore ->
when tree is
Text text ->
result = if newlineBefore then
Str.concat (Str.repeat " " (4*indent)) text
else
text
Tuple result Bool.false
Items list -> renderGroup list indent newlineBefore
Line list ->
Tuple ntext nla = renderGroup list indent Bool.true
res = if newlineBefore then
# Already added the newline, no need!
ntext
else
Str.concat "\n" ntext
res2 = if nla then
res
else
Str.concat res "\n"
(Tuple res2 Bool.true)
Indent list -> renderGroup list (indent + 1) newlineBefore
Import {modu: _, name} ->
Tuple name Bool.false
parserTrait = \t, e ->
genCall (Import {modu: ["crate", "parser"], name: "Parser"}) [Text "'a", t, e]
parseFunction : Str, RenderTree, RenderTree, RenderTree -> RenderTree
parseFunction = \name, ty, err, body ->
Items [
Line [
Text "pub fn \(name)<'a>() -> impl ",
parserTrait ty err,
Text " {",
],
Indent [body, Line [Text ".trace(\"\(name)\")" ] ],
Line [Text "}"],
Line [Text ""],
]
Type : RenderTree
ErrTy : RenderTree
Parser : [
Loc Parser,
Specialize ErrTy Parser,
Record Str (List { name: Str, parser: Parser }),
Builtin RenderTree Type,
# Named ParserName (World -> Parser),
]
errHeader : Str -> ErrTy
errHeader = \name ->
Items [
Import { modu: ["crate", "parser"], name: "EHeader" },
Text "::",
Text name,
]
fnCall : RenderTree, List RenderTree -> RenderTree
fnCall = \fnName, args ->
Items [
fnName,
Text "(",
Items (List.intersperse args (Text ",")),
Text ")",
]
fn : RenderTree -> (List RenderTree -> RenderTree)
fn = \fnName -> \args -> fnCall fnName args
genCall : RenderTree, List RenderTree -> RenderTree
genCall = \genName, args ->
Items [
genName,
Text "<",
Items (List.intersperse args (Text ", ")),
Text ">",
]
gen : RenderTree -> (List RenderTree -> RenderTree)
gen = \genName -> \args -> genCall genName args
ref : RenderTree -> RenderTree
ref = \name -> Items [Text "&'a ", name]
slice : RenderTree -> RenderTree
slice = \name -> Items [Text "[", name, Text "]"]
refSlice : RenderTree -> RenderTree
refSlice = \name -> ref (slice name)
commentOrNewline = genCall (Import {modu: ["crate", "ast"], name: "CommentOrNewline"}) [ Text "'a" ]
exposedName = genCall (Import {modu: ["crate", "header"], name: "ExposedName"}) [ Text "'a" ]
importsEntry = genCall (Import {modu: ["crate", "header"], name: "ImportsEntry"}) [ Text "'a" ]
uppercaseIdent = genCall (Import {modu: ["crate", "ident"], name: "UppercaseIdent"}) [ Text "'a" ]
moduleName = genCall (Import {modu: ["crate", "header"], name: "ModuleName"}) [ Text "'a" ]
space0E = fn (Import { modu: ["crate", "blankspace"], name: "space0_e" })
keyword = \keywordName ->
Import { modu: ["crate", "header"], name: keywordName }
spaces = \errorName ->
Builtin (space0E [errorName]) (refSlice commentOrNewline)
loc = gen (Import {modu: ["roc_region", "all"], name: "Loc"})
keywordItem = \kw, ty ->
genCall (Import {modu: ["crate", "header"], name: "KeywordItem"}) [ Text "'a", kw, ty ]
collection = \ty ->
genCall (Import {modu: ["crate", "ast"], name: "Collection"}) [ Text "'a", ty ]
spaced = \ty ->
genCall (Import {modu: ["crate", "ast"], name: "Spaced"}) [ Text "'a", ty ]
moduleNameHelp = \err ->
Builtin (fnCall (Import {modu: ["crate", "module"], name: "module_name_help" }) [ err ]) moduleName
exposesValues =
Builtin (fnCall (Import {modu: ["crate", "module"], name: "exposes_values"}) []) (keywordItem (keyword "ExposesKeyword") (collection (loc [spaced exposedName])))
imports =
Builtin (fnCall (Import {modu: ["crate", "module"], name: "imports"}) []) (keywordItem (keyword "ImportsKeyword") (collection (loc [spaced importsEntry])))
generates =
Builtin (fnCall (Import {modu: ["crate", "module"], name: "generates"}) []) (keywordItem (keyword "GeneratesKeyword") uppercaseIdent)
generatesWith =
Builtin (fnCall (Import {modu: ["crate", "module"], name: "generates_with"}) []) (keywordItem (keyword "WithKeyword") (collection (loc [spaced exposedName])))
interfaceHeader = Record "InterfaceHeader" [
{name: "before_name", parser: spaces (errHeader "IndentStart")},
{name: "name", parser: Loc (moduleNameHelp (errHeader "ModuleName"))},
{name: "exposes", parser: Specialize (errHeader "Exposes") exposesValues },
{name: "imports", parser: Specialize (errHeader "Imports") imports },
]
hostedHeader = Record "HostedHeader" [
{name: "before_name", parser: spaces (errHeader "IndentStart")},
{name: "name", parser: Loc (moduleNameHelp (errHeader "ModuleName"))},
{name: "exposes", parser: Specialize (errHeader "Exposes") exposesValues},
{name: "imports", parser: Specialize (errHeader "Imports") imports},
{name: "generates", parser: Specialize (errHeader "Generates") generates},
{name: "generates_with", parser: Specialize (errHeader "GeneratesWith") generatesWith},
]
printCombinatorParserFunction = \parser ->
parseFunction (lowerName (resolveName parser)) (resolveType parser) (Text "EHeader<'a>") (printCombinatorParser parser)
resolveName : Parser -> Str
resolveName = \parser ->
when parser is
Loc _p -> crash "Unnamed parser!"
Specialize _err _p -> crash "Unnamed parser!"
Builtin _name _ty -> crash "Unnamed parser!"
Record name _fields -> name
underscoreScalar = 95
aLowerScalar = 97
aUpperScalar = 65
zUpperScalar = 90
# map from a lower_case_name to a UpperCaseName
upperName : Str -> Str
upperName = \name ->
result = Str.walkScalars name {text: "", needUpper: Bool.true} \{text, needUpper}, c ->
if c == underscoreScalar then
{text, needUpper: Bool.true}
else
newText =
if needUpper then
Str.appendScalar text (c - aLowerScalar + aUpperScalar) |> orCrash
else
Str.appendScalar text c |> orCrash
{text: newText, needUpper: Bool.false}
result.text
expect (upperName "hello_world") == "HelloWorld"
orCrash : Result a e -> a
orCrash = \result ->
when result is
Ok a -> a
Err _e -> crash "orCrash"
lowerName : Str -> Str
lowerName = \name ->
result = Str.walkScalars name {text: "", needUnder: Bool.false} \{text, needUnder}, c ->
newText =
if c >= aUpperScalar && c <= zUpperScalar then
if needUnder then
text
|> Str.appendScalar underscoreScalar
|> orCrash
|> Str.appendScalar (c - aUpperScalar + aLowerScalar)
|> orCrash
else
text
|> Str.appendScalar (c - aUpperScalar + aLowerScalar)
|> orCrash
else
Str.appendScalar text c |> orCrash
{text: newText, needUnder: Bool.true}
result.text
expect
theResult = (lowerName "HelloWorld")
theResult == "hello_world"
resolveType : Parser -> RenderTree
resolveType = \parser ->
when parser is
Loc p -> loc [resolveType p]
Specialize _err p -> resolveType p
Record name _fields -> Items [ Import {modu: ["crate", "generated_ast"], name}, Text "<'a>"]
Builtin _name ty -> ty
printCombinatorParser : Parser -> RenderTree
printCombinatorParser = \parser ->
when parser is
Loc p ->
printed = printCombinatorParser p
value : RenderTree
value = Items [ (Text "loc!("), printed, (Text ")") ]
value
Specialize err p ->
printed = printCombinatorParser p
Items [
Import {modu: ["crate", "parser"], name: "specialize"},
Text "(",
err,
(Text ", "),
printed,
(Text ")"),
]
Record name fields ->
Items [
Text "record!(\(name) {",
(Indent
(fields
|> List.map \f ->
Line [Text "\(f.name): ", printCombinatorParser f.parser, Text ","]
)
),
Text "})"
]
Builtin name _ty -> name
printAst : Parser -> RenderTree
printAst = \parser ->
when parser is
Record name fields ->
Items [
Line [ Text "#[derive(Clone, Debug, PartialEq)]" ],
Line [ Text "pub struct \(name)<'a> {" ],
(Indent (
fields
|> List.map \f ->
Line [Text "pub \(f.name): ", resolveType f.parser, Text ","]
)),
Line [Text "}"],
Line [Text ""],
]
_ -> crash "Not implemented"
expect (render (Text "foo")) == "foo"
expect (render (Line [Text "foo"])) == "foo\n"
expect (render (Indent [Text "foo"])) == " foo"
expect (render (Line [Indent [Text "foo"]])) == " foo\n"
expect
res = (render (Items [Text "{", Indent [Line [Text "foo"]], Text "}"]))
res ==
"""
{
foo
}
"""
allSyntaxItems = [interfaceHeader, hostedHeader]
printedAstItems = Items (allSyntaxItems |> List.map printAst)
printedParserItems = Items (allSyntaxItems |> List.map printCombinatorParserFunction)
# main : Task {} []*
main =
task =
_ <- File.writeUtf8 (Path.fromStr "generated_ast.rs") (renderFile printedAstItems) |> Task.await
File.writeUtf8 (Path.fromStr "generated_parser.rs") (renderFile printedParserItems)
Task.attempt task \result ->
when result is
Ok _ -> Stdout.line "Success!"
Err _e -> Stdout.line "Failed to write file"

View file

@ -47,7 +47,7 @@ pub fn parse_header<'a>(
}
}
fn header<'a>() -> impl Parser<'a, Module<'a>, EHeader<'a>> {
pub fn header<'a>() -> impl Parser<'a, Module<'a>, EHeader<'a>> {
use crate::parser::keyword_e;
record!(Module {

View file

@ -1 +0,0 @@
Expr(Ability(DemandColon(@15), @7), @0)

View file

@ -1,4 +0,0 @@
MEq has
eq b c : a, a -> U64 | a has MEq
1

View file

@ -1 +0,0 @@
Expr(Ability(DemandAlignment(4, @49), @40), @0)

View file

@ -1,5 +0,0 @@
MEq has
eq : a, a -> U64 | a has MEq
neq : a, a -> U64 | a has MEq
1

View file

@ -1 +0,0 @@
Expr(Ability(DemandAlignment(-1, @8), @7), @0)

View file

@ -1,4 +0,0 @@
MEq has
eq : a, a -> U64 | a has MEq
1

View file

@ -1 +0,0 @@
Expr(Ability(DemandName(@12), @7), @0)

View file

@ -1 +0,0 @@
Expr(InParens(End(@3), @0), @0)

View file

@ -1 +0,0 @@
Expr(Space(HasTab, @17), @0)

View file

@ -1,2 +0,0 @@
# comment with a
4

View file

@ -1 +0,0 @@
Expr(DefMissingFinalExpr2(Start(@11), @11), @0)

View file

@ -1 +0,0 @@
Expr(BadOperator("++", @14), @0)

View file

@ -1,2 +0,0 @@
main =
[] ++ []

View file

@ -1 +0,0 @@
Expr(ElmStyleFunction(@2-5, @6), @0)

View file

@ -1 +0,0 @@
Expr(When(Pattern(Start(@28), @28), @0), @0)

View file

@ -1,6 +0,0 @@
when Just 4 is
Just 4 | ->
4
_ ->
2

View file

@ -1 +0,0 @@
Expr(Type(TInlineAlias(ArgumentNotLowercase(@50), @51), @4), @0)

View file

@ -1 +0,0 @@
f : List elem -> [Nil, Cons elem a] as LinkedList U

View file

@ -1 +0,0 @@
Expr(Type(TInlineAlias(NotAnAlias(@39), @40), @4), @0)

View file

@ -1 +0,0 @@
f : List elem -> [Nil, Cons elem a] as a

View file

@ -1 +0,0 @@
Expr(Type(TInlineAlias(Qualified(@39), @58), @4), @0)

View file

@ -1 +0,0 @@
f : List elem -> [Nil, Cons elem a] as Module.LinkedList a

View file

@ -1 +0,0 @@
Expr(Pattern(NotAPattern(@3), @3), @0)

View file

@ -1 +0,0 @@
Expr(When(IfGuard(Start(@28), @27), @0), @0)

View file

@ -1,6 +0,0 @@
when Just 4 is
Just if ->
4
_ ->
2

View file

@ -1 +0,0 @@
Expr(If(Else(@16), @0), @0)

View file

@ -1 +0,0 @@
if 5 == 5 then 2

View file

@ -1 +0,0 @@
Expr(If(IndentThenToken(@17), @8), @0)

View file

@ -1,5 +0,0 @@
x =
if 5 == 5
then 2 else 3
x

View file

@ -1 +0,0 @@
SourceError { problem: Imports(ListEnd(@87), @65), bytes: [97, 112, 112, 32, 34, 116, 101, 115, 116, 45, 109, 105, 115, 115, 105, 110, 103, 45, 99, 111, 109, 109, 97, 34, 10, 32, 32, 32, 32, 112, 97, 99, 107, 97, 103, 101, 115, 32, 123, 32, 112, 102, 58, 32, 34, 112, 108, 97, 116, 102, 111, 114, 109, 47, 109, 97, 105, 110, 46, 114, 111, 99, 34, 32, 125, 10, 32, 32, 32, 32, 105, 109, 112, 111, 114, 116, 115, 32, 91, 112, 102, 46, 84, 97, 115, 107, 32, 66, 97, 115, 101, 54, 52, 93, 10, 32, 32, 32, 32, 112, 114, 111, 118, 105, 100, 101, 115, 32, 91, 109, 97, 105, 110, 44, 32, 64, 70, 111, 111, 93, 32, 116, 111, 32, 112, 102] }

View file

@ -1,4 +0,0 @@
app "test-missing-comma"
packages { pf: "platform/main.roc" }
imports [pf.Task Base64]
provides [main, @Foo] to pf

View file

@ -1 +0,0 @@
Expr(BadOperator(":", @21), @0)

View file

@ -1,4 +0,0 @@
main =
(\x -> x) : I64
3

View file

@ -1 +0,0 @@
Expr(BadOperator("**", @13), @0)

View file

@ -1 +0,0 @@
Expr(Closure(Arg(@3), @0), @0)

View file

@ -1 +0,0 @@
Expr(Closure(Arg(@1), @0), @0)

View file

@ -1 +0,0 @@
Expr(Closure(Arg(@1), @0), @0)

View file

@ -1 +0,0 @@
Expr(Closure(IndentBody(@5), @0), @0)

View file

@ -1 +0,0 @@
Expr(List(End(@7), @0), @0)

View file

@ -1 +0,0 @@
Expr(When(Pattern(List(End(@22), @15), @15), @0), @0)

View file

@ -1,2 +0,0 @@
when [] is
[1, 2, -> ""

View file

@ -1 +0,0 @@
Expr(When(Pattern(List(End(@22), @15), @15), @0), @0)

View file

@ -1,3 +0,0 @@
when [] is
[1, 2,
3] -> ""

View file

@ -1 +0,0 @@
Expr(When(Pattern(List(Rest(@16), @15), @15), @0), @0)

View file

@ -1 +0,0 @@
Expr(List(End(@6), @0), @0)

View file

@ -1 +0,0 @@
Expr(Str(EndlessMulti(@3), @0), @0)

View file

@ -1 +0,0 @@
"""there is no end

View file

@ -1 +0,0 @@
Expr(When(Arrow(@24), @0), @0)

View file

@ -1,6 +0,0 @@
when Just 4 is
Just when ->
4
_ ->
2

View file

@ -1 +0,0 @@
Expr(Closure(Pattern(PInParens(End(@4), @1), @1), @0), @0)

View file

@ -1 +0,0 @@
Expr(Closure(Pattern(PInParens(End(@5), @1), @1), @0), @0)

View file

@ -1 +0,0 @@
Expr(Closure(Pattern(PInParens(End(@2), @1), @1), @0), @0)

View file

@ -1 +0,0 @@
Expr(Closure(Pattern(PInParens(End(@4), @1), @1), @0), @0)

View file

@ -1 +0,0 @@
Expr(Type(TRecord(End(@13), @4), @4), @0)

View file

@ -1 +0,0 @@
Expr(Type(TRecord(Field(@6), @4), @4), @0)

View file

@ -1 +0,0 @@
Expr(Type(TRecord(End(@11), @4), @4), @0)

View file

@ -1 +0,0 @@
Expr(Type(TRecord(End(@5), @4), @4), @0)

View file

@ -1 +0,0 @@
Expr(Type(TRecord(IndentEnd(@5), @4), @4), @0)

View file

@ -1 +0,0 @@
Expr(Type(TRecord(Space(HasTab, @10), @4), @4), @0)

View file

@ -1 +0,0 @@
Expr(Str(EndlessSingle(@1), @0), @0)

View file

@ -1 +0,0 @@
"there is no end

View file

@ -1 +0,0 @@
SourceError { problem: Space(HasMisplacedCarriageReturn, @1), bytes: [35, 13, 12, 9, 65] }

View file

@ -1 +0,0 @@
Expr(Type(TTagUnion(End(@9), @4), @4), @0)

Some files were not shown because too many files have changed in this diff Show more