diff --git a/Makefile b/Makefile index cd440061..f63f6aec 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,8 @@ FORMAT_DIRS = \ cli \ example-library-usages \ src \ - tests + tests \ + parser-tests \ .PHONY: run run: build @@ -35,6 +36,15 @@ test: build npx elm-test npx ava +.PHONY: regenerate +regenerate: + cd parser-tests \ + && npx elm make Update.elm --output elm.js \ + && node --unhandled-rejections=strict update \ + ; CODE=$$? \ + ; elm-format ../tests/ParserLexerTestCases.elm --yes \ + ; exit $$CODE + .PHONY: format format: npx elm-format $(FORMAT_DIRS) --yes diff --git a/integration-tests/cli/non-zero-exit-error/test.test.js.md b/integration-tests/cli/non-zero-exit-error/test.test.js.md index b52b158a..dea88a80 100644 --- a/integration-tests/cli/non-zero-exit-error/test.test.js.md +++ b/integration-tests/cli/non-zero-exit-error/test.test.js.md @@ -23,5 +23,5 @@ Generated by [AVA](https://avajs.dev). `---------------------------␊ -- STARTING THE COMPILER --␊ ---------------------------␊ - Main.main: Value { expression = Plus (Int 1) (Var { name = "y", qualifiedness = PossiblyQualified Nothing }), typeAnnotation = Nothing }␊ + Main.main: Value { expression = Operator Add (Int 1) (Var { name = "y", qualifiedness = PossiblyQualified Nothing }), typeAnnotation = Nothing }␊ ` diff --git a/integration-tests/cli/non-zero-exit-error/test.test.js.snap b/integration-tests/cli/non-zero-exit-error/test.test.js.snap index be2cc454..c1a8e075 100644 Binary files a/integration-tests/cli/non-zero-exit-error/test.test.js.snap and b/integration-tests/cli/non-zero-exit-error/test.test.js.snap differ diff --git a/integration-tests/cli/two-source/test.test.js.md b/integration-tests/cli/two-source/test.test.js.md index 8cde26c6..ed8074cd 100644 --- a/integration-tests/cli/two-source/test.test.js.md +++ b/integration-tests/cli/two-source/test.test.js.md @@ -18,7 +18,7 @@ Generated by [AVA](https://avajs.dev). `---------------------------␊ -- STARTING THE COMPILER --␊ ---------------------------␊ - Main.main: Value { expression = Plus (Int 1) (Var { name = "x", qualifiedness = PossiblyQualified (Just "Lib") }), typeAnnotation = Nothing }␊ + Main.main: Value { expression = Operator Add (Int 1) (Var { name = "x", qualifiedness = PossiblyQualified (Just "Lib") }), typeAnnotation = Nothing }␊ Lib.x: Value { expression = Int 4, typeAnnotation = Nothing }␊ Compilation finished, writing output to `out.js`.␊ ---------------------------␊ diff --git a/integration-tests/cli/two-source/test.test.js.snap b/integration-tests/cli/two-source/test.test.js.snap index 58d3ec87..6fa6a7d0 100644 Binary files a/integration-tests/cli/two-source/test.test.js.snap and b/integration-tests/cli/two-source/test.test.js.snap differ diff --git a/integration-tests/desugar/import/test.test.js.md b/integration-tests/desugar/import/test.test.js.md index 1f2e6f71..b9efdaab 100644 --- a/integration-tests/desugar/import/test.test.js.md +++ b/integration-tests/desugar/import/test.test.js.md @@ -18,7 +18,7 @@ Generated by [AVA](https://avajs.dev). `---------------------------␊ -- STARTING THE COMPILER --␊ ---------------------------␊ - Main.main: Value { expression = Plus (Int 1) (Var { name = "x", qualifiedness = PossiblyQualified (Just "Lib") }), typeAnnotation = Nothing }␊ + Main.main: Value { expression = Operator Add (Int 1) (Var { name = "x", qualifiedness = PossiblyQualified (Just "Lib") }), typeAnnotation = Nothing }␊ Lib.x: Value { expression = Int 4, typeAnnotation = Nothing }␊ Compilation finished, writing output to `out.js`.␊ ---------------------------␊ diff --git a/integration-tests/desugar/import/test.test.js.snap b/integration-tests/desugar/import/test.test.js.snap index 58d3ec87..6fa6a7d0 100644 Binary files a/integration-tests/desugar/import/test.test.js.snap and b/integration-tests/desugar/import/test.test.js.snap differ diff --git a/integration-tests/parser/add-5/test.test.js.md b/integration-tests/parser/add-5/test.test.js.md index f6b3a803..a5a61343 100644 --- a/integration-tests/parser/add-5/test.test.js.md +++ b/integration-tests/parser/add-5/test.test.js.md @@ -18,8 +18,8 @@ Generated by [AVA](https://avajs.dev). `---------------------------␊ -- STARTING THE COMPILER --␊ ---------------------------␊ - Main.main: Value { expression = Plus (Int 7) (Int 6), typeAnnotation = Nothing }␊ - Main.f: Value { expression = Lambda { arguments = ["x"], body = Plus (Int 5) (Argument "x") }, typeAnnotation = Nothing }␊ + Main.main: Value { expression = Operator Add (Int 7) (Int 6), typeAnnotation = Nothing }␊ + Main.f: Value { expression = Lambda { arguments = ["x"], body = Operator Add (Int 5) (Argument "x") }, typeAnnotation = Nothing }␊ Compilation finished, writing output to `out.js`.␊ ---------------------------␊ -- WRITING TO FS ----------␊ diff --git a/integration-tests/parser/add-5/test.test.js.snap b/integration-tests/parser/add-5/test.test.js.snap index cb3abe63..f8dd1389 100644 Binary files a/integration-tests/parser/add-5/test.test.js.snap and b/integration-tests/parser/add-5/test.test.js.snap differ diff --git a/integration-tests/parser/if-then-else/test.test.js.md b/integration-tests/parser/if-then-else/test.test.js.md index 19114c25..1fe4e591 100644 --- a/integration-tests/parser/if-then-else/test.test.js.md +++ b/integration-tests/parser/if-then-else/test.test.js.md @@ -18,7 +18,7 @@ Generated by [AVA](https://avajs.dev). `---------------------------␊ -- STARTING THE COMPILER --␊ ---------------------------␊ - Main.main: Value { expression = Plus (Call { argument = Bool True, fn = Var { name = "f", qualifiedness = PossiblyQualified Nothing } }) (Call { argument = Bool False, fn = Var { name = "f", qualifiedness = PossiblyQualified Nothing } }), typeAnnotation = Nothing }␊ + Main.main: Value { expression = Operator Add (Call { argument = Bool True, fn = Var { name = "f", qualifiedness = PossiblyQualified Nothing } }) (Call { argument = Bool False, fn = Var { name = "f", qualifiedness = PossiblyQualified Nothing } }), typeAnnotation = Nothing }␊ Main.f: Value { expression = Lambda { arguments = ["x"], body = If { else_ = Int 2, test = Argument "x", then_ = Int 18 } }, typeAnnotation = Nothing }␊ Compilation finished, writing output to `out.js`.␊ ---------------------------␊ diff --git a/integration-tests/parser/if-then-else/test.test.js.snap b/integration-tests/parser/if-then-else/test.test.js.snap index 139064a9..9d262823 100644 Binary files a/integration-tests/parser/if-then-else/test.test.js.snap and b/integration-tests/parser/if-then-else/test.test.js.snap differ diff --git a/integration-tests/parser/indentation/expr-with-indentation-within-let/test.test.js.md b/integration-tests/parser/indentation/expr-with-indentation-within-let/test.test.js.md index 0654162f..f6a3f3d6 100644 --- a/integration-tests/parser/indentation/expr-with-indentation-within-let/test.test.js.md +++ b/integration-tests/parser/indentation/expr-with-indentation-within-let/test.test.js.md @@ -18,7 +18,7 @@ Generated by [AVA](https://avajs.dev). `---------------------------␊ -- STARTING THE COMPILER --␊ ---------------------------␊ - Main.main: Value { expression = Let { bindings = [{ body = Plus (Int 1) (Int 2), name = "x" }], body = Argument "x" }, typeAnnotation = Nothing }␊ + Main.main: Value { expression = Let { bindings = [{ body = Operator Add (Int 1) (Int 2), name = "x" }], body = Argument "x" }, typeAnnotation = Nothing }␊ Compilation finished, writing output to `out.js`.␊ ---------------------------␊ -- WRITING TO FS ----------␊ diff --git a/integration-tests/parser/indentation/expr-with-indentation-within-let/test.test.js.snap b/integration-tests/parser/indentation/expr-with-indentation-within-let/test.test.js.snap index 4be1a40a..8a6f2d89 100644 Binary files a/integration-tests/parser/indentation/expr-with-indentation-within-let/test.test.js.snap and b/integration-tests/parser/indentation/expr-with-indentation-within-let/test.test.js.snap differ diff --git a/integration-tests/typecheck/let-body-visibility/test.test.js.md b/integration-tests/typecheck/let-body-visibility/test.test.js.md index 646ee93a..e7f460c1 100644 --- a/integration-tests/typecheck/let-body-visibility/test.test.js.md +++ b/integration-tests/typecheck/let-body-visibility/test.test.js.md @@ -18,7 +18,7 @@ Generated by [AVA](https://avajs.dev). `---------------------------␊ -- STARTING THE COMPILER --␊ ---------------------------␊ - Main.main: Value { expression = Let { bindings = [{ body = Int 2, name = "x" }], body = Plus (Int 1) (Argument "x") }, typeAnnotation = Nothing }␊ + Main.main: Value { expression = Let { bindings = [{ body = Int 2, name = "x" }], body = Operator Add (Int 1) (Argument "x") }, typeAnnotation = Nothing }␊ Compilation finished, writing output to `out.js`.␊ ---------------------------␊ -- WRITING TO FS ----------␊ diff --git a/integration-tests/typecheck/let-body-visibility/test.test.js.snap b/integration-tests/typecheck/let-body-visibility/test.test.js.snap index fa70cd0c..4b7421c6 100644 Binary files a/integration-tests/typecheck/let-body-visibility/test.test.js.snap and b/integration-tests/typecheck/let-body-visibility/test.test.js.snap differ diff --git a/parser-tests/.gitignore b/parser-tests/.gitignore new file mode 100644 index 00000000..1942e6d3 --- /dev/null +++ b/parser-tests/.gitignore @@ -0,0 +1 @@ +/elm.js diff --git a/parser-tests/Live.elm b/parser-tests/Live.elm new file mode 100644 index 00000000..32aca6be --- /dev/null +++ b/parser-tests/Live.elm @@ -0,0 +1,159 @@ +module Live exposing (main) + +import Browser +import Elm.Data.Located as Located +import Html exposing (Html) +import Html.Attributes as Attributes +import Html.Events as Events +import Parser.Advanced as P +import Stage.Parse.Contextualize as Contextualize +import Stage.Parse.Lexer as Lexer +import Stage.Parse.Pretty as Pretty + + +{-| We're essentially a Node.JS app (until we get self-hosting :P ). +So, `Platform.worker` is the only option for us. +-} +main : Program () String Msg +main = + Browser.element + { init = init + , update = update + , subscriptions = subscriptions + , view = view + } + + +{-| `Compiling` is the state we'll be most of the time. The other two are +mostly useless; they do effectively stop `subscriptions` and `update` though. +-} +type alias Model = + String + + +type Msg + = NewString String + + +subscriptions : Model -> Sub Msg +subscriptions _ = + Sub.none + + +init : () -> ( Model, Cmd never ) +init () = + ( """type alias Model = { h: (""", Cmd.none ) + + +view : Model -> Html Msg +view model = + let + source = + model + + lexed = + P.run Lexer.parser source + in + Html.div + [ Attributes.style "display" "flex" + , Attributes.style "flex-direction" "row" + ] + [ Html.div + [] + [ Html.textarea + [ Events.onInput <| NewString + , Attributes.value source + , Attributes.rows 20 + , Attributes.cols 80 + ] + [] + , Html.div + [ Attributes.style "font-family" "monospace" ] + -- [ Attributes.style "w" ] + (case lexed of + Ok lexItems -> + lexItems + |> List.map + (\item -> + let + { start, end } = + Located.getRegion item + in + Html.div + [ Attributes.style "white-space" "pre-wrap" ] + [ Html.text + ("(" + ++ String.padLeft 3 '0' (String.fromInt start.row) + ++ ", " + ++ String.padLeft 3 '0' (String.fromInt start.col) + ++ ") - (" + ++ String.padLeft 3 '0' (String.fromInt end.row) + ++ ", " + ++ String.padLeft 3 '0' (String.fromInt end.col) + ++ "): \"" + ++ (item |> Located.unwrap |> Lexer.toString |> String.replace " " "·") + ++ "\" " + ++ (item |> Located.unwrap |> Debug.toString) + ) + ] + ) + + Err e -> + [ Html.text (Debug.toString e) ] + ) + ] + , Html.div + [ Attributes.style "font-family" "monospace" ] + -- [ Attributes.style "w" ] + (case lexed of + Ok lexItems -> + let + contextualized = + Contextualize.run lexItems + in + [ Html.div + [ Attributes.style "white-space" "pre-wrap" ] + [ Html.div + [] + [ Html.text + (Debug.toString (Debug.log "parsed" <| contextualized)) + ] + , Html.div + [] + [ Html.text + (Pretty.printWithIndentationOf 0 + (Pretty.listWith + (\rBlock -> + case rBlock of + Ok block -> + Pretty.Many + [ Pretty.Atom "Ok" + , Pretty.block block + ] + + Err e -> + Pretty.Many + [ Pretty.Atom "Err" + , Pretty.Many + [ Pretty.pair "state" (Pretty.state e.state) + ] + ] + ) + contextualized + ) + ) + ] + ] + ] + + Err e -> + [] + ) + ] + + +update : Msg -> Model -> ( Model, Cmd Msg ) +update msg model = + case msg of + NewString string -> + ( string, Cmd.none ) diff --git a/parser-tests/Update.elm b/parser-tests/Update.elm new file mode 100644 index 00000000..91979491 --- /dev/null +++ b/parser-tests/Update.elm @@ -0,0 +1,171 @@ +port module Update exposing (main) + +import Elm.Data.Located as Located exposing (Located) +import Live +import Parser.Advanced as P +import Platform +import Stage.Parse.Contextualize as Contextualize +import Stage.Parse.Lexer as Lexer +import Stage.Parse.Pretty as Pretty + + +port output : String -> Cmd never + + +main : Program Flags Model Msg +main = + Platform.worker + { init = init + , update = update + , subscriptions = subscriptions + } + + +type alias Model = + () + + +type alias Msg = + () + + +type alias Flags = + List + { name : String + , source : String + } + + +subscriptions : Model -> Sub Msg +subscriptions _ = + Sub.none + + +init : Flags -> ( Model, Cmd never ) +init snippets = + let + rlexed : List (Result (List (P.DeadEnd Never Lexer.LexProblem)) (List (Located Lexer.LexItem))) + rlexed = + snippets + |> List.map (.source >> P.run Lexer.parser) + + mrcontextualized : List (Maybe (List Contextualize.RunResult)) + mrcontextualized = + rlexed + |> List.map + (Result.toMaybe >> Maybe.map Contextualize.run) + in + ( () + , output + (""" [ """ + ++ (List.map3 + (\{ name, source } lexed contextualized -> + "{ name = \"" + ++ name + ++ """" + , source = \"\"\"""" + ++ source + ++ """\"\"\" + , pretty = \"\"\" + """ + ++ (case contextualized of + Nothing -> + "Could not lex (a bug)." + + Just c -> + Pretty.printWithIndentationOf 4 + (Pretty.listWith + (\rBlock -> + case rBlock of + Ok block -> + Pretty.Many + [ Pretty.Atom "Ok" + , Pretty.block block + ] + + Err e -> + Pretty.Many + [ Pretty.Atom "Err" + , Pretty.Atom "todo" + ] + ) + c + ) + ) + ++ """ +\"\"\" + , contextualized =""" + ++ (Debug.toString contextualized + |> preFormatElmCode + |> resolveCustomTypeConstructors + ) + ++ """ + , lexed = """ + ++ (Debug.toString lexed + |> preFormatElmCode + ) + ++ """ + }""" + ) + snippets + rlexed + mrcontextualized + |> String.join """ + , """ + ) + ++ """ + ] + """ + ) + ) + + +update : Msg -> Model -> ( Model, Cmd Msg ) +update () model = + ( model, Cmd.none ) + + +preFormatElmCode : String -> String +preFormatElmCode = + {- String.replace "}" """ + }""" + >> + -} + String.replace "]" """ + ]""" + >> String.replace """[ + ]""" "[]" + >> String.replace """Err (""" """Err ( + """ + >> String.replace """Err {""" """Err { + """ + >> String.replace """UserDefinedType {""" """UserDefinedType { + """ + >> String.replace """BlockValueDeclaration_Completish {""" """BlockValueDeclaration_Completish { + """ + + +{-| Always run after preformatting. +-} +resolveCustomTypeConstructors : String -> String +resolveCustomTypeConstructors = + String.split "\n" + >> List.map + (\line -> + if + String.contains "valueExpr__" line + || String.contains "ExpressionNestingParent_Operator" line + || String.contains "ExpressionNestingLeaf_Operator" line + then + line + |> String.replace "Int" "Frontend.Int" + |> String.replace "Float" "Frontend.Float" + |> String.replace "Unit" "Frontend.Unit" + |> String.replace "Operator" "Frontend.Operator" + |> String.replace "ExpressionNestingLeaf_Frontend.Operator" "ExpressionNestingLeaf_Operator" + |> String.replace "ExpressionNestingParent_Frontend.Operator" "ExpressionNestingParent_Operator" + + else + line + ) + >> String.join "\n" diff --git a/parser-tests/elm.json b/parser-tests/elm.json new file mode 100644 index 00000000..0dc746e1 --- /dev/null +++ b/parser-tests/elm.json @@ -0,0 +1,47 @@ +{ + "type": "application", + "source-directories": [ + ".", + "../src" + ], + "elm-version": "0.19.1", + "dependencies": { + "direct": { + "Janiczek/transform": "1.1.0", + "dmy/elm-pratt-parser": "2.0.0", + "elm/browser": "1.0.2", + "elm/core": "1.0.5", + "elm/html": "1.0.0", + "elm/json": "1.1.3", + "elm/parser": "1.1.0", + "elm/project-metadata-utils": "1.0.1", + "elm-community/dict-extra": "2.4.0", + "elm-community/graph": "6.0.0", + "elm-community/maybe-extra": "5.2.0", + "elm-community/result-extra": "2.4.0", + "elm-community/string-extra": "4.0.1", + "erlandsona/assoc-set": "1.1.0", + "pzp1997/assoc-list": "1.0.0", + "rtfeldman/elm-hex": "1.0.0", + "turboMaCk/non-empty-list-alias": "1.1.0" + }, + "indirect": { + "avh4/elm-fifo": "1.0.4", + "elm/regex": "1.0.0", + "elm/time": "1.0.0", + "elm/url": "1.0.0", + "elm/virtual-dom": "1.0.2", + "elm-community/intdict": "3.0.0" + } + }, + "test-dependencies": { + "direct": { + "elm-community/random-extra": "3.1.0", + "elm-explorations/test": "1.2.2" + }, + "indirect": { + "elm/random": "1.0.0", + "owanturist/elm-union-find": "1.0.0" + } + } +} diff --git a/parser-tests/snippets/should-not-parse/dots b/parser-tests/snippets/should-not-parse/dots new file mode 100644 index 00000000..a7150e54 --- /dev/null +++ b/parser-tests/snippets/should-not-parse/dots @@ -0,0 +1,29 @@ +Foo. + +Foo.Bar + +Foo.Bar.baz + +Boor.Bing. + +Bor. Big. + +.sf + +sfsdf .sdfsd + +asfasf.sdgsghj + +(shdf).helloLiteral + +(sjhsf) .helloFunction + +sfhsdf(.helloFunction) + +case.hi + +Hi.case + +case .hi + +Hi. case \ No newline at end of file diff --git a/parser-tests/snippets/should-not-parse/type-alias-function-nested-missing-return b/parser-tests/snippets/should-not-parse/type-alias-function-nested-missing-return new file mode 100644 index 00000000..33c0ccb0 --- /dev/null +++ b/parser-tests/snippets/should-not-parse/type-alias-function-nested-missing-return @@ -0,0 +1,7 @@ +type alias Function = (() -> ) + +type alias Function2 = { a: () -> } + +type alias Function3 = (() -> , ()) + +type alias Function3 = (Int, () ->, ()) diff --git a/parser-tests/snippets/should-not-parse/type-alias-invalid-multiple-brackets b/parser-tests/snippets/should-not-parse/type-alias-invalid-multiple-brackets new file mode 100644 index 00000000..a296281f --- /dev/null +++ b/parser-tests/snippets/should-not-parse/type-alias-invalid-multiple-brackets @@ -0,0 +1 @@ +type alias Hi = (Int) () diff --git a/parser-tests/snippets/should-not-parse/type-alias-invalid-multiple-brackets-2 b/parser-tests/snippets/should-not-parse/type-alias-invalid-multiple-brackets-2 new file mode 100644 index 00000000..14e48f96 --- /dev/null +++ b/parser-tests/snippets/should-not-parse/type-alias-invalid-multiple-brackets-2 @@ -0,0 +1 @@ +type alias Hi = () () diff --git a/parser-tests/snippets/should-not-parse/type-alias-invalid-multiple-brackets-3 b/parser-tests/snippets/should-not-parse/type-alias-invalid-multiple-brackets-3 new file mode 100644 index 00000000..b6cca46d --- /dev/null +++ b/parser-tests/snippets/should-not-parse/type-alias-invalid-multiple-brackets-3 @@ -0,0 +1 @@ +type alias Hi = () (Int) diff --git a/parser-tests/snippets/should-not-parse/type-alias-lower-case-types b/parser-tests/snippets/should-not-parse/type-alias-lower-case-types new file mode 100644 index 00000000..a1c71a32 --- /dev/null +++ b/parser-tests/snippets/should-not-parse/type-alias-lower-case-types @@ -0,0 +1,8 @@ +type alias A = B.C.d + +type alias B = List A.d + +type alias C = list A + +type alias D a = a -> B.c +type alias E a = B.c -> a \ No newline at end of file diff --git a/parser-tests/snippets/should-not-parse/type-alias-multiline-missing-indentation b/parser-tests/snippets/should-not-parse/type-alias-multiline-missing-indentation new file mode 100644 index 00000000..9dd9e669 --- /dev/null +++ b/parser-tests/snippets/should-not-parse/type-alias-multiline-missing-indentation @@ -0,0 +1,2 @@ +type alias Model = +List Int diff --git a/parser-tests/snippets/should-not-parse/type-alias-partial b/parser-tests/snippets/should-not-parse/type-alias-partial new file mode 100644 index 00000000..75eda7f0 --- /dev/null +++ b/parser-tests/snippets/should-not-parse/type-alias-partial @@ -0,0 +1 @@ +type alias diff --git a/parser-tests/snippets/should-not-parse/type-alias-partial-2 b/parser-tests/snippets/should-not-parse/type-alias-partial-2 new file mode 100644 index 00000000..2d0f58fe --- /dev/null +++ b/parser-tests/snippets/should-not-parse/type-alias-partial-2 @@ -0,0 +1 @@ +type alias Hi diff --git a/parser-tests/snippets/should-not-parse/type-alias-partial-3 b/parser-tests/snippets/should-not-parse/type-alias-partial-3 new file mode 100644 index 00000000..b9163533 --- /dev/null +++ b/parser-tests/snippets/should-not-parse/type-alias-partial-3 @@ -0,0 +1 @@ +type alias Hi = diff --git a/parser-tests/snippets/should-not-parse/type-alias-partial-with-bracket b/parser-tests/snippets/should-not-parse/type-alias-partial-with-bracket new file mode 100644 index 00000000..e834db67 --- /dev/null +++ b/parser-tests/snippets/should-not-parse/type-alias-partial-with-bracket @@ -0,0 +1 @@ +type alias Hi = ( diff --git a/parser-tests/snippets/should-not-parse/type-alias-partial-with-bracket-2 b/parser-tests/snippets/should-not-parse/type-alias-partial-with-bracket-2 new file mode 100644 index 00000000..338f61f0 --- /dev/null +++ b/parser-tests/snippets/should-not-parse/type-alias-partial-with-bracket-2 @@ -0,0 +1,2 @@ +type alias Hi = ( + Int diff --git a/parser-tests/snippets/should-not-parse/type-alias-record-half-empty b/parser-tests/snippets/should-not-parse/type-alias-record-half-empty new file mode 100644 index 00000000..d5931b68 --- /dev/null +++ b/parser-tests/snippets/should-not-parse/type-alias-record-half-empty @@ -0,0 +1 @@ +type alias Ty = { diff --git a/parser-tests/snippets/should-not-parse/type-alias-record-missing-colon b/parser-tests/snippets/should-not-parse/type-alias-record-missing-colon new file mode 100644 index 00000000..9d0955b8 --- /dev/null +++ b/parser-tests/snippets/should-not-parse/type-alias-record-missing-colon @@ -0,0 +1 @@ +type alias Ty = { hi j7 } diff --git a/parser-tests/snippets/should-not-parse/type-alias-with-quadruple b/parser-tests/snippets/should-not-parse/type-alias-with-quadruple new file mode 100644 index 00000000..1d848f3b --- /dev/null +++ b/parser-tests/snippets/should-not-parse/type-alias-with-quadruple @@ -0,0 +1,2 @@ +type alias Hi = (Int, A, B, C, D) +type alias Hi = (A Int, C D E F, H I (J K), L M () O P) diff --git a/parser-tests/snippets/should-not-parse/type-alias-with-tuple-double-comma b/parser-tests/snippets/should-not-parse/type-alias-with-tuple-double-comma new file mode 100644 index 00000000..03cae1e5 --- /dev/null +++ b/parser-tests/snippets/should-not-parse/type-alias-with-tuple-double-comma @@ -0,0 +1 @@ +type alias Hi = (Int, , A) diff --git a/parser-tests/snippets/should-not-parse/type-alias-with-tuple-not-closed b/parser-tests/snippets/should-not-parse/type-alias-with-tuple-not-closed new file mode 100644 index 00000000..2b6ad7ea --- /dev/null +++ b/parser-tests/snippets/should-not-parse/type-alias-with-tuple-not-closed @@ -0,0 +1,4 @@ +type alias Hi = (Int, + + + diff --git a/parser-tests/snippets/should-not-parse/type-partial b/parser-tests/snippets/should-not-parse/type-partial new file mode 100644 index 00000000..aa80e646 --- /dev/null +++ b/parser-tests/snippets/should-not-parse/type-partial @@ -0,0 +1 @@ +type diff --git a/parser-tests/snippets/should-parse/expression-int b/parser-tests/snippets/should-parse/expression-int new file mode 100644 index 00000000..3d3ed933 --- /dev/null +++ b/parser-tests/snippets/should-parse/expression-int @@ -0,0 +1,3 @@ +a = 5 + +b = 78 diff --git a/parser-tests/snippets/should-parse/expression-int-add b/parser-tests/snippets/should-parse/expression-int-add new file mode 100644 index 00000000..ee8724ca --- /dev/null +++ b/parser-tests/snippets/should-parse/expression-int-add @@ -0,0 +1,3 @@ +a = 5 + 5 + +b = 78 + 5 + 2+ 4 diff --git a/parser-tests/snippets/should-parse/expression-int-multiply b/parser-tests/snippets/should-parse/expression-int-multiply new file mode 100644 index 00000000..e34459ec --- /dev/null +++ b/parser-tests/snippets/should-parse/expression-int-multiply @@ -0,0 +1,3 @@ +a = 5 * 5 + +b = 78 * 5 * 2 / 4 * 5 diff --git a/parser-tests/snippets/should-parse/expression-int-multiply-and-add b/parser-tests/snippets/should-parse/expression-int-multiply-and-add new file mode 100644 index 00000000..f694f9e2 --- /dev/null +++ b/parser-tests/snippets/should-parse/expression-int-multiply-and-add @@ -0,0 +1,13 @@ +a = 5 * 5 + 6 +a1 = 7 + 5 * 5 +a11 = 7 + 5 * 5 + 6 +a2 = 100 + 5 * 5 +a3 = 345 * 2234 + 2342 * 1010 + + +b = 78 + 5 * 2 / 4 * 5 +b1 = 78 * 5 * 2 / 4 - 5 +b2 = 78 * 5 - 2 / 4 * 5 +b3 = 78 - 5 + 2 / 4 * 5 +b4 = 78 / 5 / 2 / 4 + 5 + diff --git a/parser-tests/snippets/should-parse/expression-int-subtract b/parser-tests/snippets/should-parse/expression-int-subtract new file mode 100644 index 00000000..b47cb249 --- /dev/null +++ b/parser-tests/snippets/should-parse/expression-int-subtract @@ -0,0 +1,3 @@ +a = 5 - 5 + +b = 78 + 5 + 2 - 4 + 5 diff --git a/parser-tests/snippets/should-parse/type-alias b/parser-tests/snippets/should-parse/type-alias new file mode 100644 index 00000000..28e25425 --- /dev/null +++ b/parser-tests/snippets/should-parse/type-alias @@ -0,0 +1 @@ +type alias Model = List Int diff --git a/parser-tests/snippets/should-parse/type-alias-and-expression b/parser-tests/snippets/should-parse/type-alias-and-expression new file mode 100644 index 00000000..841b72b2 --- /dev/null +++ b/parser-tests/snippets/should-parse/type-alias-and-expression @@ -0,0 +1,3 @@ +type alias Model = List Int + +expr hi = 77 diff --git a/parser-tests/snippets/should-parse/type-alias-bracket-in-record b/parser-tests/snippets/should-parse/type-alias-bracket-in-record new file mode 100644 index 00000000..c9a28038 --- /dev/null +++ b/parser-tests/snippets/should-parse/type-alias-bracket-in-record @@ -0,0 +1 @@ +type alias Ty = { hi: (Int) } diff --git a/parser-tests/snippets/should-parse/type-alias-function b/parser-tests/snippets/should-parse/type-alias-function new file mode 100644 index 00000000..f28a436b --- /dev/null +++ b/parser-tests/snippets/should-parse/type-alias-function @@ -0,0 +1 @@ +type alias Function = List Int -> List (List Int) diff --git a/parser-tests/snippets/should-parse/type-alias-function-binding-order b/parser-tests/snippets/should-parse/type-alias-function-binding-order new file mode 100644 index 00000000..be3bef4d --- /dev/null +++ b/parser-tests/snippets/should-parse/type-alias-function-binding-order @@ -0,0 +1,2 @@ +type alias Function = A -> B -> C +type alias Function = A -> B -> C -> D diff --git a/parser-tests/snippets/should-parse/type-alias-function-generic b/parser-tests/snippets/should-parse/type-alias-function-generic new file mode 100644 index 00000000..cb780075 --- /dev/null +++ b/parser-tests/snippets/should-parse/type-alias-function-generic @@ -0,0 +1,3 @@ +type alias Function a = List Int -> List (List a) + +type alias Function b c = b -> c \ No newline at end of file diff --git a/parser-tests/snippets/should-parse/type-alias-function-nested b/parser-tests/snippets/should-parse/type-alias-function-nested new file mode 100644 index 00000000..0960177f --- /dev/null +++ b/parser-tests/snippets/should-parse/type-alias-function-nested @@ -0,0 +1,7 @@ +type alias Function = (() -> (Int, String)) + +type alias Function2 = { a: () -> (Int, String) } + +type alias Function3 = (() -> (Int, String), ()) + +type alias Function3 = (Int, () -> (Int, String), ()) diff --git a/parser-tests/snippets/should-parse/type-alias-function-record b/parser-tests/snippets/should-parse/type-alias-function-record new file mode 100644 index 00000000..7c4aecfe --- /dev/null +++ b/parser-tests/snippets/should-parse/type-alias-function-record @@ -0,0 +1 @@ +type alias Function = { a: { b: C}, d: E } -> {} diff --git a/parser-tests/snippets/should-parse/type-alias-function-tuple b/parser-tests/snippets/should-parse/type-alias-function-tuple new file mode 100644 index 00000000..846a2516 --- /dev/null +++ b/parser-tests/snippets/should-parse/type-alias-function-tuple @@ -0,0 +1 @@ +type alias Function = () -> (Int, String) diff --git a/parser-tests/snippets/should-parse/type-alias-function-type-args b/parser-tests/snippets/should-parse/type-alias-function-type-args new file mode 100644 index 00000000..1ab584d5 --- /dev/null +++ b/parser-tests/snippets/should-parse/type-alias-function-type-args @@ -0,0 +1 @@ +type alias Function = List A -> List B C D -> List D E F diff --git a/parser-tests/snippets/should-parse/type-alias-funky-indentation b/parser-tests/snippets/should-parse/type-alias-funky-indentation new file mode 100644 index 00000000..8550df91 --- /dev/null +++ b/parser-tests/snippets/should-parse/type-alias-funky-indentation @@ -0,0 +1,2 @@ +type alias + Model = List Int diff --git a/parser-tests/snippets/should-parse/type-alias-funky-indentation-2 b/parser-tests/snippets/should-parse/type-alias-funky-indentation-2 new file mode 100644 index 00000000..c2026530 --- /dev/null +++ b/parser-tests/snippets/should-parse/type-alias-funky-indentation-2 @@ -0,0 +1,3 @@ +type alias + Model = + List Int diff --git a/parser-tests/snippets/should-parse/type-alias-qualified-type b/parser-tests/snippets/should-parse/type-alias-qualified-type new file mode 100644 index 00000000..d7854fbc --- /dev/null +++ b/parser-tests/snippets/should-parse/type-alias-qualified-type @@ -0,0 +1,3 @@ +type alias A = B.C.D + +type alias A = List B.C.D \ No newline at end of file diff --git a/parser-tests/snippets/should-parse/type-alias-record-3-entries b/parser-tests/snippets/should-parse/type-alias-record-3-entries new file mode 100644 index 00000000..d7de8e6d --- /dev/null +++ b/parser-tests/snippets/should-parse/type-alias-record-3-entries @@ -0,0 +1 @@ +type alias Ty = { a: A, b: B, c: C } diff --git a/parser-tests/snippets/should-parse/type-alias-record-empty b/parser-tests/snippets/should-parse/type-alias-record-empty new file mode 100644 index 00000000..21e03e70 --- /dev/null +++ b/parser-tests/snippets/should-parse/type-alias-record-empty @@ -0,0 +1 @@ +type alias Ty = {} diff --git a/parser-tests/snippets/should-parse/type-alias-record-empty-multiline b/parser-tests/snippets/should-parse/type-alias-record-empty-multiline new file mode 100644 index 00000000..36c8e64c --- /dev/null +++ b/parser-tests/snippets/should-parse/type-alias-record-empty-multiline @@ -0,0 +1,4 @@ +type alias Ty = { + + + } diff --git a/parser-tests/snippets/should-parse/type-alias-record-in-bracket b/parser-tests/snippets/should-parse/type-alias-record-in-bracket new file mode 100644 index 00000000..b508363d --- /dev/null +++ b/parser-tests/snippets/should-parse/type-alias-record-in-bracket @@ -0,0 +1 @@ +type alias Ty = ({ hi: Int }) diff --git a/parser-tests/snippets/should-parse/type-alias-record-nested b/parser-tests/snippets/should-parse/type-alias-record-nested new file mode 100644 index 00000000..740b4600 --- /dev/null +++ b/parser-tests/snippets/should-parse/type-alias-record-nested @@ -0,0 +1,4 @@ +type alias Ty = + { hi: { a: Int, b: List String } + , ih: CustomType A B C (D E) + } diff --git a/parser-tests/snippets/should-parse/type-alias-record-simple b/parser-tests/snippets/should-parse/type-alias-record-simple new file mode 100644 index 00000000..2841ea53 --- /dev/null +++ b/parser-tests/snippets/should-parse/type-alias-record-simple @@ -0,0 +1 @@ +type alias Ty = { hi: Int } diff --git a/parser-tests/snippets/should-parse/type-alias-record-two-entries b/parser-tests/snippets/should-parse/type-alias-record-two-entries new file mode 100644 index 00000000..a4663cf2 --- /dev/null +++ b/parser-tests/snippets/should-parse/type-alias-record-two-entries @@ -0,0 +1 @@ +type alias Ty = { hi: (), buy: String } diff --git a/parser-tests/snippets/should-parse/type-alias-unit b/parser-tests/snippets/should-parse/type-alias-unit new file mode 100644 index 00000000..70908a19 --- /dev/null +++ b/parser-tests/snippets/should-parse/type-alias-unit @@ -0,0 +1 @@ +type alias Hi = () diff --git a/parser-tests/snippets/should-parse/type-alias-with-bracket b/parser-tests/snippets/should-parse/type-alias-with-bracket new file mode 100644 index 00000000..a11313ad --- /dev/null +++ b/parser-tests/snippets/should-parse/type-alias-with-bracket @@ -0,0 +1 @@ +type alias Hi = (Int) diff --git a/parser-tests/snippets/should-parse/type-alias-with-bracket-2 b/parser-tests/snippets/should-parse/type-alias-with-bracket-2 new file mode 100644 index 00000000..a52b546c --- /dev/null +++ b/parser-tests/snippets/should-parse/type-alias-with-bracket-2 @@ -0,0 +1 @@ +type alias Hi = (List Int) diff --git a/parser-tests/snippets/should-parse/type-alias-with-pair b/parser-tests/snippets/should-parse/type-alias-with-pair new file mode 100644 index 00000000..4d9f7b29 --- /dev/null +++ b/parser-tests/snippets/should-parse/type-alias-with-pair @@ -0,0 +1,2 @@ +type alias Hi = (Int, List String) +type alias Hi = (Int) diff --git a/parser-tests/snippets/should-parse/type-alias-with-tripple b/parser-tests/snippets/should-parse/type-alias-with-tripple new file mode 100644 index 00000000..54357e69 --- /dev/null +++ b/parser-tests/snippets/should-parse/type-alias-with-tripple @@ -0,0 +1,2 @@ +type alias Hi = (Int, Two, Three) +type alias Hi = ((), (), ()) diff --git a/parser-tests/snippets/should-parse/type-alias-with-tripple-in-record b/parser-tests/snippets/should-parse/type-alias-with-tripple-in-record new file mode 100644 index 00000000..410d38b1 --- /dev/null +++ b/parser-tests/snippets/should-parse/type-alias-with-tripple-in-record @@ -0,0 +1,4 @@ +type alias Hi = + { a: (Int, Int, Int) + , b: ({ good_bye: () }) + } diff --git a/parser-tests/update.js b/parser-tests/update.js new file mode 100755 index 00000000..a371e752 --- /dev/null +++ b/parser-tests/update.js @@ -0,0 +1,108 @@ +#!/usr/bin/env node + +const fs = require('fs').promises; +const path = require('path'); +const assert = require('assert'); +const {Elm} = require('./elm.js'); + +const warningCommentLines = ` + +-- AUTO GENERATED TEST CASES +-- +-- Do not edit below this line or your changes will be overwritten by +-- tests/parser-tests/update.js + + +` + .trim() + .split('\n'); + +const TYPE_OF_RESULT_CASES = ` + List + { contextualized : Maybe (List Contextualize.RunResult) + , pretty : String + , lexed : Result Never (List (Located LexItem)) + , name : String + , source : String + } +`; + +const TEST_FILE_PATH = path.join(__dirname, '..', 'tests', 'ParserLexerTestCases.elm'); +const BASE_SNIPPETS_DIR_PATH = path.join(__dirname, 'snippets'); +const SNIPPETS_DIR_PATH = Object.freeze({ + shouldParse: path.join(BASE_SNIPPETS_DIR_PATH, 'should-parse'), + shouldNotParse: path.join(BASE_SNIPPETS_DIR_PATH, 'should-not-parse') +}); + +function getTestCase(snippets) { + return new Promise(resolve => { + const app = Elm.Update.init({flags: snippets}); + app.ports.output.subscribe(resolve); + }); +} + +async function main() { + const testFile = await fs.readFile(TEST_FILE_PATH, 'utf-8'); + + const epilogueStart = testFile.indexOf(warningCommentLines[0]); + assert.notStrictEqual(epilogueStart, -1); + + const testFileStart = testFile.slice(0, epilogueStart).trim(); + + const snippets = await Promise.all( + Object.entries(SNIPPETS_DIR_PATH).map(async ([category, dirPath]) => { + let files; + try { + files = await fs.readdir(dirPath); + } catch (error) { + if (error.code === 'ENOENT') { + return [category, []]; + } + + throw error; + } + + return [ + category, + await Promise.all( + files + .sort() + .filter(name => !name.startsWith('_')) + .map(async name => ({ + name, + source: await fs.readFile(path.join(dirPath, name), 'utf-8') + })) + ) + ]; + }) + ); + + const testCases = await Promise.all( + snippets.map(async ([category, snippets2]) => [category, await getTestCase(snippets2)]) + ); + + if (testCases.some(([_, tests]) => tests.includes('Panic'))) { + console.error('ERROR: One or more test cases panicked!'); + process.exitCode = 1; + } + + const newTestFile = [ + testFileStart, + '\n\n', + warningCommentLines.join('\n'), + '\n', + testCases + .flatMap(([category, testCases]) => [ + `${category}TestCases :`, + TYPE_OF_RESULT_CASES, + `${category}TestCases =`, + testCases, + '\n' + ]) + .join('\n') + ].join('\n'); + + await fs.writeFile(TEST_FILE_PATH, newTestFile); +} + +main(); diff --git a/src/Elm/AST/Canonical.elm b/src/Elm/AST/Canonical.elm index d8577dfd..d56785a4 100644 --- a/src/Elm/AST/Canonical.elm +++ b/src/Elm/AST/Canonical.elm @@ -18,6 +18,7 @@ import Elm.Data.Binding as Binding exposing (Binding) import Elm.Data.Located as Located exposing (Located) import Elm.Data.Module exposing (Module) import Elm.Data.ModuleName exposing (ModuleName) +import Elm.Data.Operator exposing (Operator) import Elm.Data.Qualifiedness exposing (Qualified) import Elm.Data.Type.Concrete exposing (ConcreteType) import Elm.Data.VarName exposing (VarName) @@ -73,8 +74,7 @@ type Expr | Bool Bool | Var { module_ : ModuleName, name : VarName } | Argument VarName - | Plus LocatedExpr LocatedExpr - | Cons LocatedExpr LocatedExpr + | Operator (Located Operator) LocatedExpr LocatedExpr | Lambda { argument : VarName, body : LocatedExpr } | Call { fn : LocatedExpr, argument : LocatedExpr } | If { test : LocatedExpr, then_ : LocatedExpr, else_ : LocatedExpr } @@ -140,13 +140,9 @@ unwrap expr = Argument name -> Unwrapped.Argument name - Plus e1 e2 -> - Unwrapped.Plus - (f e1) - (f e2) - - Cons e1 e2 -> - Unwrapped.Cons + Operator op e1 e2 -> + Unwrapped.Operator + (Located.unwrap op) (f e1) (f e2) @@ -299,13 +295,9 @@ fromUnwrapped expr = Unwrapped.Argument name -> Argument name - Unwrapped.Plus e1 e2 -> - Plus - (f e1) - (f e2) - - Unwrapped.Cons e1 e2 -> - Cons + Unwrapped.Operator op e1 e2 -> + Operator + (Located.located Located.dummyRegion op) (f e1) (f e2) diff --git a/src/Elm/AST/Canonical/Unwrapped.elm b/src/Elm/AST/Canonical/Unwrapped.elm index 9bc884e9..be46c091 100644 --- a/src/Elm/AST/Canonical/Unwrapped.elm +++ b/src/Elm/AST/Canonical/Unwrapped.elm @@ -18,6 +18,7 @@ and from it using [`Elm.AST.Canonical.fromUnwrapped`](Elm.AST.Canonical#fromUnwr import Dict exposing (Dict) import Elm.Data.Binding exposing (Binding) import Elm.Data.ModuleName exposing (ModuleName) +import Elm.Data.Operator exposing (Operator) import Elm.Data.VarName exposing (VarName) @@ -30,8 +31,7 @@ type Expr | Bool Bool | Var { module_ : ModuleName, name : VarName } | Argument VarName - | Plus Expr Expr - | Cons Expr Expr + | Operator Operator Expr Expr | Lambda { argument : VarName, body : Expr } | Call { fn : Expr, argument : Expr } | If { test : Expr, then_ : Expr, else_ : Expr } diff --git a/src/Elm/AST/Frontend.elm b/src/Elm/AST/Frontend.elm index f433361d..05cf12ec 100644 --- a/src/Elm/AST/Frontend.elm +++ b/src/Elm/AST/Frontend.elm @@ -19,6 +19,7 @@ import Elm.Data.Binding as Binding exposing (Binding) import Elm.Data.Located as Located exposing (Located) import Elm.Data.Module exposing (Module) import Elm.Data.ModuleName exposing (ModuleName) +import Elm.Data.Operator exposing (Operator) import Elm.Data.Qualifiedness exposing (PossiblyQualified) import Elm.Data.TypeAnnotation exposing (TypeAnnotation) import Elm.Data.VarName exposing (VarName) @@ -60,9 +61,7 @@ type Expr | Var { qualifiedness : PossiblyQualified, name : VarName } | -- Both lambda arguments and let..in bindings Argument VarName - | Plus LocatedExpr LocatedExpr - | Cons LocatedExpr LocatedExpr - | ListConcat LocatedExpr LocatedExpr + | Operator (Located Operator) LocatedExpr LocatedExpr | Lambda { arguments : List VarName, body : LocatedExpr } | Call { fn : LocatedExpr, argument : LocatedExpr } | If { test : LocatedExpr, then_ : LocatedExpr, else_ : LocatedExpr } @@ -131,19 +130,12 @@ recurse f expr = Argument _ -> expr - Plus e1 e2 -> - Plus + Operator op e1 e2 -> + Operator + op (f_ e1) (f_ e2) - Cons e1 e2 -> - Cons - (f_ e1) - (f_ e2) - - ListConcat e1 e2 -> - ListConcat (f_ e1) (f_ e2) - Lambda ({ body } as lambda_) -> Lambda { lambda_ | body = f_ body } @@ -239,18 +231,9 @@ unwrap expr = Argument name -> Unwrapped.Argument name - Plus e1 e2 -> - Unwrapped.Plus - (unwrap e1) - (unwrap e2) - - Cons e1 e2 -> - Unwrapped.Cons - (unwrap e1) - (unwrap e2) - - ListConcat e1 e2 -> - Unwrapped.ListConcat + Operator op e1 e2 -> + Unwrapped.Operator + (Located.unwrap op) (unwrap e1) (unwrap e2) diff --git a/src/Elm/AST/Frontend/Unwrapped.elm b/src/Elm/AST/Frontend/Unwrapped.elm index 69e59632..448a18fb 100644 --- a/src/Elm/AST/Frontend/Unwrapped.elm +++ b/src/Elm/AST/Frontend/Unwrapped.elm @@ -14,6 +14,7 @@ Convert to it using the [`Elm.AST.Frontend.unwrap`](Elm.AST.Frontend#unwrap). -} import Elm.Data.Binding exposing (Binding) +import Elm.Data.Operator exposing (Operator) import Elm.Data.Qualifiedness exposing (PossiblyQualified) import Elm.Data.VarName exposing (VarName) @@ -28,9 +29,7 @@ type Expr | Bool Bool | Var { qualifiedness : PossiblyQualified, name : VarName } | Argument VarName - | Plus Expr Expr - | Cons Expr Expr - | ListConcat Expr Expr + | Operator Operator Expr Expr | Lambda { arguments : List VarName, body : Expr } | Call { fn : Expr, argument : Expr } | If { test : Expr, then_ : Expr, else_ : Expr } diff --git a/src/Elm/AST/Typed.elm b/src/Elm/AST/Typed.elm index 9722b619..f853444d 100644 --- a/src/Elm/AST/Typed.elm +++ b/src/Elm/AST/Typed.elm @@ -23,6 +23,7 @@ import Elm.Data.Binding as Binding exposing (Binding) import Elm.Data.Located as Located exposing (Located) import Elm.Data.Module exposing (Module) import Elm.Data.ModuleName exposing (ModuleName) +import Elm.Data.Operator exposing (Operator) import Elm.Data.Qualifiedness exposing (Qualified) import Elm.Data.Type as Type exposing (Type, TypeOrId(..)) import Elm.Data.VarName exposing (VarName) @@ -72,8 +73,7 @@ type Expr_ | Bool Bool | Var { module_ : ModuleName, name : VarName } | Argument VarName - | Plus LocatedExpr LocatedExpr - | Cons LocatedExpr LocatedExpr + | Operator (Located Operator) LocatedExpr LocatedExpr | Lambda { argument : VarName, body : LocatedExpr } | Call { fn : LocatedExpr, argument : LocatedExpr } | If { test : LocatedExpr, then_ : LocatedExpr, else_ : LocatedExpr } @@ -146,13 +146,9 @@ recurse fn locatedExpr = Argument _ -> expr - Plus e1 e2 -> - Plus - (fn e1) - (fn e2) - - Cons e1 e2 -> - Cons + Operator op e1 e2 -> + Operator + op (fn e1) (fn e2) @@ -266,13 +262,8 @@ recursiveChildren fn locatedExpr = Argument _ -> [] - Plus left right -> - fn left - ++ fn right - - Cons left right -> - fn left - ++ fn right + Operator _ left right -> + fn left ++ fn right Lambda { body } -> fn body @@ -380,13 +371,9 @@ unwrap expr = Argument name -> Unwrapped.Argument name - Plus e1 e2 -> - Unwrapped.Plus - (f e1) - (f e2) - - Cons e1 e2 -> - Unwrapped.Cons + Operator op e1 e2 -> + Unwrapped.Operator + (Located.unwrap op) (f e1) (f e2) @@ -545,13 +532,9 @@ dropTypes locatedExpr = Argument var -> Canonical.Argument var - Plus e1 e2 -> - Canonical.Plus - (f e1) - (f e2) - - Cons e1 e2 -> - Canonical.Cons + Operator op e1 e2 -> + Canonical.Operator + op (f e1) (f e2) diff --git a/src/Elm/AST/Typed/Unwrapped.elm b/src/Elm/AST/Typed/Unwrapped.elm index 651be0fe..4e54d5cd 100644 --- a/src/Elm/AST/Typed/Unwrapped.elm +++ b/src/Elm/AST/Typed/Unwrapped.elm @@ -16,6 +16,7 @@ Convert to it using the [`Elm.AST.Typed.unwrap`](Elm.AST.Typed#unwrap). import Dict exposing (Dict) import Elm.Data.Binding exposing (Binding) import Elm.Data.ModuleName exposing (ModuleName) +import Elm.Data.Operator exposing (Operator) import Elm.Data.Qualifiedness exposing (Qualified) import Elm.Data.Type exposing (TypeOrId) import Elm.Data.VarName exposing (VarName) @@ -37,8 +38,7 @@ type Expr_ | Bool Bool | Var { module_ : ModuleName, name : VarName } | Argument VarName - | Plus Expr Expr - | Cons Expr Expr + | Operator Operator Expr Expr | Lambda { argument : VarName, body : Expr } | Call { fn : Expr, argument : Expr } | If { test : Expr, then_ : Expr, else_ : Expr } diff --git a/src/Elm/Compiler.elm b/src/Elm/Compiler.elm index 55c592c6..2db92ba5 100644 --- a/src/Elm/Compiler.elm +++ b/src/Elm/Compiler.elm @@ -87,7 +87,7 @@ Eg. the `plus` optimization is (conceptually): optimizePlus : Expr -> Maybe Expr optimizePlus expr = case expr of - Plus (Int a) (Int b) -> + Operator Operator.Add (Int a) (Int b) -> Just (Int (a + b)) _ -> diff --git a/src/Elm/Data/Located.elm b/src/Elm/Data/Located.elm index 491feb83..f02b4c7d 100644 --- a/src/Elm/Data/Located.elm +++ b/src/Elm/Data/Located.elm @@ -1,6 +1,6 @@ module Elm.Data.Located exposing - ( Located, Region, Position - , located, unwrap, getRegion, map, merge, replaceWith + ( Located(..), Region, Position + , located, unwrap, getRegion, map, merge, merge3, replaceWith , dummyRegion, mergeRegions, regionToComparable , positionToComparable, comparePosition ) @@ -18,7 +18,7 @@ Useful for error messages, but hopefully for stuff like source maps etc. too. # Located -@docs located, unwrap, getRegion, map, merge, replaceWith +@docs located, unwrap, getRegion, map, merge, merge3, replaceWith # Region @@ -97,6 +97,15 @@ merge fn l1 l2 = (fn l1 l2) +{-| Merge the regions of the three wrappers. +-} +merge3 : (Located a -> Located b -> Located c -> d) -> Located a -> Located b -> Located c -> Located d +merge3 fn l1 l2 l3 = + Located + (mergeRegions (mergeRegions (getRegion l1) (getRegion l2)) (getRegion l3)) + (fn l1 l2 l3) + + {-| Merge the regions: the resulting region is always bigger or equal than the input regions. diff --git a/src/Elm/Data/Operator.elm b/src/Elm/Data/Operator.elm new file mode 100644 index 00000000..339e2c49 --- /dev/null +++ b/src/Elm/Data/Operator.elm @@ -0,0 +1,245 @@ +module Elm.Data.Operator exposing (..) + + +type Operator + = Add + | Subtract + | Multiply + | Divide + | Exponentiate + | And + | Or + | Equals + | GreaterThan + | GreaterThanEquals + | LessThan + | LessThanEquals + | Append + | Cons + + +{-| Operator precedence. + +Constructors are ordered from highest precedence to lowest. High precedence +operators bind more strongly to operands and thus end up deeper in the AST. + +-} +type OperatorPrecedence + = Composition + | Exponentiation + | Multiplication + | Addition + | Concatenation + | Comparison + | AndPrec + | OrPrec + | Pipe + + +type OperatorAssociativity + = ConflictsWithOthers + | ConflictsWithSelf + | RightToLeft + | LeftToRight + + +getPrecedence : Operator -> OperatorPrecedence +getPrecedence op = + case op of + Add -> + Addition + + Subtract -> + Addition + + Multiply -> + Multiplication + + Divide -> + Multiplication + + Exponentiate -> + Exponentiation + + And -> + AndPrec + + Or -> + OrPrec + + Equals -> + Comparison + + GreaterThan -> + Comparison + + GreaterThanEquals -> + Comparison + + LessThan -> + Comparison + + LessThanEquals -> + Comparison + + Append -> + Concatenation + + Cons -> + Concatenation + + +getAssociativity : OperatorPrecedence -> OperatorAssociativity +getAssociativity prec = + case prec of + Composition -> + ConflictsWithOthers + + Exponentiation -> + RightToLeft + + Multiplication -> + LeftToRight + + Addition -> + LeftToRight + + Concatenation -> + RightToLeft + + Comparison -> + ConflictsWithSelf + + AndPrec -> + RightToLeft + + OrPrec -> + RightToLeft + + Pipe -> + ConflictsWithOthers + + +toString : Operator -> String +toString op = + case op of + Add -> + "+" + + Subtract -> + "-" + + Multiply -> + "*" + + Divide -> + "/" + + Exponentiate -> + "^" + + And -> + "&&" + + Or -> + "||" + + Equals -> + "==" + + GreaterThan -> + ">" + + GreaterThanEquals -> + ">=" + + LessThan -> + "<" + + LessThanEquals -> + "<=" + + Cons -> + "::" + + Append -> + "++" + + +comparePrec : { lhs : OperatorPrecedence, rhs : OperatorPrecedence } -> Order +comparePrec { lhs, rhs } = + case ( lhs, rhs ) of + ( Composition, Composition ) -> + EQ + + ( Composition, _ ) -> + GT + + ( _, Composition ) -> + LT + + ( Exponentiation, Exponentiation ) -> + EQ + + ( Exponentiation, _ ) -> + GT + + ( _, Exponentiation ) -> + LT + + ( Multiplication, Multiplication ) -> + EQ + + ( Multiplication, _ ) -> + GT + + ( _, Multiplication ) -> + LT + + ( Addition, Addition ) -> + EQ + + ( Addition, _ ) -> + GT + + ( _, Addition ) -> + LT + + ( Concatenation, Concatenation ) -> + EQ + + ( Concatenation, _ ) -> + GT + + ( _, Concatenation ) -> + LT + + ( Comparison, Comparison ) -> + EQ + + ( Comparison, _ ) -> + GT + + ( _, Comparison ) -> + LT + + ( AndPrec, AndPrec ) -> + EQ + + ( AndPrec, _ ) -> + GT + + ( _, AndPrec ) -> + LT + + ( OrPrec, OrPrec ) -> + EQ + + ( OrPrec, _ ) -> + GT + + ( _, OrPrec ) -> + LT + + ( Pipe, Pipe ) -> + EQ diff --git a/src/Stage/Desugar.elm b/src/Stage/Desugar.elm index 50da640a..2530135f 100644 --- a/src/Stage/Desugar.elm +++ b/src/Stage/Desugar.elm @@ -116,36 +116,11 @@ desugarExpr modules thisModule locatedExpr = Frontend.Argument varName -> return <| Canonical.Argument varName - Frontend.Plus e1 e2 -> - map2 Canonical.Plus + Frontend.Operator op e1 e2 -> + map2 (Canonical.Operator op) (f e1) (f e2) - Frontend.Cons e1 e2 -> - map2 Canonical.Cons - (f e1) - (f e2) - - Frontend.ListConcat e1 e2 -> - let - region = - Located.getRegion locatedExpr - - listConcatVar = - Frontend.Var - { qualifiedness = PossiblyQualified <| Just "List" - , name = "append" - } - |> Located.located region - - firstCall = - Frontend.Call { fn = listConcatVar, argument = e1 } |> Located.located region - - expr = - Frontend.Call { fn = firstCall, argument = e2 } |> Located.located region - in - f expr - Frontend.Lambda { arguments, body } -> f body |> Result.map (curryLambda locatedExpr arguments) diff --git a/src/Stage/Emit.elm b/src/Stage/Emit.elm index 1b4d727d..f0208599 100644 --- a/src/Stage/Emit.elm +++ b/src/Stage/Emit.elm @@ -32,7 +32,7 @@ import AssocList import AssocSet import Dict exposing (Dict) import Dict.Extra as Dict -import Elm.AST.Typed as Typed exposing (Expr_(..)) +import Elm.AST.Typed as Typed exposing (Expr_(..), Pattern_(..)) import Elm.Compiler.Error exposing ( DesugarError(..) @@ -43,6 +43,7 @@ import Elm.Data.Declaration exposing (Declaration, DeclarationBody(..)) import Elm.Data.Exposing as Exposing exposing (ExposedItem(..), Exposing(..)) import Elm.Data.Module exposing (Module) import Elm.Data.ModuleName exposing (ModuleName) +import Elm.Data.Operator as Operator import Elm.Data.Project exposing (Project) import Elm.Data.Qualifiedness exposing (Qualified(..)) import Elm.Data.Type.Concrete as ConcreteType exposing (ConcreteType) @@ -489,12 +490,7 @@ findDependenciesOfExpr modules locatedExpr = Argument _ -> Ok [] - Plus e1 e2 -> - Result.map2 (++) - (f e1) - (f e2) - - Cons e1 e2 -> + Operator _ e1 e2 -> Result.map2 (++) (f e1) (f e2) diff --git a/src/Stage/Emit/JavaScript.elm b/src/Stage/Emit/JavaScript.elm index 92ed2b4e..2944a52b 100644 --- a/src/Stage/Emit/JavaScript.elm +++ b/src/Stage/Emit/JavaScript.elm @@ -23,6 +23,8 @@ import Elm.Compiler.Error exposing (Error(..)) import Elm.Data.Declaration exposing (Declaration, DeclarationBody(..)) import Elm.Data.FileContents exposing (FileContents) import Elm.Data.FilePath exposing (FilePath) +import Elm.Data.Located as Located +import Elm.Data.Operator as Operator exposing (Operator) import Elm.Data.Project exposing (Project) import Elm.Data.Qualifiedness exposing (Qualified) import Stage.Emit.Common exposing (mangleQualifiedVar, mangleVarName, prepareProjectFields) @@ -75,11 +77,19 @@ emitExpr located = Argument argument -> mangleVarName argument - Plus e1 e2 -> - "(" ++ emitExpr e1 ++ " + " ++ emitExpr e2 ++ ")" + Operator op e1 e2 -> + case Located.unwrap op of + Operator.Add -> + "(" ++ emitExpr e1 ++ " + " ++ emitExpr e2 ++ ")" - Cons e1 e2 -> - "[" ++ emitExpr e1 ++ "].concat(" ++ emitExpr e2 ++ ")" + Operator.Cons -> + "[" ++ emitExpr e1 ++ "].concat(" ++ emitExpr e2 ++ ")" + + Operator.Append -> + emitExpr e1 ++ ".concat(" ++ emitExpr e2 ++ ")" + + _ -> + Debug.todo "emit js for other operators" Lambda { argument, body } -> -- TODO are these parentheses needed? diff --git a/src/Stage/Emit/JsonAST.elm b/src/Stage/Emit/JsonAST.elm index d0e68683..4f334d31 100644 --- a/src/Stage/Emit/JsonAST.elm +++ b/src/Stage/Emit/JsonAST.elm @@ -25,6 +25,8 @@ import Elm.Compiler.Error exposing (Error(..)) import Elm.Data.Declaration exposing (Declaration, DeclarationBody(..)) import Elm.Data.FileContents exposing (FileContents) import Elm.Data.FilePath exposing (FilePath) +import Elm.Data.Located as Located +import Elm.Data.Operator as Operator exposing (Operator) import Elm.Data.Project exposing (Project) import Elm.Data.Qualifiedness exposing (Qualified) import Json.Encode as Encode exposing (Value) @@ -80,17 +82,23 @@ emitExpr located = Argument argument -> encode "arg" [ ( "name", Encode.string argument ) ] - Plus e1 e2 -> - encode "plus" - [ ( "e1", emitExpr e1 ) - , ( "e2", emitExpr e2 ) - ] - - Cons e1 e2 -> - encode "cons" - [ ( "e1", emitExpr e1 ) - , ( "e2", emitExpr e2 ) - ] + -- TODO(harry): Change this to `{ 'op': '+', lhs: { ... }, rhs: { ... } }` + Operator op e1 e2 -> + case Located.unwrap op of + Operator.Add -> + encode "plus" + [ ( "e1", emitExpr e1 ) + , ( "e2", emitExpr e2 ) + ] + + Operator.Cons -> + encode "cons" + [ ( "e1", emitExpr e1 ) + , ( "e2", emitExpr e2 ) + ] + + _ -> + Debug.todo "encode other operators into json" Lambda { argument, body } -> encode "lambda" diff --git a/src/Stage/InferTypes/AssignIds.elm b/src/Stage/InferTypes/AssignIds.elm index 8d50508f..f404b4a4 100644 --- a/src/Stage/InferTypes/AssignIds.elm +++ b/src/Stage/InferTypes/AssignIds.elm @@ -11,7 +11,8 @@ Input (forgive the nonsense AST): Canonical.If { test = - Canonical.Plus + Canonical.Operator + Operator.Add (Canonical.Int 1) (Canonical.Int 2) , then_ = Canonical.Unit @@ -22,7 +23,8 @@ Output: ( Typed.If { test = - ( Typed.Plus + ( Typed.Operator + Operator.Add ( Typed.Int 1 , Var 0 ) @@ -101,7 +103,7 @@ assignIdsHelp currentId located = Canonical.Var name -> assignId currentId (Typed.Var name) - Canonical.Plus e1 e2 -> + Canonical.Operator op e1 e2 -> let ( e1_, id1 ) = f currentId e1 @@ -109,17 +111,7 @@ assignIdsHelp currentId located = ( e2_, id2 ) = f id1 e2 in - assignId id2 (Typed.Plus e1_ e2_) - - Canonical.Cons e1 e2 -> - let - ( e1_, id1 ) = - f currentId e1 - - ( e2_, id2 ) = - f id1 e2 - in - assignId id2 (Typed.Cons e1_ e2_) + assignId id2 (Typed.Operator op e1_ e2_) Canonical.Lambda { argument, body } -> let diff --git a/src/Stage/InferTypes/GenerateEquations.elm b/src/Stage/InferTypes/GenerateEquations.elm index 42c53e41..efc87415 100644 --- a/src/Stage/InferTypes/GenerateEquations.elm +++ b/src/Stage/InferTypes/GenerateEquations.elm @@ -32,6 +32,7 @@ subexpression. import Dict import Elm.AST.Typed as Typed import Elm.Data.Located as Located +import Elm.Data.Operator as Operator exposing (Operator) import Elm.Data.Qualifiedness exposing (Qualified) import Elm.Data.Type as Type exposing (Type(..), TypeOrId(..)) import Elm.Data.VarName exposing (VarName) @@ -92,7 +93,7 @@ generateEquations currentId located = -- we can't make any assumptions here ( [], currentId ) - Typed.Plus left right -> + Typed.Operator op left right -> let ( _, leftType ) = Located.unwrap left @@ -105,35 +106,25 @@ generateEquations currentId located = ( rightEquations, id2 ) = generateEquations id1 right - in - ( -- for expression `a + b`: - [ equals leftType (Type Int) -- type of `a` is Int - , equals rightType (Type Int) -- type of `b` is Int - , equals type_ (Type Int) -- type of `a + b` is Int - ] - ++ leftEquations - ++ rightEquations - , id2 - ) - - Typed.Cons left right -> - let - ( _, leftType ) = - Located.unwrap left - ( _, rightType ) = - Located.unwrap right - - ( leftEquations, id1 ) = - generateEquations currentId left - - ( rightEquations, id2 ) = - generateEquations id1 right + opEquations = + case Located.unwrap op of + Operator.Add -> + [ equals leftType (Type Int) -- type of `a` is Int + , equals rightType (Type Int) -- type of `b` is Int + , equals type_ (Type Int) -- type of `a + b` is Int + ] + + Operator.Cons -> + [ equals rightType (Type (List leftType)) -- type of b is a List a + , equals type_ rightType -- a :: [ b ] is a List b + ] + + _ -> + Debug.todo "handle typing of other operators" in - ( -- For expression a :: [ b ]: - [ equals rightType (Type (List leftType)) -- type of b is a List a - , equals type_ rightType -- a :: [ b ] is a List b - ] + ( opEquations + -- for expression `a OP b`: ++ leftEquations ++ rightEquations , id2 diff --git a/src/Stage/Optimize.elm b/src/Stage/Optimize.elm index 9bef00c1..29b9d861 100644 --- a/src/Stage/Optimize.elm +++ b/src/Stage/Optimize.elm @@ -6,6 +6,8 @@ module Stage.Optimize exposing ) import Elm.AST.Typed as Typed +import Elm.Data.Located as Located +import Elm.Data.Operator as Operator import Elm.Data.Project exposing (Project) import Stage.Optimize.Boilerplate as Boilerplate @@ -38,10 +40,15 @@ defaultOptimizations = optimizePlus : Typed.LocatedExpr -> Maybe Typed.LocatedExpr optimizePlus located = case Typed.getExpr located of - Typed.Plus l r -> - case ( Typed.getExpr l, Typed.getExpr r ) of - ( Typed.Int left, Typed.Int right ) -> - Just (Typed.setExpr (Typed.Int (left + right)) r) + Typed.Operator op l r -> + case Located.unwrap op of + Operator.Add -> + case ( Typed.getExpr l, Typed.getExpr r ) of + ( Typed.Int left, Typed.Int right ) -> + Just (Typed.setExpr (Typed.Int (left + right)) r) + + _ -> + Nothing _ -> Nothing @@ -53,10 +60,15 @@ optimizePlus located = optimizeCons : Typed.LocatedExpr -> Maybe Typed.LocatedExpr optimizeCons located = case Typed.getExpr located of - Typed.Cons l r -> - case Typed.getExpr r of - Typed.List list -> - Just (Typed.setExpr (Typed.List (l :: list)) r) + Typed.Operator op l r -> + case Located.unwrap op of + Operator.Cons -> + case Typed.getExpr r of + Typed.List list -> + Just (Typed.setExpr (Typed.List (l :: list)) r) + + _ -> + Nothing _ -> Nothing diff --git a/src/Stage/Parse/Contextualize.elm b/src/Stage/Parse/Contextualize.elm new file mode 100644 index 00000000..4db3d09f --- /dev/null +++ b/src/Stage/Parse/Contextualize.elm @@ -0,0 +1,2022 @@ +module Stage.Parse.Contextualize exposing (..) + +{-| Here we define parsers. A parser is function + + type alias Parser = + Lexer.LexItem -> Result Error State + +that takes one lexed item and produces either an error or some state (it can also +choose to skip the lexed item). + +-} + +import Dict +import Elm.AST.Frontend as Frontend exposing (Expr(..), LocatedExpr, LocatedPattern, Pattern(..)) +import Elm.Data.Declaration +import Elm.Data.Exposing +import Elm.Data.Located as Located exposing (Located) +import Elm.Data.Module exposing (Module, ModuleType(..)) +import Elm.Data.ModuleName exposing (ModuleName) +import Elm.Data.Operator as Operator exposing (Operator) +import Elm.Data.Qualifiedness as Qualifiedness exposing (PossiblyQualified(..)) +import Elm.Data.Type.Concrete as ConcreteType exposing (ConcreteType) +import Elm.Data.VarName exposing (VarName) +import Stage.Parse.Lexer as Lexer exposing (LexItem(..), LexSigil(..)) +import Stage.Parse.Token as Token exposing (Keyword) + + +{-| An 'block' starts with an unindented line and continues until the next +unindented line. + +In the following Program + +```text +module Main exposing (..) -- 0 + + +import Dict -- 1 + +type A = A -- 2 + +a : A -- 3 +a = A -- 4 +``` + +There are five blocks. + +-} +type Block + = Module + { ty : Elm.Data.Module.ModuleType + , name : Elm.Data.ModuleName.ModuleName + , exposingList : Elm.Data.Exposing.Exposing + } + | ValueDeclaration + { name : Located Token.LowerCase + + -- TODO(harry): these could be patterns! + , args : List (Located Token.LowerCase) + + -- This key's name is hard coded into parser-tests/Update.elm + , valueExpr__ : Frontend.LocatedExpr + } + | TypeAlias + { ty : Token.UpperCase + , genericArgs : List Token.LowerCase + , expr : ConcreteType PossiblyQualified + } + | CustomType + { ty : VarName + , constructors : List (Elm.Data.Declaration.Constructor PossiblyQualified) + } + + +type State + = State_BlockStart + | State_Error_Recovery + | State_BlockFirstItem BlockFirstItem + | State_BlockTypeAlias BlockTypeAlias + | State_BlockCustomType BlockCustomType + | State_BlockValueDeclaration BlockValueDeclaration + + +type ParseSuccess + = ParseSuccess_NewState State + | ParseSuccess_Complete Block + | ParseSuccess_Skip + + +type alias State_ = + { previousBlocks : List RunResult + , state : State + } + + +type BlockFirstItem + = BlockFirstItem_Type + | BlockFirstItem_Module + + +type BlockTypeAlias + = BlockTypeAlias_Keywords + | BlockTypeAlias_Named Token.UpperCase (Stack Token.LowerCase) + | BlockTypeAlias_NamedAssigns Token.UpperCase (List Token.LowerCase) + | BlockTypeAlias_Completish Token.UpperCase (List Token.LowerCase) (TypeExpressionNestingLeaf () () ()) + + +type BlockCustomType + = BlockCustomType_Named Token.UpperCase (Stack Token.LowerCase) + | BlockCustomType_NamedAssigns Token.UpperCase (List Token.LowerCase) + + +type BlockValueDeclaration + = BlockValueDeclaration_Named + { name : Located Token.LowerCase + , args : Stack (Located Token.LowerCase) + } + | BlockValueDeclaration_NamedAssigns + { name : Located Token.LowerCase + , args : List (Located Token.LowerCase) + } + | BlockValueDeclaration_Completish + { name : Located Token.LowerCase + , args : List (Located Token.LowerCase) + , partialExpr : ExpressionNestingLeaf + } + + + +-- TYPE EXPRESSIONS -- + + +{-| Notes: + + - Type names can start with a lower case character as it may be generic. If + it is generic there should be no args (we do not check this currently + though :(). + +-} +type TypeExpression + = TypeExpression_NamedType + { qualifiers : List Token.UpperCase + , name : Token.UpperCase + , args : Stack TypeExpression + } + | TypeExpression_GenericType Token.LowerCase + | TypeExpression_Unit + | TypeExpression_Bracketed TypeExpression + | TypeExpression_Tuple TypeExpression TypeExpression (List TypeExpression) + | TypeExpression_Record (List ( Token.LowerCase, TypeExpression )) + | TypeExpression_Function + { firstInput : TypeExpression + , otherInputs : List TypeExpression + , output : TypeExpression + } + + +type LastEntryOfRecord + = LastEntryOfRecord_Empty + | LastEntryOfRecord_Key Token.LowerCase + | LastEntryOfRecord_KeyColon Token.LowerCase + | LastEntryOfRecord_KeyValue Token.LowerCase TypeExpression + + +type alias PartialRecord = + { firstEntries : Stack ( Token.LowerCase, TypeExpression ) + , lastEntry : LastEntryOfRecord + , parent : Maybe TypeExpressionNestingParent + } + + +type TypeExpressionNestingParent + = NestingParentType_Bracket + { expressions : Stack TypeExpression + , parent : Maybe TypeExpressionNestingParent + } + | NestingParentType_PartialRecord + { firstEntries : Stack ( Token.LowerCase, TypeExpression ) + , lastEntryName : Token.LowerCase + , parent : Maybe TypeExpressionNestingParent + } + | NestingParentType_TypeWithArgs + { qualifiers : List Token.UpperCase + , name : Token.UpperCase + , args : Stack TypeExpression + , parent : Maybe TypeExpressionNestingParent + , phantom : () + } + | NestingParentType_Function + { firstInput : TypeExpression + , otherInputs : Stack TypeExpression + , parent : Maybe TypeExpressionNestingParent + } + + +{-| Sometimes we need to limit which types of `TypeExpressionNestingLeaf` are valid. We do that using the phantom type +parameters. For example `TypeExpressionNestingLeaf () Never` cannot be a `TypeExpressionNestingLeaf_TypeWithArgs`. +-} +type TypeExpressionNestingLeaf phantomFunctionWithOutput phantomTypeWithArgs phantomHasParent + = TypeExpressionNestingLeaf_Bracket + { firstExpressions : Stack TypeExpression + , trailingExpression : Maybe TypeExpression + , parent : Maybe TypeExpressionNestingParent + } + | TypeExpressionNestingLeaf_PartialRecord PartialRecord + | TypeExpressionNestingLeaf_TypeWithArgs + { qualifiers : List Token.UpperCase + , name : Token.UpperCase + , args : Stack TypeExpression + , parent : Maybe TypeExpressionNestingParent + , phantom : phantomTypeWithArgs + } + | TypeExpressionNestingLeaf_Function + { firstInput : TypeExpression + , otherInputs : Stack TypeExpression + , output : Maybe ( TypeExpression, phantomFunctionWithOutput ) + , parent : Maybe TypeExpressionNestingParent + } + | TypeExpressionNestingLeaf_Expr phantomHasParent TypeExpression + + + +-- EXPRESSIONS -- + + +type ExpressionNestingParent + = ExpressionNestingParent_Operator + { op : Located Operator + , lhs : Frontend.LocatedExpr + , parent : Maybe ExpressionNestingParent + } + + +type ExpressionNestingLeaf + = ExpressionNestingLeaf_Operator + { op : Located Operator + , lhs : Frontend.LocatedExpr + , rhs : Maybe Frontend.LocatedExpr + , parent : Maybe ExpressionNestingParent + } + | ExpressionTypeExpressionNestingLeaf_Expr Frontend.LocatedExpr + + +type Error + = Error_InvalidToken Expecting + | Error_MisplacedKeyword Keyword + | Error_BlockStartsWithUpperCase Token.UpperCase + | Error_BlockStartsWithQualifiedName + { qualifiers : List Token.UpperCase + , name : Token.Token + } + | Error_QualifiedArgName + { qualifiers : List Token.UpperCase + , name : Token.Token + } + | Error_UpperCaseArgName + { qualifiers : List Token.UpperCase + , name : Token.UpperCase + } + | Error_UpperCaseRecordKey Token.UpperCase + | Error_QualifiedRecordKey + { qualifiers : List Token.UpperCase + , name : Token.Token + } + | Error_LowerCasedTypename + { qualifiers : List Token.UpperCase + , name : Token.LowerCase + } + -- Type Expressions -- + | Error_UnmatchedBracket Lexer.BracketType Lexer.BracketRole + | Error_WrongClosingBracket + { expecting : Lexer.BracketType + , found : Lexer.BracketType + } + | Error_MissingFunctionReturnType + | Error_ExpectedColonWhilstParsingRecord + | Error_ExpectedKeyWhilstParsingRecord + | Error_TypeDoesNotTakeArgs TypeExpression (TypeExpressionNestingLeaf () () ()) + | Error_ValueDoesNotTakeArgs Frontend.LocatedExpr + | Error_ExtraItemAfterBlock TypeExpression Lexer.LexItem + | Error_TooManyTupleArgs + -- + (ConcreteType PossiblyQualified) + (ConcreteType PossiblyQualified) + (ConcreteType PossiblyQualified) + (ConcreteType PossiblyQualified) + (List (ConcreteType PossiblyQualified)) + -- Expressions -- + | Error_InvalidNumericLiteral String + | Error_ConflictingOperators (Located Operator) (Located Operator) + -- Incomplete parsing -- + | Error_PartwayThroughBlock + | Error_PartwayThroughValueDeclaration + -- Bugs in the parser -- + | Error_Panic String + + +type Expecting + = Expecting_Sigil Lexer.LexSigil + | Expecting_Block + | Expecting_TypeName + | Expecting_Identifier + -- TODO(harry): reduce number of cases where we do not know what sigil we + -- are expecting. + | Expecting_Unknown + + + +-- exported functions + + +type alias RunResult = + Result + { state : State + , item : Maybe (Located LexItem) + , error : Error + } + Block + + +run : List (Located LexItem) -> List RunResult +run items = + runHelp + items + { previousBlocks = [] + , state = State_BlockStart + } + + +runHelp : List (Located LexItem) -> State_ -> List RunResult +runHelp items state = + case items of + item :: rest -> + case parseAnything state.state item of + Ok (ParseSuccess_NewState newState_) -> + runHelp + rest + { previousBlocks = state.previousBlocks + , state = newState_ + } + + Ok (ParseSuccess_Complete block) -> + runHelp + rest + { previousBlocks = Ok block :: state.previousBlocks + , state = State_BlockStart + } + + Ok ParseSuccess_Skip -> + runHelp + rest + state + + Err error -> + runHelp + (case error of + Error_Panic _ -> + [{- An empty list to abort parsing. -}] + + _ -> + rest + ) + { previousBlocks = + Err + { state = state.state + , item = Just item + , error = error + } + :: state.previousBlocks + , state = + case Located.unwrap item of + Lexer.Newlines _ 0 -> + State_BlockStart + + _ -> + State_Error_Recovery + } + + [] -> + List.reverse + (case blockFromState state.state of + Nothing -> + state.previousBlocks + + Just newBlock -> + (newBlock + |> Result.mapError + (\err -> + { state = state.state + , item = Nothing + , error = err + } + ) + ) + :: state.previousBlocks + ) + + + +-- parsers + + +parseAnything : State -> Located Lexer.LexItem -> Result Error ParseSuccess +parseAnything state item = + let + newTypeAliasState : Token.UpperCase -> List Token.LowerCase -> TypeExpressionNestingLeaf () () () -> Result Error State + newTypeAliasState aliasName typeArgs expr = + State_BlockTypeAlias (BlockTypeAlias_Completish aliasName typeArgs expr) + |> Ok + + doneParsingTypeAlias : Token.UpperCase -> List Token.LowerCase -> TypeExpression -> Result Error ParseSuccess + doneParsingTypeAlias aliasName typeArgs expr = + case typeExpressionToConcreteType expr of + Ok concreteType -> + { ty = aliasName + , genericArgs = typeArgs + , expr = concreteType + } + |> TypeAlias + |> ParseSuccess_Complete + |> Ok + + Err (ToConcreteTypeError_TooManyTupleArgs a b c d e) -> + Error_TooManyTupleArgs a b c d e + |> Err + + newExpressionState : Located Token.LowerCase -> List (Located Token.LowerCase) -> ExpressionNestingLeaf -> Result Error State + newExpressionState name args expr = + State_BlockValueDeclaration + (BlockValueDeclaration_Completish + { name = name + , args = args + , partialExpr = expr + } + ) + |> Ok + + doneParsingExpr : Located Token.LowerCase -> List (Located Token.LowerCase) -> LocatedExpr -> ParseSuccess + doneParsingExpr name args expr = + { name = name + , args = args + , valueExpr__ = expr + } + |> ValueDeclaration + |> ParseSuccess_Complete + + region = + Located.getRegion item + in + case Located.unwrap item of + Lexer.Invalid _ -> + Err (Error_InvalidToken Expecting_Unknown) + + Lexer.Newlines _ 0 -> + case state of + State_Error_Recovery -> + State_BlockStart + |> ParseSuccess_NewState + |> Ok + + State_BlockStart -> + State_BlockStart + |> ParseSuccess_NewState + |> Ok + + State_BlockFirstItem BlockFirstItem_Type -> + Error_PartwayThroughBlock + |> Err + + State_BlockFirstItem BlockFirstItem_Module -> + Error_PartwayThroughBlock + |> Err + + State_BlockValueDeclaration (BlockValueDeclaration_Named _) -> + Error_PartwayThroughBlock + |> Err + + State_BlockValueDeclaration (BlockValueDeclaration_NamedAssigns _) -> + Error_PartwayThroughBlock + |> Err + + State_BlockValueDeclaration (BlockValueDeclaration_Completish { name, args, partialExpr }) -> + case partialExpr of + ExpressionNestingLeaf_Operator { rhs, lhs, op, parent } -> + case rhs of + Just rhs_ -> + collapseOperators { op = op, lhs = lhs, parent = parent } rhs_ + |> doneParsingExpr name args + |> Ok + + Nothing -> + Error_PartwayThroughBlock + |> Err + + ExpressionTypeExpressionNestingLeaf_Expr expr -> + doneParsingExpr name args expr + |> Ok + + State_BlockTypeAlias BlockTypeAlias_Keywords -> + Error_PartwayThroughBlock + |> Err + + State_BlockTypeAlias (BlockTypeAlias_Named _ _) -> + Error_PartwayThroughBlock + |> Err + + State_BlockTypeAlias (BlockTypeAlias_NamedAssigns _ _) -> + Error_PartwayThroughBlock + |> Err + + State_BlockTypeAlias (BlockTypeAlias_Completish name typeArgs exprSoFar) -> + case collapseFunction exprSoFar of + TypeExpressionNestingLeaf_Expr () expr -> + doneParsingTypeAlias name typeArgs expr + + _ -> + Error_PartwayThroughBlock + |> Err + + State_BlockCustomType (BlockCustomType_Named _ _) -> + Error_PartwayThroughBlock + |> Err + + State_BlockCustomType (BlockCustomType_NamedAssigns _ _) -> + Debug.todo "BlockCustomType_NamedAssigns" + + Lexer.Newlines _ _ -> + Ok ParseSuccess_Skip + + Lexer.Ignorable _ -> + Ok ParseSuccess_Skip + + Lexer.Token token -> + Result.map + ParseSuccess_NewState + (case state of + State_Error_Recovery -> + State_Error_Recovery + |> Ok + + State_BlockStart -> + parseBlockStart region token + + State_BlockFirstItem BlockFirstItem_Type -> + parseTypeBlock token + + State_BlockFirstItem BlockFirstItem_Module -> + Debug.todo "BlockFirstItem_Module" + + State_BlockValueDeclaration (BlockValueDeclaration_Named { name, args }) -> + parseLowercaseArgsOrAssignment token + |> Result.map + (\res -> + case res of + ArgOrAssign_Arg newArg -> + State_BlockValueDeclaration + (BlockValueDeclaration_Named + { name = name + , args = Located.located region newArg |> pushOnto args + } + ) + + ArgOrAssign_Assign -> + State_BlockValueDeclaration + (BlockValueDeclaration_NamedAssigns + { name = name + , args = args |> toList (\x -> x) + } + ) + ) + + State_BlockValueDeclaration (BlockValueDeclaration_NamedAssigns { name, args }) -> + parserExpressionFromEmpty (Located.located region token) + |> Result.andThen (newExpressionState name args) + + State_BlockValueDeclaration (BlockValueDeclaration_Completish { name, args, partialExpr }) -> + parserExpression partialExpr (Located.located region token) + |> Result.andThen (newExpressionState name args) + + State_BlockTypeAlias BlockTypeAlias_Keywords -> + parseTypeAliasName token + + State_BlockTypeAlias (BlockTypeAlias_Named name typeArgs) -> + parseLowercaseArgsOrAssignment token + |> Result.map + (\res -> + case res of + ArgOrAssign_Arg newTypeArg -> + State_BlockTypeAlias + (BlockTypeAlias_Named + name + (newTypeArg |> pushOnto typeArgs) + ) + + ArgOrAssign_Assign -> + State_BlockTypeAlias + (BlockTypeAlias_NamedAssigns + name + (typeArgs |> toList (\x -> x)) + ) + ) + + State_BlockTypeAlias (BlockTypeAlias_NamedAssigns name typeArgs) -> + parserTypeExprFromEmpty (Located.located region token) + |> Result.andThen (newTypeAliasState name typeArgs) + + State_BlockTypeAlias (BlockTypeAlias_Completish name typeArgs exprSoFar) -> + parserTypeExpr exprSoFar (Located.located region token) + |> Result.andThen (newTypeAliasState name typeArgs) + + State_BlockCustomType (BlockCustomType_Named name typeArgs) -> + parseLowercaseArgsOrAssignment token + |> Result.map + (\res -> + case res of + ArgOrAssign_Arg newTypeArg -> + State_BlockCustomType + (BlockCustomType_Named + name + (newTypeArg |> pushOnto typeArgs) + ) + + ArgOrAssign_Assign -> + State_BlockCustomType + (BlockCustomType_NamedAssigns + name + (typeArgs |> toList (\x -> x)) + ) + ) + + State_BlockCustomType (BlockCustomType_NamedAssigns _ _) -> + Debug.todo "BlockCustomType_NamedAssigns" + ) + + +{-| + + +### Panics + +If the LexItem is a `Newlines` with indentation or is `Whitespace`. + +-} +parseBlockStart : Located.Region -> Lexer.LexToken -> Result Error State +parseBlockStart region item = + let + withCorrectLocation = + Located.located region + in + case item of + Lexer.Keyword Token.Type -> + Ok (State_BlockFirstItem BlockFirstItem_Type) + + Lexer.Keyword Token.Module -> + Ok (State_BlockFirstItem BlockFirstItem_Module) + + Lexer.Keyword other -> + Err (Error_MisplacedKeyword other) + + Lexer.Identifier ({ qualifiers, name } as identifier) -> + if qualifiers /= [] then + Err (Error_BlockStartsWithQualifiedName identifier) + + else + case name of + Token.TokenLowerCase lower -> + Ok + (State_BlockValueDeclaration + (BlockValueDeclaration_Named + { name = withCorrectLocation lower + , args = empty + } + ) + ) + + Token.TokenUpperCase upperCase -> + Error_BlockStartsWithUpperCase upperCase + |> Err + + _ -> + Err (Error_InvalidToken Expecting_Block) + + +parseTypeBlock : Lexer.LexToken -> Result Error State +parseTypeBlock item = + case item of + Lexer.Keyword Token.Alias -> + State_BlockTypeAlias BlockTypeAlias_Keywords + |> Ok + + Lexer.Keyword other -> + Error_MisplacedKeyword other + |> Err + + Lexer.Identifier ({ qualifiers, name } as identifier) -> + if qualifiers /= [] then + Err (Error_BlockStartsWithQualifiedName identifier) + + else + case name of + Token.TokenLowerCase lower -> + Error_LowerCasedTypename + { qualifiers = qualifiers + , name = lower + } + |> Err + + Token.TokenUpperCase upper -> + State_BlockCustomType (BlockCustomType_Named upper empty) + |> Ok + + _ -> + -- TODO(harry) indicate that we could also be expecting the `alias` + -- keyword. + Error_InvalidToken Expecting_TypeName + |> Err + + +parseTypeAliasName : Lexer.LexToken -> Result Error State +parseTypeAliasName item = + case item of + Lexer.Keyword other -> + Error_MisplacedKeyword other + |> Err + + Lexer.Identifier ({ qualifiers, name } as identifier) -> + if qualifiers /= [] then + Err (Error_BlockStartsWithQualifiedName identifier) + + else + case name of + Token.TokenLowerCase lower -> + Error_LowerCasedTypename + { qualifiers = qualifiers + , name = lower + } + |> Err + + Token.TokenUpperCase upper -> + State_BlockTypeAlias (BlockTypeAlias_Named upper empty) + |> Ok + + _ -> + Error_InvalidToken Expecting_TypeName + |> Err + + +type ArgOrAssign + = ArgOrAssign_Arg Token.LowerCase + | ArgOrAssign_Assign + + +parseLowercaseArgsOrAssignment : Lexer.LexToken -> Result Error ArgOrAssign +parseLowercaseArgsOrAssignment item = + case item of + Lexer.Keyword kw -> + Error_MisplacedKeyword kw + |> Err + + Lexer.Identifier ({ qualifiers, name } as identifier) -> + if qualifiers /= [] then + Err (Error_QualifiedArgName identifier) + + else + case name of + Token.TokenLowerCase lower -> + lower + |> ArgOrAssign_Arg + |> Ok + + Token.TokenUpperCase upper -> + Error_UpperCaseArgName { qualifiers = qualifiers, name = upper } + |> Err + + Lexer.Sigil Lexer.Assign -> + ArgOrAssign_Assign + |> Ok + + _ -> + Error_InvalidToken (Expecting_Sigil Lexer.Assign) + |> Err + + +parserTypeExprFromEmpty : Located Lexer.LexToken -> Result Error (TypeExpressionNestingLeaf () () ()) +parserTypeExprFromEmpty item = + case Located.unwrap item of + Lexer.Identifier { qualifiers, name } -> + case name of + Token.TokenLowerCase lower -> + if qualifiers == [] then + TypeExpression_GenericType lower + |> TypeExpressionNestingLeaf_Expr () + |> Ok + + else + Error_LowerCasedTypename + { qualifiers = qualifiers + , name = lower + } + |> Err + + Token.TokenUpperCase upper -> + TypeExpressionNestingLeaf_TypeWithArgs + { qualifiers = qualifiers + , name = upper + , args = empty + , parent = Nothing + , phantom = () + } + |> Ok + + Lexer.Sigil (Lexer.Bracket Lexer.Round Lexer.Open) -> + TypeExpressionNestingLeaf_Bracket + { firstExpressions = empty + , trailingExpression = Nothing + , parent = Nothing + } + |> Ok + + Lexer.Sigil (Lexer.Bracket role Lexer.Close) -> + Error_UnmatchedBracket role Lexer.Close + |> Err + + Lexer.Sigil (Lexer.Bracket Lexer.Curly Lexer.Open) -> + TypeExpressionNestingLeaf_PartialRecord + { firstEntries = empty + , lastEntry = LastEntryOfRecord_Empty + , parent = Nothing + } + |> Ok + + Lexer.Sigil Lexer.Colon -> + Error_InvalidToken Expecting_Unknown + |> Err + + Lexer.Sigil Lexer.Comma -> + Error_InvalidToken Expecting_Unknown + |> Err + + Lexer.Sigil Lexer.ThinArrow -> + Error_InvalidToken Expecting_Unknown + |> Err + + _ -> + Error_InvalidToken Expecting_Unknown + |> Err + + +parserTypeExpr : + TypeExpressionNestingLeaf () () () + -> Located Lexer.LexToken + -> Result Error (TypeExpressionNestingLeaf () () ()) +parserTypeExpr prevExpr item = + case Located.unwrap item of + Lexer.Identifier ident -> + appendPossiblyQualifiedTokenTo prevExpr ident + + Lexer.Sigil (Lexer.Bracket Lexer.Round Lexer.Open) -> + addNewNestingContextTo prevExpr + (TypeExpressionNestingLeaf_Bracket + { firstExpressions = empty + , trailingExpression = Nothing + , parent = Nothing + } + ) + + Lexer.Sigil (Lexer.Bracket Lexer.Round Lexer.Close) -> + case collapseFunction prevExpr of + TypeExpressionNestingLeaf_Expr () _ -> + Error_UnmatchedBracket Lexer.Round Lexer.Close + |> Err + + TypeExpressionNestingLeaf_TypeWithArgs { name, args, phantom } -> + never phantom + + TypeExpressionNestingLeaf_Bracket { firstExpressions, trailingExpression, parent } -> + closeBracket firstExpressions trailingExpression parent + + TypeExpressionNestingLeaf_PartialRecord _ -> + Error_WrongClosingBracket + { expecting = Lexer.Curly + , found = Lexer.Round + } + |> Err + + TypeExpressionNestingLeaf_Function { output } -> + case output of + Nothing -> + Error_MissingFunctionReturnType + |> Err + + Just ( _, phantom ) -> + never phantom + + Lexer.Sigil (Lexer.Bracket Lexer.Curly Lexer.Open) -> + addNewNestingContextTo prevExpr + (TypeExpressionNestingLeaf_PartialRecord + { firstEntries = empty + , lastEntry = LastEntryOfRecord_Empty + , parent = Nothing + } + ) + + Lexer.Sigil Lexer.Colon -> + appendColonTo prevExpr + + Lexer.Sigil Lexer.Comma -> + appendCommaTo prevExpr + + Lexer.Sigil (Lexer.Bracket Lexer.Curly Lexer.Close) -> + case collapseFunction prevExpr of + TypeExpressionNestingLeaf_Expr () _ -> + Error_UnmatchedBracket Lexer.Curly Lexer.Close + |> Err + + TypeExpressionNestingLeaf_TypeWithArgs { name, args, phantom } -> + never phantom + + TypeExpressionNestingLeaf_Bracket _ -> + Error_WrongClosingBracket + { expecting = Lexer.Round + , found = Lexer.Curly + } + |> Err + + TypeExpressionNestingLeaf_PartialRecord pr -> + closeRecord pr + + TypeExpressionNestingLeaf_Function { output } -> + case output of + Nothing -> + Error_MissingFunctionReturnType + |> Err + + Just ( _, phantom ) -> + never phantom + + Lexer.Sigil Lexer.ThinArrow -> + case collapseTypeWithArgs prevExpr of + TypeExpressionNestingLeaf_Expr () expr -> + TypeExpressionNestingLeaf_Function + { firstInput = expr + , otherInputs = empty + , output = Nothing + , parent = Nothing + } + |> Ok + + TypeExpressionNestingLeaf_TypeWithArgs { phantom } -> + never phantom + + TypeExpressionNestingLeaf_Function { firstInput, otherInputs, output, parent } -> + case output of + Nothing -> + Error_InvalidToken Expecting_Unknown + |> Err + + Just output_ -> + TypeExpressionNestingLeaf_Function + { firstInput = firstInput + , otherInputs = output_ |> Tuple.first |> pushOnto otherInputs + , output = Nothing + , parent = parent + } + |> Ok + + TypeExpressionNestingLeaf_Bracket { firstExpressions, trailingExpression, parent } -> + case trailingExpression of + Just trailingExpression_ -> + TypeExpressionNestingLeaf_Function + { firstInput = trailingExpression_ + , otherInputs = empty + , output = Nothing + , parent = + { expressions = firstExpressions + , parent = parent + } + |> NestingParentType_Bracket + |> Just + } + |> Ok + + Nothing -> + Error_InvalidToken Expecting_Unknown + |> Err + + TypeExpressionNestingLeaf_PartialRecord { firstEntries, lastEntry, parent } -> + case lastEntry of + LastEntryOfRecord_Empty -> + Error_InvalidToken Expecting_Identifier + |> Err + + LastEntryOfRecord_Key _ -> + Error_InvalidToken (Expecting_Sigil Lexer.Colon) + |> Err + + LastEntryOfRecord_KeyColon _ -> + Error_InvalidToken Expecting_Unknown + |> Err + + LastEntryOfRecord_KeyValue key value -> + TypeExpressionNestingLeaf_Function + { firstInput = value + , otherInputs = empty + , output = Nothing + , parent = + { firstEntries = firstEntries + , lastEntryName = key + , parent = parent + } + |> NestingParentType_PartialRecord + |> Just + } + |> Ok + + _ -> + Error_InvalidToken Expecting_Unknown + |> Err + + +parserExpressionFromEmpty : Located Lexer.LexToken -> Result Error ExpressionNestingLeaf +parserExpressionFromEmpty item = + let + withCorrectLocation x = + Located.map (\_ -> x) item + in + case Located.unwrap item of + Lexer.NumericLiteral str -> + case String.toInt str of + Just i -> + Frontend.Int i + |> withCorrectLocation + |> ExpressionTypeExpressionNestingLeaf_Expr + |> Ok + + Nothing -> + Error_InvalidNumericLiteral str + |> Err + + _ -> + Error_InvalidToken Expecting_Unknown + |> Err + + +parserExpression : + ExpressionNestingLeaf + -> Located Lexer.LexToken + -> Result Error ExpressionNestingLeaf +parserExpression prevExpr item = + let + withCorrectLocation x = + Located.map (\_ -> x) item + in + case Located.unwrap item of + Lexer.Sigil (Lexer.Operator op) -> + appendOperatorTo prevExpr (withCorrectLocation op) + + Lexer.NumericLiteral str -> + case String.toInt str of + Just i -> + Frontend.Int i + |> withCorrectLocation + |> appendValueExprTo prevExpr + + Nothing -> + Error_InvalidNumericLiteral str + |> Err + + _ -> + Error_InvalidToken Expecting_Unknown + |> Err + + + +-- HELPERS + + +{-| Takes the first `TypeExpressionNestingLeaf () () ()`, converts it into a `TypeExpressionNestingParent` and +overwrites the `parent` field of the second `TypeExpressionNestingLeaf () () Never` with the newly created +`TypeExpressionNestingParent`. +-} +addNewNestingContextTo : TypeExpressionNestingLeaf () () () -> TypeExpressionNestingLeaf () () Never -> Result Error (TypeExpressionNestingLeaf () () ()) +addNewNestingContextTo oldLeaf newLeaf = + let + processParent mParent = + case newLeaf of + TypeExpressionNestingLeaf_Bracket record -> + TypeExpressionNestingLeaf_Bracket { record | parent = mParent } + + TypeExpressionNestingLeaf_PartialRecord partialRecord -> + TypeExpressionNestingLeaf_PartialRecord { partialRecord | parent = mParent } + + TypeExpressionNestingLeaf_TypeWithArgs record -> + TypeExpressionNestingLeaf_TypeWithArgs { record | parent = mParent } + + TypeExpressionNestingLeaf_Function record -> + TypeExpressionNestingLeaf_Function { record | parent = mParent } + + TypeExpressionNestingLeaf_Expr notAnExpression _ -> + never notAnExpression + in + case oldLeaf of + TypeExpressionNestingLeaf_Expr () expr -> + -- Cannot nest unless there is a trailing comma! + Error_TypeDoesNotTakeArgs expr (processParent Nothing) |> Err + + TypeExpressionNestingLeaf_Bracket { firstExpressions, trailingExpression, parent } -> + case trailingExpression of + Just lastType -> + -- Cannot nest unless there is a trailing comma! + Error_TypeDoesNotTakeArgs lastType (processParent Nothing) |> Err + + Nothing -> + { expressions = firstExpressions + , parent = parent + } + |> NestingParentType_Bracket + |> Just + |> processParent + |> Ok + + TypeExpressionNestingLeaf_PartialRecord { firstEntries, lastEntry, parent } -> + case lastEntry of + LastEntryOfRecord_Empty -> + Error_ExpectedKeyWhilstParsingRecord + |> Err + + LastEntryOfRecord_Key _ -> + Error_ExpectedColonWhilstParsingRecord + |> Err + + LastEntryOfRecord_KeyColon key -> + { firstEntries = firstEntries + , lastEntryName = key + , parent = parent + } + |> NestingParentType_PartialRecord + |> Just + |> processParent + |> Ok + + LastEntryOfRecord_KeyValue _ lastValueType -> + Error_TypeDoesNotTakeArgs lastValueType (processParent Nothing) |> Err + + TypeExpressionNestingLeaf_TypeWithArgs details -> + NestingParentType_TypeWithArgs details + |> Just + |> processParent + |> Ok + + TypeExpressionNestingLeaf_Function { firstInput, otherInputs, output, parent } -> + case output of + Nothing -> + NestingParentType_Function + { firstInput = firstInput + , otherInputs = otherInputs + , parent = parent + } + |> Just + |> processParent + |> Ok + + Just ( te, () ) -> + Error_TypeDoesNotTakeArgs te (processParent Nothing) |> Err + + +appendTypeExprTo : Maybe TypeExpressionNestingParent -> TypeExpression -> TypeExpressionNestingLeaf () () () +appendTypeExprTo toMakeIntoLeaf expr = + case toMakeIntoLeaf of + Just (NestingParentType_PartialRecord { firstEntries, lastEntryName, parent }) -> + TypeExpressionNestingLeaf_PartialRecord + { firstEntries = firstEntries + , lastEntry = LastEntryOfRecord_KeyValue lastEntryName expr + , parent = parent + } + + Just (NestingParentType_Bracket { expressions, parent }) -> + TypeExpressionNestingLeaf_Bracket + { firstExpressions = expressions + , trailingExpression = Just expr + , parent = parent + } + + Just (NestingParentType_TypeWithArgs { qualifiers, name, args, parent }) -> + TypeExpressionNestingLeaf_TypeWithArgs + { qualifiers = qualifiers + , name = name + , args = expr |> pushOnto args + , parent = parent + , phantom = () + } + + Just (NestingParentType_Function { firstInput, otherInputs, parent }) -> + TypeExpressionNestingLeaf_Function + { firstInput = firstInput + , otherInputs = otherInputs + , output = Just ( expr, () ) + , parent = parent + } + + Nothing -> + TypeExpressionNestingLeaf_Expr () expr + + +appendPossiblyQualifiedTokenTo : + TypeExpressionNestingLeaf () () () + -> + { qualifiers : List Token.UpperCase + , name : Token.Token + } + -> Result Error (TypeExpressionNestingLeaf () () ()) +appendPossiblyQualifiedTokenTo currentLeaf token = + case token.name of + Token.TokenLowerCase lower -> + let + lowerCaseTypeError = + Error_LowerCasedTypename + { qualifiers = token.qualifiers + , name = lower + } + |> Err + + genericType = + if token.qualifiers == [] then + TypeExpression_GenericType lower + |> Ok + + else + lowerCaseTypeError + in + case currentLeaf of + TypeExpressionNestingLeaf_Bracket { firstExpressions, trailingExpression, parent } -> + case trailingExpression of + Nothing -> + genericType + |> Result.map + (\ty -> + TypeExpressionNestingLeaf_Bracket + { firstExpressions = firstExpressions + , trailingExpression = Just ty + , parent = parent + } + ) + + Just existingRoot -> + genericType + |> Result.andThen + (TypeExpressionNestingLeaf_Expr () >> Error_TypeDoesNotTakeArgs existingRoot >> Err) + + TypeExpressionNestingLeaf_Expr () expr -> + genericType + |> Result.andThen + (TypeExpressionNestingLeaf_Expr () >> Error_TypeDoesNotTakeArgs expr >> Err) + + TypeExpressionNestingLeaf_PartialRecord pr -> + case pr.lastEntry of + LastEntryOfRecord_Empty -> + if token.qualifiers == [] then + TypeExpressionNestingLeaf_PartialRecord + { firstEntries = pr.firstEntries + , lastEntry = LastEntryOfRecord_Key lower + , parent = pr.parent + } + |> Ok + + else + Error_QualifiedRecordKey + { qualifiers = token.qualifiers + , name = token.name + } + |> Err + + LastEntryOfRecord_Key _ -> + Error_ExpectedColonWhilstParsingRecord + |> Err + + LastEntryOfRecord_KeyColon key -> + genericType + |> Result.map + (appendTypeExprTo + ({ firstEntries = pr.firstEntries + , lastEntryName = key + , parent = pr.parent + } + |> NestingParentType_PartialRecord + |> Just + ) + ) + + LastEntryOfRecord_KeyValue _ lastValueType -> + genericType + |> Result.andThen + (\gt -> + Error_TypeDoesNotTakeArgs lastValueType (TypeExpressionNestingLeaf_Expr () gt) + |> Err + ) + + TypeExpressionNestingLeaf_TypeWithArgs details -> + genericType + |> Result.map (appendTypeExprTo (Just (NestingParentType_TypeWithArgs details))) + + TypeExpressionNestingLeaf_Function { firstInput, otherInputs, output, parent } -> + genericType + |> Result.andThen + (\gt -> + case output of + Nothing -> + gt + |> appendTypeExprTo + ({ firstInput = firstInput + , otherInputs = otherInputs + , parent = parent + } + |> NestingParentType_Function + |> Just + ) + |> Ok + + Just ( te, () ) -> + gt + |> appendTypeExprTo Nothing + |> Error_TypeDoesNotTakeArgs te + |> Err + ) + + Token.TokenUpperCase upper -> + let + record = + { qualifiers = token.qualifiers + , name = upper + , args = empty + , parent = Nothing + , phantom = () + } + + ty = + TypeExpressionNestingLeaf_TypeWithArgs record + in + case currentLeaf of + -- We are within a nested bracket. + TypeExpressionNestingLeaf_Bracket { firstExpressions, trailingExpression } -> + case trailingExpression of + Nothing -> + addNewNestingContextTo currentLeaf ty + + Just existingRoot -> + Error_TypeDoesNotTakeArgs existingRoot ty + |> Err + + TypeExpressionNestingLeaf_Expr () expr -> + Error_TypeDoesNotTakeArgs expr ty + |> Err + + TypeExpressionNestingLeaf_PartialRecord pr -> + case pr.lastEntry of + LastEntryOfRecord_Empty -> + if token.qualifiers /= [] then + Error_QualifiedRecordKey + { qualifiers = token.qualifiers + , name = token.name + } + |> Err + + else + Error_UpperCaseRecordKey upper + |> Err + + _ -> + addNewNestingContextTo + currentLeaf + (TypeExpressionNestingLeaf_TypeWithArgs + { qualifiers = token.qualifiers + , name = upper + , args = empty + , parent = Nothing + , phantom = () + } + ) + + TypeExpressionNestingLeaf_TypeWithArgs { name, args, parent } -> + TypeExpressionNestingLeaf_TypeWithArgs + { qualifiers = token.qualifiers + , name = name + , args = + { qualifiers = token.qualifiers + , name = upper + , args = empty + } + |> TypeExpression_NamedType + |> pushOnto args + , parent = parent + , phantom = () + } + |> Ok + + TypeExpressionNestingLeaf_Function { firstInput, otherInputs, parent, output } -> + case output of + Nothing -> + { record + | parent = + Just + (NestingParentType_Function + { firstInput = firstInput + , otherInputs = otherInputs + , parent = parent + } + ) + } + |> TypeExpressionNestingLeaf_TypeWithArgs + |> Ok + + Just ( te, () ) -> + Error_TypeDoesNotTakeArgs te ty + |> Err + + +appendCommaTo : TypeExpressionNestingLeaf () () () -> Result Error (TypeExpressionNestingLeaf () () ()) +appendCommaTo prevExpr = + case collapseFunction prevExpr of + TypeExpressionNestingLeaf_PartialRecord { firstEntries, lastEntry, parent } -> + case lastEntry of + LastEntryOfRecord_KeyValue key value -> + TypeExpressionNestingLeaf_PartialRecord + { firstEntries = ( key, value ) |> pushOnto firstEntries + , lastEntry = LastEntryOfRecord_Empty + , parent = parent + } + |> Ok + + _ -> + Error_InvalidToken Expecting_Unknown + |> Err + + TypeExpressionNestingLeaf_Bracket { firstExpressions, trailingExpression, parent } -> + case trailingExpression of + Just trailingExpression_ -> + TypeExpressionNestingLeaf_Bracket + { firstExpressions = trailingExpression_ |> pushOnto firstExpressions + , trailingExpression = Nothing + , parent = parent + } + |> Ok + + Nothing -> + Error_InvalidToken Expecting_Unknown + |> Err + + _ -> + Error_InvalidToken Expecting_Unknown + |> Err + + +appendColonTo : TypeExpressionNestingLeaf () () () -> Result Error (TypeExpressionNestingLeaf () () ()) +appendColonTo prevExpr = + case prevExpr of + TypeExpressionNestingLeaf_PartialRecord { firstEntries, lastEntry, parent } -> + case lastEntry of + LastEntryOfRecord_Key key -> + TypeExpressionNestingLeaf_PartialRecord + { firstEntries = firstEntries + , lastEntry = LastEntryOfRecord_KeyColon key + , parent = parent + } + |> Ok + + _ -> + Error_InvalidToken Expecting_Unknown + |> Err + + _ -> + Error_InvalidToken Expecting_Unknown + |> Err + + +closeBracket : + Stack TypeExpression + -> Maybe TypeExpression + -> Maybe TypeExpressionNestingParent + -> Result Error (TypeExpressionNestingLeaf () () ()) +closeBracket argStack mLastExpression mParent = + let + rexpr = + if argStack /= empty && mLastExpression == Nothing then + -- We have a trailing comma! + Error_UnmatchedBracket Lexer.Round Lexer.Close + |> Err + + else + let + fullArgsList = + (case mLastExpression of + Just expr -> + expr |> pushOnto argStack + + Nothing -> + argStack + ) + |> toList (\x -> x) + in + case fullArgsList of + [] -> + TypeExpression_Unit + |> Ok + + first :: [] -> + TypeExpression_Bracketed first + |> Ok + + first :: second :: rest -> + TypeExpression_Tuple first second rest + |> Ok + in + rexpr + |> Result.map (appendTypeExprTo mParent) + + +closeRecord : PartialRecord -> Result Error (TypeExpressionNestingLeaf () () ()) +closeRecord { firstEntries, lastEntry, parent } = + let + fromRecordEntries recordEntries = + appendTypeExprTo parent (TypeExpression_Record recordEntries) + in + case lastEntry of + LastEntryOfRecord_KeyValue key value -> + ( key, value ) + |> pushOnto firstEntries + |> toList (\x -> x) + |> fromRecordEntries + |> Ok + + LastEntryOfRecord_Empty -> + if firstEntries == empty then + [] + |> fromRecordEntries + |> Ok + + else + Error_InvalidToken Expecting_Unknown + |> Err + + _ -> + Error_InvalidToken Expecting_Unknown + |> Err + + + +-- Value expression helpers + + +appendOperatorTo : ExpressionNestingLeaf -> Located Operator -> Result Error ExpressionNestingLeaf +appendOperatorTo leaf appendingOp = + case leaf of + ExpressionNestingLeaf_Operator oldLeaf -> + case oldLeaf.rhs of + Nothing -> + Error_InvalidToken Expecting_Unknown + |> Err + + Just parentRhs -> + let + prevPrec = + Operator.getPrecedence (Located.unwrap oldLeaf.op) + + appendingPrec = + Operator.getPrecedence (Located.unwrap appendingOp) + in + case Operator.comparePrec { lhs = prevPrec, rhs = appendingPrec } of + EQ -> + case Operator.getAssociativity prevPrec of + Operator.ConflictsWithOthers -> + Debug.todo "" + + Operator.ConflictsWithSelf -> + Error_ConflictingOperators oldLeaf.op appendingOp + |> Err + + Operator.RightToLeft -> + ExpressionNestingLeaf_Operator + { op = appendingOp + , lhs = parentRhs + , rhs = Nothing + , parent = + Just + (ExpressionNestingParent_Operator + { op = oldLeaf.op + , lhs = oldLeaf.lhs + , parent = oldLeaf.parent + } + ) + } + |> Ok + + Operator.LeftToRight -> + ExpressionNestingLeaf_Operator + { op = appendingOp + , lhs = Located.merge (Frontend.Operator oldLeaf.op) oldLeaf.lhs parentRhs + , rhs = Nothing + , parent = oldLeaf.parent + } + |> Ok + + GT -> + -- Prev operator has higher precedence than the appending operator. We bundle the previous + -- nesting context into the child's lhs. + ExpressionNestingLeaf_Operator + { op = appendingOp + , lhs = + Located.merge + (\op args -> + let + ( lhs, rhs ) = + Located.unwrap args + in + Frontend.Operator op lhs rhs + ) + oldLeaf.op + (Located.merge Tuple.pair oldLeaf.lhs parentRhs) + , rhs = Nothing + , parent = oldLeaf.parent + } + |> Ok + + LT -> + -- Prev operator has lower precedence than the appending operator. We steal the previous + -- operator's rhs and start a new layer of nesting with the previous rhs as our new lhs. + ExpressionNestingLeaf_Operator + { op = appendingOp + , lhs = parentRhs + , rhs = Nothing + , parent = + Just + (ExpressionNestingParent_Operator + { op = oldLeaf.op + , lhs = oldLeaf.lhs + , parent = oldLeaf.parent + } + ) + } + |> Ok + + ExpressionTypeExpressionNestingLeaf_Expr locatedexpr -> + ExpressionNestingLeaf_Operator + { op = appendingOp + , lhs = locatedexpr + , parent = Nothing + , rhs = Nothing + } + |> Ok + + +appendValueExprTo : ExpressionNestingLeaf -> Frontend.LocatedExpr -> Result Error ExpressionNestingLeaf +appendValueExprTo leaf appendingExpr = + case leaf of + ExpressionNestingLeaf_Operator oldLeaf -> + case oldLeaf.rhs of + Nothing -> + ExpressionNestingLeaf_Operator + { op = oldLeaf.op + , lhs = oldLeaf.lhs + , rhs = Just appendingExpr + , parent = oldLeaf.parent + } + |> Ok + + Just parentRhs -> + Error_ValueDoesNotTakeArgs parentRhs + |> Err + + ExpressionTypeExpressionNestingLeaf_Expr locatedExpr -> + Error_ValueDoesNotTakeArgs locatedExpr + |> Err + + +collapseOperators : + { op : Located Operator + , lhs : Frontend.LocatedExpr + , parent : Maybe ExpressionNestingParent + } + -> Frontend.LocatedExpr + -> Frontend.LocatedExpr +collapseOperators opData rhs = + let + expr = + Located.merge (Frontend.Operator opData.op) opData.lhs rhs + in + case opData.parent of + Just (ExpressionNestingParent_Operator parentData) -> + collapseOperators parentData expr + + Nothing -> + expr + + +blockFromState : State -> Maybe (Result Error Block) +blockFromState state = + case state of + State_Error_Recovery -> + Nothing + + State_BlockStart -> + Nothing + + State_BlockFirstItem _ -> + Debug.todo "handle incomplete block" + + State_BlockTypeAlias BlockTypeAlias_Keywords -> + Error_PartwayThroughBlock + |> Err + |> Just + + State_BlockTypeAlias (BlockTypeAlias_Named _ _) -> + Error_PartwayThroughBlock + |> Err + |> Just + + State_BlockTypeAlias (BlockTypeAlias_NamedAssigns _ _) -> + Error_PartwayThroughBlock + |> Err + |> Just + + State_BlockTypeAlias (BlockTypeAlias_Completish aliasName typeArgs partialExpr) -> + case collapseFunction partialExpr of + TypeExpressionNestingLeaf_Expr () expr -> + typeExpressionToConcreteType expr + |> Result.map + (\conceteType -> + { ty = aliasName + , genericArgs = typeArgs + , expr = conceteType + } + |> TypeAlias + ) + |> Result.mapError (\(ToConcreteTypeError_TooManyTupleArgs a b c d e) -> Error_TooManyTupleArgs a b c d e) + |> Just + + _ -> + Error_PartwayThroughBlock + |> Err + |> Just + + State_BlockCustomType _ -> + Debug.todo "handle incomplete block" + + State_BlockValueDeclaration (BlockValueDeclaration_Named _) -> + Error_PartwayThroughValueDeclaration + |> Err + |> Just + + State_BlockValueDeclaration (BlockValueDeclaration_NamedAssigns _) -> + Error_PartwayThroughValueDeclaration + |> Err + |> Just + + State_BlockValueDeclaration (BlockValueDeclaration_Completish { name, args, partialExpr }) -> + case partialExpr of + ExpressionNestingLeaf_Operator _ -> + Error_PartwayThroughValueDeclaration + |> Err + |> Just + + ExpressionTypeExpressionNestingLeaf_Expr expr -> + { name = name + , args = args + , valueExpr__ = expr + } + |> ValueDeclaration + |> Ok + |> Just + + + +-- helper functions + + +collapseTypeWithArgs : TypeExpressionNestingLeaf () () () -> TypeExpressionNestingLeaf () Never () +collapseTypeWithArgs pte = + case pte of + TypeExpressionNestingLeaf_TypeWithArgs { qualifiers, name, args, parent } -> + let + newTypeExpr = + TypeExpression_NamedType { qualifiers = qualifiers, name = name, args = args } + in + newTypeExpr + |> appendTypeExprTo parent + |> collapseTypeWithArgs + + TypeExpressionNestingLeaf_Expr () expr -> + TypeExpressionNestingLeaf_Expr () expr + + TypeExpressionNestingLeaf_Bracket b -> + TypeExpressionNestingLeaf_Bracket b + + TypeExpressionNestingLeaf_PartialRecord pr -> + TypeExpressionNestingLeaf_PartialRecord pr + + TypeExpressionNestingLeaf_Function { firstInput, otherInputs, output, parent } -> + TypeExpressionNestingLeaf_Function + { firstInput = firstInput + , otherInputs = otherInputs + , output = output |> Maybe.map (\( o, _ ) -> ( o, () )) + , parent = parent + } + + +collapseFunction : TypeExpressionNestingLeaf () () () -> TypeExpressionNestingLeaf Never Never () +collapseFunction pte = + case collapseTypeWithArgs pte of + TypeExpressionNestingLeaf_TypeWithArgs { phantom } -> + never phantom + + TypeExpressionNestingLeaf_Expr () expr -> + TypeExpressionNestingLeaf_Expr () expr + + TypeExpressionNestingLeaf_Bracket b -> + TypeExpressionNestingLeaf_Bracket b + + TypeExpressionNestingLeaf_PartialRecord pr -> + TypeExpressionNestingLeaf_PartialRecord pr + + TypeExpressionNestingLeaf_Function { firstInput, otherInputs, output, parent } -> + case output of + Nothing -> + TypeExpressionNestingLeaf_Function + { firstInput = firstInput + , otherInputs = otherInputs + , output = Nothing + , parent = parent + } + + Just ( outputExpr, () ) -> + let + newTypeExpr = + TypeExpression_Function + { firstInput = firstInput + , otherInputs = otherInputs |> toList (\x -> x) + , output = outputExpr + } + in + appendTypeExprTo parent newTypeExpr + |> collapseFunction + + +type ToConcreteTypeError + = ToConcreteTypeError_TooManyTupleArgs + -- + (ConcreteType PossiblyQualified) + (ConcreteType PossiblyQualified) + (ConcreteType PossiblyQualified) + (ConcreteType PossiblyQualified) + (List (ConcreteType PossiblyQualified)) + + +typeExpressionToConcreteType : TypeExpression -> Result ToConcreteTypeError (ConcreteType PossiblyQualified) +typeExpressionToConcreteType pte = + case pte of + TypeExpression_NamedType { qualifiers, name, args } -> + let + (Token.UpperCase sName) = + name + + mModuleName = + if qualifiers == [] then + Nothing + + else + qualifiers + |> List.map (\(Token.UpperCase s) -> s) + |> String.join "." + |> Just + in + args + |> toList typeExpressionToConcreteType + |> collectList (\x -> x) + |> Result.map + (\goodArgs -> + { qualifiedness = Qualifiedness.PossiblyQualified mModuleName + , name = sName + , args = goodArgs + } + |> ConcreteType.UserDefinedType + ) + + TypeExpression_GenericType name -> + let + (Token.LowerCase sName) = + name + in + { qualifiedness = Qualifiedness.PossiblyQualified Nothing + , name = sName + , args = [] + } + |> ConcreteType.UserDefinedType + |> Ok + + TypeExpression_Unit -> + ConcreteType.Unit + |> Ok + + TypeExpression_Bracketed ty -> + typeExpressionToConcreteType ty + + TypeExpression_Tuple first second [] -> + Result.map2 + ConcreteType.Tuple + (typeExpressionToConcreteType first) + (typeExpressionToConcreteType second) + + TypeExpression_Tuple first second (third :: []) -> + Result.map3 + ConcreteType.Tuple3 + (typeExpressionToConcreteType first) + (typeExpressionToConcreteType second) + (typeExpressionToConcreteType third) + + TypeExpression_Tuple first second (third :: fouth :: rest) -> + Result.map5 + ToConcreteTypeError_TooManyTupleArgs + (typeExpressionToConcreteType first) + (typeExpressionToConcreteType second) + (typeExpressionToConcreteType third) + (typeExpressionToConcreteType fouth) + (rest + |> collectList typeExpressionToConcreteType + ) + |> Result.andThen Err + + TypeExpression_Record keyValues -> + keyValues + |> collectList + (\( Token.LowerCase key, value ) -> + typeExpressionToConcreteType value + |> Result.map (\concreteValue -> ( key, concreteValue )) + ) + |> Result.map + (\goodKeyValues -> + Dict.fromList goodKeyValues + |> ConcreteType.Record + ) + + TypeExpression_Function functionTypeExpr -> + Result.map3 + (\concreteFirstInput concreteOtherInputs concreteOutput -> + ConcreteType.Function + { from = concreteFirstInput + , to = + List.foldl + (\arg te -> + ConcreteType.Function + { from = arg + , to = te + } + ) + concreteOutput + concreteOtherInputs + } + ) + (typeExpressionToConcreteType functionTypeExpr.firstInput) + (functionTypeExpr.otherInputs + |> List.reverse + |> collectList typeExpressionToConcreteType + ) + (typeExpressionToConcreteType functionTypeExpr.output) + + +collectList : (a -> Result e o) -> List a -> Result e (List o) +collectList = + collectListHelp [] + + +collectListHelp : List o -> (a -> Result e o) -> List a -> Result e (List o) +collectListHelp new func old = + case old of + curr :: rest -> + case func curr of + Ok o -> + collectListHelp (o :: new) func rest + + Err e -> + Err e + + [] -> + Ok (List.reverse new) + + + +-- stacks + + +type Stack a + = Stack (List a) + + +empty : Stack a +empty = + Stack [] + + +singleton : a -> Stack a +singleton val = + Stack [ val ] + + +pushOnto : Stack a -> a -> Stack a +pushOnto (Stack ls) val = + Stack (val :: ls) + + +pop : Stack a -> Maybe ( a, Stack a ) +pop (Stack ls) = + case ls of + last :: preceding -> + Just ( last, Stack preceding ) + + [] -> + Nothing + + +toList : (a -> b) -> Stack a -> List b +toList mapper (Stack ls) = + List.foldl + (\curr prev -> mapper curr :: prev) + [] + ls diff --git a/src/Stage/Parse/Lexer.elm b/src/Stage/Parse/Lexer.elm new file mode 100644 index 00000000..e71d194b --- /dev/null +++ b/src/Stage/Parse/Lexer.elm @@ -0,0 +1,633 @@ +module Stage.Parse.Lexer exposing (..) + +import Elm.Data.Located as Located exposing (Located) +import Elm.Data.Operator as Operator exposing (Operator) +import Parser.Advanced as P exposing ((|.), (|=), Parser) +import Set +import Stage.Parse.Token as Token + + +type LexItem + = Token LexToken + | Ignorable LexIgnorable + | Invalid LexInvalid + | Newlines (List Int) Int + + +type LexToken + = Sigil LexSigil + | Identifier + { qualifiers : List Token.UpperCase + , name : Token.Token + } + | RecordAccessorLiteral Token.LowerCase + | RecordAccessorFunction Token.LowerCase + | Keyword Token.Keyword + | NumericLiteral String + | TextLiteral LexLiteralType String + + +type LexIgnorable + = Whitespace Int + | Comment LexCommentType String + + +type LexInvalid + = IdentifierWithTrailingDot + { qualifiers : List Token.UpperCase + , name : Token.UpperCase + } + | IllegalCharacter Char + | OtherInvalid String + + +type LexSigil + = Bracket BracketType BracketRole + | Assign + | Pipe + | Comma + | DoubleDot + | ThinArrow + | Backslash + | Underscore + | Colon + | Operator Operator + + +type LexCommentType + = LineComment + | MultilineComment + | DocComment + + +type BracketType + = Round + | Square + | Curly + + +type BracketRole + = Open + | Close + + +type LexLiteralType + = StringL StringType + | CharL + + +type StringType + = Single + | Triple + + +type LexProblem + = ExpectingToken + | ExpectingSigil + | ExpectingLiteralStart LexLiteralType + | ExpectingLiteralEnd LexLiteralType + | ExpectingBackslash + | ExpectingAnything + | ExpectingWhitespace + | ExpectingNewline + | ExpectingLineComment + | ExpectingNumericLiteral + | ExpectingEscape + | ExpectingKeyword + | ExpectingEnd + + +type alias Parser_ a = + Parser Never LexProblem a + + +toString : LexItem -> String +toString item = + case item of + Token (Sigil (Bracket Round Open)) -> + "(" + + Token (Sigil (Bracket Round Close)) -> + ")" + + Token (Sigil (Bracket Square Open)) -> + "[" + + Token (Sigil (Bracket Square Close)) -> + "]" + + Token (Sigil (Bracket Curly Open)) -> + "{" + + Token (Sigil (Bracket Curly Close)) -> + "}" + + Token (Sigil Assign) -> + "=" + + Token (Sigil Pipe) -> + "|" + + Token (Sigil Comma) -> + "," + + Token (Sigil DoubleDot) -> + ".." + + Token (Sigil ThinArrow) -> + "->" + + Token (Sigil Backslash) -> + "\\" + + Token (Sigil Colon) -> + ":" + + Token (Sigil Underscore) -> + "_" + + Token (Sigil (Operator op)) -> + Operator.toString op + + Token (Identifier { qualifiers, name }) -> + (List.map (\(Token.UpperCase s) -> s) qualifiers ++ [ Token.tokenToString name ]) + |> String.join "." + + Token (RecordAccessorLiteral (Token.LowerCase name)) -> + "." ++ name + + Token (RecordAccessorFunction (Token.LowerCase name)) -> + "." ++ name + + Token (Keyword k) -> + Token.keywordToString k + + Token (NumericLiteral s) -> + s + + Token (TextLiteral ty s) -> + delimiterFor ty ++ s ++ delimiterFor ty + + Ignorable (Whitespace i) -> + String.repeat i " " + + Newlines empties indentationSpaces -> + (empties + |> List.map (\spacesInEmptyLine -> "\n" ++ String.repeat spacesInEmptyLine " ") + |> String.join "" + ) + ++ "\n" + ++ String.repeat indentationSpaces " " + + Ignorable (Comment LineComment s) -> + "//" ++ s + + Ignorable (Comment MultilineComment s) -> + "{-" ++ s ++ "-}" + + Ignorable (Comment DocComment s) -> + "{-|" ++ s ++ "-}" + + Invalid (IdentifierWithTrailingDot { qualifiers, name }) -> + ((qualifiers ++ [ name ]) + |> List.map (\(Token.UpperCase s) -> s) + |> String.join "." + ) + ++ "." + + Invalid (IllegalCharacter c) -> + String.fromChar c + + Invalid (OtherInvalid s) -> + s + + +located : Parser_ p -> Parser_ (Located p) +located p = + P.succeed + (\( startRow, startCol ) value ( endRow, endCol ) -> + Located.located + { start = { row = startRow, col = startCol } + , end = { row = endRow, col = endCol } + } + value + ) + |= P.getPosition + |= p + |= P.getPosition + + +parser : Parser_ (List (Located LexItem)) +parser = + P.loop + [] + (\reversed -> + P.oneOf + [ P.oneOf + ([ -- 1. commentParser must come before sigil parser as the sigil + -- parser will try to interpret "--" as two "-" sigils. + -- 2. sigilParser must come before recordAccessorLiteralParser so that ".." is parsed as the + -- DoubleDot sigil. + commentParser + |> P.map (\( ty, commentBody ) -> Comment ty commentBody |> Ignorable) + , sigilParser + |> P.map (Sigil >> Token) + , identifierParser + , recordAccessorParser (List.head reversed |> Maybe.map Located.unwrap) + , numericLiteralParser + |> P.map (NumericLiteral >> Token) + , textLiteralParser + |> P.map + (\( ty, terminates, literalBody ) -> + if terminates then + TextLiteral ty literalBody |> Token + + else + (delimiterFor ty ++ literalBody) + |> OtherInvalid + |> Invalid + ) + , P.symbol (P.Token " " ExpectingWhitespace) + |> P.andThen (\() -> chompSpacesAndCount) + |> P.map (\count -> (count + 1) |> Whitespace |> Ignorable) + , newlinesParser + |> P.map (\( emptyLines, indentation ) -> Newlines emptyLines indentation) + , P.getChompedString (P.chompIf (\_ -> True) ExpectingAnything) + |> P.map + (\s -> + case String.toList s of + [ c ] -> + c |> IllegalCharacter |> Invalid + + _ -> + Debug.todo "ICE here" + ) + ] + |> List.map (located >> P.map (\t -> P.Loop (t :: reversed))) + ) + , P.end ExpectingEnd + |> P.map (\() -> P.Done (List.reverse reversed)) + ] + ) + + +upperCaseWord : Parser_ Token.UpperCase +upperCaseWord = + P.variable + { start = Char.isUpper + , inner = \c -> Char.isAlphaNum c || c == '_' + , reserved = Set.empty + , expecting = ExpectingToken + } + |> P.map Token.UpperCase + + +lowerCaseWord : Parser_ Token.LowerCase +lowerCaseWord = + P.variable + { start = Char.isLower + , inner = \c -> Char.isAlphaNum c || c == '_' + , reserved = Set.empty + , expecting = ExpectingToken + } + |> P.map Token.LowerCase + + +identifierParser : Parser_ LexItem +identifierParser = + let + loopHelp { reversedQualifiers, name } = + P.oneOf + [ P.succeed (\x -> x) + |. P.symbol (P.Token "." ExpectingSigil) + |= P.oneOf + [ upperCaseWord + |> P.map + (\new -> + P.Loop + { reversedQualifiers = name :: reversedQualifiers + , name = new + } + ) + , lowerCaseWord + |> P.map + (\new -> + { qualifiers = List.reverse (name :: reversedQualifiers) + , name = Token.TokenLowerCase new + } + |> Identifier + |> Token + |> P.Done + ) + , { qualifiers = List.reverse reversedQualifiers + , name = name + } + |> IdentifierWithTrailingDot + |> Invalid + |> P.Done + |> P.succeed + ] + , { qualifiers = List.reverse reversedQualifiers + , name = Token.TokenUpperCase name + } + |> Identifier + |> Token + |> P.Done + |> P.succeed + ] + in + P.oneOf + [ P.token (P.Token "module" ExpectingKeyword) + |> P.map + (\() -> + Token.Module + |> Keyword + |> Token + ) + , P.token (P.Token "type" ExpectingKeyword) + |> P.map + (\() -> + Token.Type + |> Keyword + |> Token + ) + , P.token (P.Token "alias" ExpectingKeyword) + |> P.map + (\() -> + Token.Alias + |> Keyword + |> Token + ) + , P.token (P.Token "exposing" ExpectingKeyword) + |> P.map + (\() -> + Token.Exposing + |> Keyword + |> Token + ) + , P.token (P.Token "case" ExpectingKeyword) + |> P.map + (\() -> + Token.Case + |> Keyword + |> Token + ) + , P.token (P.Token "of" ExpectingKeyword) + |> P.map + (\() -> + Token.Of + |> Keyword + |> Token + ) + , P.token (P.Token "if" ExpectingKeyword) + |> P.map + (\() -> + Token.If + |> Keyword + |> Token + ) + , P.token (P.Token "then" ExpectingKeyword) + |> P.map + (\() -> + Token.Then + |> Keyword + |> Token + ) + , P.token (P.Token "else" ExpectingKeyword) + |> P.map + (\() -> + Token.Else + |> Keyword + |> Token + ) + , upperCaseWord + |> P.andThen (\first -> P.loop { reversedQualifiers = [], name = first } loopHelp) + , lowerCaseWord + |> P.map + (\name -> + { name = Token.TokenLowerCase name + , qualifiers = [] + } + |> Identifier + |> Token + ) + ] + + +recordAccessorParser : Maybe LexItem -> Parser_ LexItem +recordAccessorParser previous = + P.succeed (\x -> x) + |. P.symbol (P.Token "." ExpectingSigil) + |= P.oneOf + [ lowerCaseWord + |> P.map + (case previous of + Just (Token (Sigil (Bracket Round Close))) -> + RecordAccessorLiteral >> Token + + Just (Token (Sigil (Bracket Curly Close))) -> + RecordAccessorLiteral >> Token + + Just (Token (Identifier _)) -> + RecordAccessorLiteral >> Token + + _ -> + RecordAccessorFunction >> Token + ) + , P.succeed ('.' |> IllegalCharacter |> Invalid) + ] + + +newlinesParser : Parser_ ( List Int, Int ) +newlinesParser = + let + eolParser = + P.oneOf + [ P.symbol (P.Token "\n\u{000D}" ExpectingNewline) + , P.symbol (P.Token "\n" ExpectingNewline) + ] + in + eolParser + |> P.andThen + (\() -> + P.loop + [] + (\reversed -> + P.succeed + (\spacesOnThisLine isThisLineEmpty -> + if isThisLineEmpty then + P.Loop (spacesOnThisLine :: reversed) + + else + P.Done ( List.reverse reversed, spacesOnThisLine ) + ) + |= chompSpacesAndCount + |= P.oneOf + [ eolParser + |> P.map (\() -> True) + , P.succeed False + ] + ) + ) + + +chompSpacesAndCount : Parser_ Int +chompSpacesAndCount = + P.chompWhile (\c -> c == ' ') + |> P.getChompedString + |> P.map String.length + + +textLiteralParser : Parser_ ( LexLiteralType, Bool, String ) +textLiteralParser = + P.oneOf + [ -- order matters! We must try parsing a triple delimited string first! + delimitedLiteral (StringL Triple) + , delimitedLiteral (StringL Single) + , delimitedLiteral CharL + ] + + +delimiterFor : LexLiteralType -> String +delimiterFor ty = + case ty of + StringL Single -> + "\"" + + StringL Triple -> + "\"\"\"" + + CharL -> + "'" + + +commentParser : Parser_ ( LexCommentType, String ) +commentParser = + P.oneOf + [ P.symbol (P.Token "--" ExpectingLineComment) + |> P.andThen (\() -> P.chompWhile (\c -> c /= '\n') |> P.getChompedString) + |> P.map (Tuple.pair LineComment) + ] + + +delimitedLiteral : LexLiteralType -> Parser_ ( LexLiteralType, Bool, String ) +delimitedLiteral ty = + let + delimiter = + delimiterFor ty + in + P.succeed + (\( body, terminates ) -> + ( ty + , terminates + , if terminates then + String.dropRight (String.length (delimiterFor ty)) body + + else + body + ) + ) + |. P.symbol (P.Token delimiter (ExpectingLiteralStart ty)) + |= P.mapChompedString + Tuple.pair + (P.loop () + (\() -> + P.oneOf + [ P.token (P.Token delimiter (ExpectingLiteralEnd ty)) + |> P.map (\() -> P.Done True) + , P.token (P.Token "\\" ExpectingEscape) + |> P.andThen + (\() -> P.chompIf (\_ -> True) ExpectingAnything) + |> P.map P.Loop + , P.chompIf (\_ -> True) ExpectingAnything + |> P.map P.Loop + , P.end ExpectingEnd + |> P.map (\() -> P.Done False) + ] + ) + ) + + +numericLiteralParser : Parser_ String +numericLiteralParser = + let + isValidNumericLiteralChar c = + Char.isAlphaNum c || c == '_' || c == '.' + in + P.getChompedString + (P.oneOf + [ P.chompIf Char.isDigit ExpectingNumericLiteral + |> P.andThen (\() -> P.chompWhile isValidNumericLiteralChar) + , P.backtrackable + (P.succeed () + |. P.chompIf (\c -> c == '-') ExpectingNumericLiteral + |. P.chompIf Char.isDigit ExpectingNumericLiteral + |. P.chompWhile isValidNumericLiteralChar + ) + ] + ) + + +sigilParser : Parser_ LexSigil +sigilParser = + P.oneOf + [ -- Two character sigils (must come first) + P.symbol (P.Token "&&" ExpectingSigil) + |> P.map (\() -> Operator Operator.And) + , P.symbol (P.Token "++" ExpectingSigil) + |> P.map (\() -> Operator Operator.Append) + , P.symbol (P.Token "::" ExpectingSigil) + |> P.map (\() -> Operator Operator.Cons) + , P.symbol (P.Token "==" ExpectingSigil) + |> P.map (\() -> Operator Operator.Equals) + , P.symbol (P.Token "||" ExpectingSigil) + |> P.map (\() -> Operator Operator.Or) + , P.symbol (P.Token ".." ExpectingSigil) + |> P.map (\() -> DoubleDot) + , P.symbol (P.Token "->" ExpectingSigil) + |> P.map (\() -> ThinArrow) + , P.symbol (P.Token ">=" ExpectingSigil) + |> P.map (\() -> Operator Operator.GreaterThanEquals) + , P.symbol (P.Token "<=" ExpectingSigil) + |> P.map (\() -> Operator Operator.LessThanEquals) + + -- Single character sigils + , P.symbol (P.Token "^" ExpectingSigil) + |> P.map (\() -> Operator Operator.Exponentiate) + , P.symbol (P.Token "\\" ExpectingSigil) + |> P.map (\() -> Backslash) + , P.symbol (P.Token "_" ExpectingSigil) + |> P.map (\() -> Underscore) + , P.symbol (P.Token "(" ExpectingSigil) + |> P.map (\() -> Bracket Round Open) + , P.symbol (P.Token ")" ExpectingSigil) + |> P.map (\() -> Bracket Round Close) + , P.symbol (P.Token ">" ExpectingSigil) + |> P.map (\() -> Operator Operator.GreaterThan) + , P.symbol (P.Token "<" ExpectingSigil) + |> P.map (\() -> Operator Operator.LessThan) + , P.symbol (P.Token "-" ExpectingSigil) + |> P.map (\() -> Operator Operator.Subtract) + , P.symbol (P.Token "+" ExpectingSigil) + |> P.map (\() -> Operator Operator.Add) + , P.symbol (P.Token "=" ExpectingSigil) + |> P.map (\() -> Assign) + , P.symbol (P.Token "/" ExpectingSigil) + |> P.map (\() -> Operator Operator.Divide) + , P.symbol (P.Token "*" ExpectingSigil) + |> P.map (\() -> Operator Operator.Multiply) + , P.symbol (P.Token "{" ExpectingSigil) + |> P.map (\() -> Bracket Curly Open) + , P.symbol (P.Token "[" ExpectingSigil) + |> P.map (\() -> Bracket Square Open) + , P.symbol (P.Token "}" ExpectingSigil) + |> P.map (\() -> Bracket Curly Close) + , P.symbol (P.Token "]" ExpectingSigil) + |> P.map (\() -> Bracket Square Close) + , P.symbol (P.Token ":" ExpectingSigil) + |> P.map (\() -> Colon) + , P.symbol (P.Token "," ExpectingSigil) + |> P.map (\() -> Comma) + , P.symbol (P.Token "|" ExpectingSigil) + |> P.map (\() -> Pipe) + ] diff --git a/src/Stage/Parse/Parser.elm b/src/Stage/Parse/Parser.elm index 3ecf3e91..8a5b9d77 100644 --- a/src/Stage/Parse/Parser.elm +++ b/src/Stage/Parse/Parser.elm @@ -38,6 +38,7 @@ import Elm.Data.Import exposing (Import) import Elm.Data.Located as Located exposing (Located) import Elm.Data.Module exposing (Module, ModuleType(..)) import Elm.Data.ModuleName exposing (ModuleName) +import Elm.Data.Operator as Operator import Elm.Data.Qualifiedness exposing (PossiblyQualified(..)) import Elm.Data.Type.Concrete as ConcreteType exposing (ConcreteType) import Elm.Data.TypeAnnotation exposing (TypeAnnotation) @@ -562,17 +563,17 @@ expr = (checkIndent (<) ExpectingIndentation |> P.andThen (\() -> P.symbol (P.Token "++" ExpectingConcatOperator)) ) - (Located.merge ListConcat) + (Located.merge3 Operator (Located.located Located.dummyRegion Operator.Append)) , PP.infixLeft 1 (checkIndent (<) ExpectingIndentation |> P.andThen (\() -> P.symbol (P.Token "+" ExpectingPlusOperator)) ) - (Located.merge Plus) + (Located.merge3 Operator (Located.located Located.dummyRegion Operator.Add)) , PP.infixRight 1 (checkIndent (<) ExpectingIndentation |> P.andThen (\() -> P.symbol (P.Token "::" ExpectingConsOperator)) ) - (Located.merge Cons) + (Located.merge (Operator (Located.located Located.dummyRegion Operator.Cons))) ] , spaces = ignorables } diff --git a/src/Stage/Parse/Pretty.elm b/src/Stage/Parse/Pretty.elm new file mode 100644 index 00000000..c294d06f --- /dev/null +++ b/src/Stage/Parse/Pretty.elm @@ -0,0 +1,377 @@ +module Stage.Parse.Pretty exposing (..) + +import Dict exposing (Dict) +import Elm.AST.Frontend as Frontend +import Elm.Data.Located as Located +import Elm.Data.Module as ModuleType exposing (ModuleType) +import Elm.Data.Operator as Operator +import Elm.Data.Qualifiedness exposing (PossiblyQualified(..)) +import Elm.Data.Type.Concrete as Concrete exposing (ConcreteType) +import Stage.Parse.Contextualize as Contextualize exposing (Block(..), BlockTypeAlias(..), State(..), TypeExpressionNestingLeaf(..)) +import Stage.Parse.Token as Token + + +type Sexpr a + = Atom a + | Many (List (Sexpr a)) + + +printWithIndentationOf : Int -> Sexpr String -> String +printWithIndentationOf indent sexpr = + case sexpr of + Atom s -> + s + + Many ls -> + case ls of + [] -> + "()" + + [ first ] -> + "( " + ++ printWithIndentationOf (indent + 1) first + ++ " )" + + [ Atom first, Atom second ] -> + "( " ++ first ++ ", " ++ second ++ " )" + + [ Many [], Atom second ] -> + "( (), " ++ second ++ " )" + + [ Atom first, Many [] ] -> + "( " ++ first ++ ", () )" + + [ Many [], Many [] ] -> + "( (), () )" + + _ -> + printManyItems True indent ls "" + ++ ")" + + +printManyItems : Bool -> Int -> List (Sexpr String) -> String -> String +printManyItems isFirst indent many soFar = + case many of + first :: rest -> + printManyItems + False + indent + rest + (soFar + ++ (if isFirst then + "( " + + else + ", " + ) + ++ printWithIndentationOf (indent + 1) first + ++ "\n" + ++ String.repeat (indent * 2) " " + ) + + [] -> + soFar + + +listWith : (a -> Sexpr String) -> List a -> Sexpr String +listWith f ls = + Many (List.map f ls) + + +dictEntriesWith : (a -> Sexpr String) -> (b -> Sexpr String) -> Dict a b -> Sexpr String +dictEntriesWith keys values d = + Dict.toList d |> listWith (\( k, v ) -> Many [ keys k, values v ]) + + +pair : a -> Sexpr a -> Sexpr a +pair key value = + Many [ Atom key, value ] + + +block : Block -> Sexpr String +block b = + case b of + Module record -> + Many + [ Atom "Module" + , Many + [ Atom "ty" + , moduleType record.ty + ] + ] + + ValueDeclaration record -> + Many + [ Atom "ValueDeclaration" + , Many + [ Atom "name" + , record.name |> Located.unwrap |> Token.TokenLowerCase |> Token.tokenToString |> Atom + ] + , Many + [ Atom "args" + , listWith + (Located.unwrap >> Token.TokenLowerCase >> Token.tokenToString >> Atom) + record.args + ] + , Many + [ Atom "valueExpr__" + , expr record.valueExpr__ + ] + ] + + TypeAlias record -> + Many + [ Atom "TypeAlias" + , Many + [ Atom "ty" + , record.ty |> Token.TokenUpperCase |> Token.tokenToString |> Atom + ] + , Many + [ Atom "genericArgs" + , Many + (record.genericArgs + |> List.map (Token.TokenLowerCase >> Token.tokenToString >> Atom) + ) + ] + , Many + [ Atom "expr" + , typeExpr record.expr + ] + ] + + CustomType record -> + Debug.todo "" + + +state : State -> Sexpr String +state s = + case s of + State_BlockStart -> + Atom "State_BlockStart" + + State_Error_Recovery -> + Atom "State_Error_Recovery" + + State_BlockFirstItem _ -> + pair "State_BlockFirstItem" (Atom "TODO") + + State_BlockTypeAlias BlockTypeAlias_Keywords -> + pair "State_BlockTypeAlias" (Atom "BlockTypeAlias_Keywords") + + State_BlockTypeAlias (BlockTypeAlias_Named name genericArgs) -> + pair "State_BlockTypeAlias" + (Many + [ Atom "BlockTypeAlias_Named" + , name |> Token.TokenUpperCase |> Token.tokenToString |> Atom + , listWith Atom (Contextualize.toList (Token.TokenLowerCase >> Token.tokenToString) genericArgs) + ] + ) + + State_BlockTypeAlias (BlockTypeAlias_NamedAssigns name genericArgs) -> + pair "State_BlockTypeAlias" + (Many + [ Atom "BlockTypeAlias_NamedAssigns" + , name |> Token.TokenUpperCase |> Token.tokenToString |> Atom + , listWith (Token.TokenLowerCase >> Token.tokenToString >> Atom) genericArgs + ] + ) + + State_BlockTypeAlias (BlockTypeAlias_Completish name genericArgs typeExpr_) -> + pair "State_BlockTypeAlias" + (Many + [ Atom "BlockTypeAlias_Completish" + , name |> Token.TokenUpperCase |> Token.tokenToString |> Atom + , listWith (Token.TokenLowerCase >> Token.tokenToString >> Atom) genericArgs + , typeExpressionNestingLeaf typeExpr_ + ] + ) + + State_BlockCustomType _ -> + pair "State_BlockCustomType" (Atom "TODO") + + State_BlockValueDeclaration _ -> + pair "State_BlockValueDeclaration" (Atom "TODO") + + +expr : Frontend.LocatedExpr -> Sexpr String +expr expr_ = + case Located.unwrap expr_ of + Frontend.Int int -> + pair "Int" (Atom (String.fromInt int)) + + Frontend.HexInt int -> + pair "HexInt" (Atom (String.fromInt int)) + + Frontend.Float float -> + pair "Float" (Atom (String.fromFloat float)) + + Frontend.Char char -> + pair "Char" (Atom (String.fromChar char)) + + Frontend.String string -> + pair "String" (Atom string) + + Frontend.Bool bool -> + pair "Bool" + (Atom + (if bool then + "True" + + else + "False" + ) + ) + + Frontend.Var { qualifiedness, name } -> + pair "Var" + (Many + [ pair "qualifiedness" (Atom "TODO") + , pair "name" (Atom name) + ] + ) + + Frontend.Argument varName -> + pair "Argument" (Atom varName) + + Frontend.Operator operator lhs rhs -> + pair "Operator" + (Many + [ pair "op" (operator |> Located.unwrap |> Operator.toString |> Atom) + , pair "lhs" (expr lhs) + , pair "rhs" (expr rhs) + ] + ) + + Frontend.Lambda { arguments, body } -> + pair "Lambda" + (Many + [ pair "arguments" (listWith Atom arguments) + , pair "body " (Atom "TODO") + ] + ) + + Frontend.Call record -> + pair "Call" (Atom "TODO") + + Frontend.If record -> + pair "If" (Atom "TODO") + + Frontend.Let record -> + pair "Let" (Atom "TODO") + + Frontend.List locateds -> + pair "List" (Atom "TODO") + + Frontend.Unit -> + Atom "Unit" + + Frontend.Tuple first second -> + pair "Tuple" (Many [ Atom "TODO", Atom "TODO" ]) + + Frontend.Tuple3 first second third -> + pair "Tuple" (Many [ Atom "TODO", Atom "TODO", Atom "TODO" ]) + + Frontend.Record bindings -> + pair "Record" (Atom "TODO") + + Frontend.Case locatedExpr list -> + Debug.todo "" + + +typeExpr : ConcreteType PossiblyQualified -> Sexpr String +typeExpr expr_ = + case expr_ of + Concrete.TypeVar string -> + pair "TypeVar" (Atom string) + + Concrete.Function { from, to } -> + pair "Function" + (Many + [ pair "from" (typeExpr from) + , pair "to" (typeExpr to) + ] + ) + + Concrete.Int -> + Atom "Int" + + Concrete.Float -> + Atom "Float" + + Concrete.Char -> + Atom "Char" + + Concrete.String -> + Atom "String" + + Concrete.Bool -> + Atom "Bool" + + Concrete.List list -> + pair "List" (typeExpr list) + + Concrete.Unit -> + Atom "Unit" + + Concrete.Tuple first second -> + pair "Tuple" (Many [ typeExpr first, typeExpr second ]) + + Concrete.Tuple3 first second third -> + pair "Tuple" (Many [ typeExpr first, typeExpr second, typeExpr third ]) + + Concrete.Record dict -> + pair "Record" (dictEntriesWith Atom typeExpr dict) + + Concrete.UserDefinedType { qualifiedness, name, args } -> + let + (PossiblyQualified q) = + qualifiedness + in + pair "UserDefinedType" + (Many + [ pair "qualifiedness" + (pair "PossiblyQualified" + (case q of + Just moduleName -> + pair "Just" (Atom moduleName) + + Nothing -> + Atom "Nothing" + ) + ) + , pair "name" (Atom name) + , pair "args" (listWith typeExpr args) + ] + ) + + +typeExpressionNestingLeaf : TypeExpressionNestingLeaf () () () -> Sexpr String +typeExpressionNestingLeaf leaf = + case leaf of + TypeExpressionNestingLeaf_Bracket record -> + pair "TypeExpressionNestingLeaf_Bracket" (Atom "TODO") + + TypeExpressionNestingLeaf_PartialRecord partialRecord -> + pair "TypeExpressionNestingLeaf_PartialRecord" (Atom "TODO") + + TypeExpressionNestingLeaf_TypeWithArgs record -> + pair "TypeExpressionNestingLeaf_TypeWithArgs" (Atom "TODO") + + TypeExpressionNestingLeaf_Function record -> + pair "TypeExpressionNestingLeaf_Function" (Atom "TODO") + + TypeExpressionNestingLeaf_Expr () typeExpression -> + pair "TypeExpressionNestingLeaf_Expr" (Atom "TODO") + + +moduleType : ModuleType -> Sexpr String +moduleType m = + case m of + ModuleType.PlainModule -> + Atom "PlainModule" + + ModuleType.PortModule -> + Atom "PortModule" + + ModuleType.EffectModule -> + Atom "EffectModule" diff --git a/src/Stage/Parse/Token.elm b/src/Stage/Parse/Token.elm new file mode 100644 index 00000000..2ebc72c4 --- /dev/null +++ b/src/Stage/Parse/Token.elm @@ -0,0 +1,66 @@ +module Stage.Parse.Token exposing (..) + + +type Keyword + = Module + | Type + | Alias + | Exposing + | Case + | Of + | If + | Then + | Else + + +type UpperCase + = UpperCase String + + +type LowerCase + = LowerCase String + + +type Token + = TokenUpperCase UpperCase + | TokenLowerCase LowerCase + + +tokenToString t = + case t of + TokenUpperCase (UpperCase s) -> + s + + TokenLowerCase (LowerCase s) -> + s + + +keywordToString : Keyword -> String +keywordToString keyword = + case keyword of + Module -> + "module" + + Type -> + "type" + + Alias -> + "alias" + + Exposing -> + "exposing" + + Case -> + "case" + + Of -> + "of" + + If -> + "if" + + Then -> + "then" + + Else -> + "else" diff --git a/tests/DesugarTest.elm b/tests/DesugarTest.elm index ff05d99e..d19caf3c 100644 --- a/tests/DesugarTest.elm +++ b/tests/DesugarTest.elm @@ -11,6 +11,7 @@ import Elm.Data.Import exposing (Import) import Elm.Data.Located as Located import Elm.Data.Module as Module exposing (Module) import Elm.Data.ModuleName exposing (ModuleName) +import Elm.Data.Operator as Operator import Elm.Data.Qualifiedness exposing (PossiblyQualified(..)) import Elm.Data.TypeAnnotation exposing (TypeAnnotation) import Elm.Data.VarName exposing (VarName) @@ -167,7 +168,8 @@ frontendLambda arg1 arg2 = { arguments = [ arg1, arg2 ] , body = located <| - Frontend.Plus + Frontend.Operator + (located Operator.Add) (located <| Frontend.Argument arg1) (located <| Frontend.Argument arg2) } @@ -183,7 +185,8 @@ canonicalLambda arg1 arg2 = CanonicalU.Lambda { argument = arg2 , body = - CanonicalU.Plus + CanonicalU.Operator + Operator.Add (CanonicalU.Argument arg1) (CanonicalU.Argument arg2) } diff --git a/tests/EmitJsonTest.elm b/tests/EmitJsonTest.elm index 1bb2e06c..9ea3ff18 100644 --- a/tests/EmitJsonTest.elm +++ b/tests/EmitJsonTest.elm @@ -3,6 +3,7 @@ module EmitJsonTest exposing (json) import Dict import Elm.AST.Typed as Typed exposing (Expr_(..)) import Elm.Data.Declaration exposing (Declaration, DeclarationBody(..)) +import Elm.Data.Operator as Operator import Elm.Data.Qualifiedness exposing (Qualified) import Expect import Fuzz exposing (bool, char, float, int, string) @@ -11,7 +12,8 @@ import Stage.Emit.JsonAST as JSON import Test exposing (Test, describe, fuzz, test) import TestHelpers exposing - ( typed + ( located + , typed , typedInt , typedIntList , typedString @@ -91,13 +93,13 @@ json = ) , describe "Plus" (List.map runTest - [ ( "simple", Plus (typedInt 1) (typedInt 2), "{\"type\":\"plus\",\"e1\":{\"type\":\"int\",\"value\":1},\"e2\":{\"type\":\"int\",\"value\":2}}" ) + [ ( "simple", Operator (located Operator.Add) (typedInt 1) (typedInt 2), "{\"type\":\"plus\",\"e1\":{\"type\":\"int\",\"value\":1},\"e2\":{\"type\":\"int\",\"value\":2}}" ) ] ) , describe "Cons" (List.map runTest [ ( "simple" - , Cons (typedInt 1) (typedIntList [ 2, 3 ]) + , Operator (located Operator.Cons) (typedInt 1) (typedIntList [ 2, 3 ]) , "{\"type\":\"cons\",\"e1\":{\"type\":\"int\",\"value\":1},\"e2\":{\"type\":\"list\",\"items\":[{\"type\":\"int\",\"value\":2},{\"type\":\"int\",\"value\":3}]}}" ) ] diff --git a/tests/EmitTest.elm b/tests/EmitTest.elm index 278e9bad..7b310a1e 100644 --- a/tests/EmitTest.elm +++ b/tests/EmitTest.elm @@ -3,13 +3,15 @@ module EmitTest exposing (javascript) import Dict import Elm.AST.Typed as Typed exposing (Expr_(..)) import Elm.Data.Declaration exposing (Declaration, DeclarationBody(..)) +import Elm.Data.Operator as Operator import Elm.Data.Qualifiedness exposing (Qualified) import Expect import Stage.Emit.JavaScript as JS import Test exposing (Test, describe, test) import TestHelpers exposing - ( typed + ( located + , typed , typedBool , typedInt , typedIntList @@ -85,20 +87,30 @@ javascript = , describe "Plus" (List.map runTest -- We need to give the child `Expr`s a type too - [ ( "simple", Plus (typedInt 1) (typedInt 2), "(1 + 2)" ) - , ( "nested", Plus (typedInt 1) (typed (Plus (typedInt 2) (typedInt 3))), "(1 + (2 + 3))" ) + [ ( "simple" + , Operator (located Operator.Add) (typedInt 1) (typedInt 2) + , "(1 + 2)" + ) + , ( "nested" + , Operator + (located Operator.Add) + (typedInt 1) + (typed (Operator (located Operator.Add) (typedInt 2) (typedInt 3))) + , "(1 + (2 + 3))" + ) ] ) , describe "Cons" (List.map runTest [ ( "simple" - , Cons (typedInt 1) (typedIntList [ 2, 3 ]) + , Operator (located Operator.Cons) (typedInt 1) (typedIntList [ 2, 3 ]) , "[1].concat([2, 3])" ) , ( "nested" - , Cons + , Operator + (located Operator.Cons) (typedInt 1) - (typed (Cons (typedInt 2) (typedIntList [ 3, 4 ]))) + (typed (Operator (located Operator.Cons) (typedInt 2) (typedIntList [ 3, 4 ]))) , "[1].concat([2].concat([3, 4]))" ) ] @@ -238,7 +250,8 @@ javascript = } , body = typed - (Plus + (Operator + (located Operator.Add) (typedInt 1) (typed (Argument "x")) ) @@ -258,7 +271,8 @@ javascript = , { name = "y" , body = typed - (Plus + (Operator + (located Operator.Add) (typedInt 1) (typed (Argument "x")) ) @@ -333,14 +347,14 @@ javascript = , describe "Mixed expressions" (List.map runTest [ ( "plus in tuple" - , Tuple (typed (Plus (typedInt 1) (typedInt 41))) (typedString "Hello") + , Tuple (typed (Operator (located Operator.Add) (typedInt 1) (typedInt 41))) (typedString "Hello") , """[(1 + 41),"Hello"]""" ) , ( "tuple and cons in record" , Record (Dict.fromList [ ( "a", { name = "a", body = typed (Tuple (typedInt 2) (typedInt 3)) } ) - , ( "b", { name = "b", body = typed (Cons (typedInt 2) (typedIntList [ 3, 4 ])) } ) + , ( "b", { name = "b", body = typed (Operator (located Operator.Cons) (typedInt 2) (typedIntList [ 3, 4 ])) } ) ] ) , """{a: [2,3], b: [2].concat([3, 4])}""" diff --git a/tests/InferTypesFuzz.elm b/tests/InferTypesFuzz.elm index 4244a58e..3ed5ceb8 100644 --- a/tests/InferTypesFuzz.elm +++ b/tests/InferTypesFuzz.elm @@ -5,6 +5,7 @@ import Elm.AST.Canonical as Canonical import Elm.AST.Canonical.Unwrapped as CanonicalU import Elm.Compiler.Error exposing (TypeError(..)) import Elm.Data.Located as Located +import Elm.Data.Operator as Operator import Elm.Data.Qualifiedness exposing (Qualified) import Elm.Data.Type as Type import Elm.Data.Type.Concrete as ConcreteType exposing (ConcreteType(..)) @@ -248,7 +249,8 @@ intToIntFunctionExpr = let combine argument intPart = lambda argument <| - CanonicalU.Plus + CanonicalU.Operator + Operator.Add (CanonicalU.Argument argument) intPart @@ -361,11 +363,8 @@ shrinkExpr expr = CanonicalU.Argument _ -> nope - CanonicalU.Plus left right -> - shrinkPlus left right - - CanonicalU.Cons x xs -> - shrinkCons x xs + CanonicalU.Operator op x xs -> + shrinkOp op x xs CanonicalU.Lambda { argument, body } -> shrinkLambda argument body @@ -407,47 +406,21 @@ shrinkExpr expr = nope -{-| Shrinks a plus expression. - ---- - -We cannot write a type annotation here. -The `LazyList a` type used by shrinkers is not exposed outside `elm-explorations/test`. - - shrinkPlus : CanonicalU.Expr -> CanonicalU.Expr -> LazyList CanonicalU.Expr - --} -shrinkPlus left right = - ([ Shrink.map2 CanonicalU.Plus - (shrinkExpr left) - (Shrink.singleton right) - , Shrink.map2 CanonicalU.Plus - (Shrink.singleton left) - (shrinkExpr right) - ] - |> List.map always - |> Shrink.mergeMany - ) - -- The value built up to this point is a shrinker. - -- We need to call it with an CanonicalU.Expr to get a lazy list. - left - - -{-| Shrinks a cons expression. +{-| Shrinks a binary operator expression. --- We cannot write a type annotation here. The `LazyList a` type used by shrinkers is not exposed outside `elm-explorations/test`. - shrinkCons : CanonicalU.Expr -> CanonicalU.Expr -> LazyList CanonicalU.Expr + shrinkCons : Operator -> CanonicalU.Expr -> CanonicalU.Expr -> LazyList CanonicalU.Expr -} -shrinkCons x xs = - ([ Shrink.map2 CanonicalU.Cons +shrinkOp op x xs = + ([ Shrink.map2 (CanonicalU.Operator op) (shrinkExpr x) (Shrink.singleton xs) - , Shrink.map2 CanonicalU.Cons + , Shrink.map2 (CanonicalU.Operator op) (Shrink.singleton x) (shrinkExpr xs) ] diff --git a/tests/InferTypesTest.elm b/tests/InferTypesTest.elm index eed1ff46..64bd2ab3 100644 --- a/tests/InferTypesTest.elm +++ b/tests/InferTypesTest.elm @@ -5,6 +5,7 @@ import Elm.AST.Canonical as Canonical import Elm.AST.Canonical.Unwrapped as CanonicalU import Elm.AST.Typed as Typed import Elm.Compiler.Error as Error exposing (Error(..), TypeError(..)) +import Elm.Data.Operator as Operator import Elm.Data.Qualifiedness exposing (PossiblyQualified(..), Qualified(..)) import Elm.Data.Type as Type exposing (Type(..), TypeOrId(..)) import Elm.Data.Type.ToString as TypeToString @@ -115,7 +116,7 @@ typeInference = ] , runSection "plus" [ ( "same types" - , CanonicalU.Plus + , CanonicalU.Operator Operator.Add (CanonicalU.Var { module_ = "Main", name = "age" }) (CanonicalU.Int 1) , Ok Int @@ -123,15 +124,15 @@ typeInference = ] , runSection "cons" [ ( "simple case" - , CanonicalU.Cons + , CanonicalU.Operator Operator.Cons (CanonicalU.Int 1) (CanonicalU.List []) , Ok (List (Type Int)) ) , ( "advanced case" - , CanonicalU.Cons + , CanonicalU.Operator Operator.Cons (CanonicalU.Int 1) - (CanonicalU.Cons + (CanonicalU.Operator Operator.Cons (CanonicalU.Int 2) (CanonicalU.List [ CanonicalU.Int 3 @@ -142,7 +143,7 @@ typeInference = , Ok (List (Type Int)) ) , ( "fail with wrong argument types" - , CanonicalU.Cons + , CanonicalU.Operator Operator.Cons (CanonicalU.List [ CanonicalU.Int 1 , CanonicalU.Int 2 @@ -160,7 +161,7 @@ typeInference = ) ) , ( "variable and list" - , CanonicalU.Cons + , CanonicalU.Operator Operator.Cons (CanonicalU.Var { module_ = "Main", name = "age" }) (CanonicalU.List [ CanonicalU.Int 1 ]) , Ok (List (Type Int)) diff --git a/tests/LexerTest.elm b/tests/LexerTest.elm new file mode 100644 index 00000000..3c205f5f --- /dev/null +++ b/tests/LexerTest.elm @@ -0,0 +1,1083 @@ +module LexerTest exposing (..) + +import Dict +import Elm.AST.Frontend as Frontend +import Elm.AST.Frontend.Unwrapped exposing (Expr(..), Pattern(..)) +import Elm.Data.Declaration as Declaration exposing (DeclarationBody) +import Elm.Data.Exposing exposing (ExposedItem(..), Exposing(..)) +import Elm.Data.Located as Located +import Elm.Data.Module exposing (ModuleType(..)) +import Elm.Data.Qualifiedness exposing (PossiblyQualified(..)) +import Elm.Data.Type.Concrete as ConcreteType exposing (ConcreteType) +import Elm.Data.TypeAnnotation exposing (TypeAnnotation) +import Expect exposing (Expectation) +import OurExtras.String as String +import Parser.Advanced as P +import Stage.Parse.Lexer exposing (..) +import String.Extra as String +import Test exposing (Test, describe, test) + + +runTest ( description, input ) = + test description <| + \() -> + input + |> P.run Stage.Parse.Lexer.parser + |> Expect.all + [ Result.map (List.map (Located.unwrap >> toString) >> String.join "") + >> Expect.equal (Ok input) + , Result.map + (List.filterMap + (\item -> + case Located.unwrap item of + Invalid (OtherInvalid s) -> + Just s + + Invalid (IllegalCharacter c) -> + Just (String.fromChar c) + + _ -> + Nothing + ) + ) + >> Expect.equal (Ok []) + ] + + +moduleDeclaration : Test +moduleDeclaration = + describe "Stage.Parse.Parser.moduleDeclaration" + [ describe "general" + (List.map runTest + [ ( "works with simple module name" + , "module Foo exposing (..)" + -- , [ Token "module" + -- , Whitespace 1 + -- , Token "Foo" + -- , Whitespace 1 + -- , Token "exposing" + -- , Whitespace 1 + -- , Sigil (Bracket Round Open) + -- , Sigil DoubleDot + -- , Sigil (Bracket Round Close) + -- ] + ) + , ( "works with nested module name" + , "module Foo.Bar exposing (..)" + ) + , ( "works with even more nested module name" + , "module Foo.Bar.Baz.Quux exposing (..)" + ) + , ( "allows multiple spaces between the `module` keyword and the module name" + , "module Foo exposing (..)" + ) + , ( "doesn't allow a newline between the `module` keyword and the module name" + , """ + module + Foo exposing (..) + """ + |> String.unindent + |> String.removeNewlinesAtEnds + ) + , ( "allows a newline and space between the `module` keyword and the module name" + , """ + module + Foo exposing (..) + """ + |> String.unindent + |> String.removeNewlinesAtEnds + ) + , ( "allows multiple spaces between the module name and the `exposing` keyword" + , "module Foo exposing (..)" + ) + , ( "doesn't allow a newline between the module name and the `exposing` keyword" + , """ + module Foo + exposing (..) + """ + |> String.unindent + |> String.removeNewlinesAtEnds + ) + , ( "allows newline and space between the module name and the `exposing` keyword" + , """ + module Foo + exposing (..) + """ + |> String.unindent + |> String.removeNewlinesAtEnds + ) + , ( "allows multiple spaces between the `exposing` keyword and the exposing list" + , "module Foo exposing (..)" + ) + , ( "doesn't allow a newline between the `exposing` keyword and the exposing list" + , """ + module Foo exposing + (..) + """ + |> String.unindent + |> String.removeNewlinesAtEnds + ) + , ( "allows a newline and space between the `exposing` keyword and the exposing list" + , """ + module Foo exposing + (..) + """ + |> String.unindent + |> String.removeNewlinesAtEnds + ) + , ( "doesn't work without something after the `exposing` keyword" + , "module Foo exposing" + ) + ] + ) + , describe "plain module" + (List.map runTest + [ ( "simply works" + , "module Foo exposing (..)" + ) + ] + ) + , describe "port module" + (List.map runTest + [ ( "simply works" + , "port module Foo exposing (..)" + ) + ] + ) + ] + + +exposingList : Test +exposingList = + describe "Stage.Parse.Parser.exposingList" + [ describe "exposing all" + (List.map runTest + [ ( "simply works" + , "(..)" + ) + , ( "doesn't work with spaces inside the parens" + , "( .. )" + ) + ] + ) + , describe "exposing some" + [ describe "general" + (List.map runTest + [ ( "can't be empty" + , "()" + ) + , ( "works with spaces between items" + , "(foo, bar)" + ) + , ( "works with even more spaces between items" + , "(foo , bar)" + ) + , ( "works with mixed values" + , "(foo, Bar, Baz(..))" + ) + , ( "allows for newline" + , "(foo\n,bar)" + ) + ] + ) + , describe "values" + (List.map runTest + [ ( "works with a value" + , "(foo)" + ) + ] + ) + , describe "types" + (List.map runTest + [ ( "works with exposed type" + , "(Foo)" + ) + ] + ) + , describe "types with all constructors" + (List.map runTest + [ ( "works with exposed type and all constructors" + , "(Foo(..))" + ) + , ( "doesn't allow spaces between the module name and the double period list" + , "(Foo (..))" + ) + , ( "doesn't allow spaces inside the double period list" + , "(Foo( .. ))" + ) + , ( "doesn't allow only some constructors exposed" + , "(Foo(Bar))" + ) + ] + ) + ] + ] + + +imports : Test +imports = + describe "Stage.Parse.Parser.imports" + [ describe "general" + (List.map runTest + [ ( "allows for multiple modifiers" + , "import Foo as F exposing (..)" + ) + , ( "allows for multiple spaces" + , "import Foo as F exposing (..)" + ) + , ( "allows for multiple imports" + , "import Foo\nimport Bar" + ) + , ( "allows for multiple newlines between imports" + , "import Foo\n\nimport Bar" + ) + , ( "doesn't allow for lower-case import" + , "import foo" + ) + ] + ) + , describe "simple" + (List.map runTest + [ ( "simply works" + , "import Foo" + ) + ] + ) + , describe "as" + (List.map runTest + [ ( "simply works" + , "import Foo as F" + ) + , ( "doesn't work with lowercase alias" + , "import Foo as f" + ) + , ( "doesn't work with dot-separated alias" + , "import Foo as X.B" + ) + ] + ) + , describe "exposing" + (List.map runTest + [ ( "simply works" + , "import Foo exposing (bar, Baz, Quux(..))" + ) + , ( "doesn't work without something after the `exposing` keyword" + , "import Foo exposing" + ) + ] + ) + ] + + +moduleName : Test +moduleName = + describe "Stage.Parse.Parser.moduleName" + (List.map runTest + [ ( "works with simple module name" + , "Foo" + ) + , ( "doesn't work with lower-case name" + , "foo" + ) + , ( "doesn't work with dot at the end" + , "Foo." + ) + , ( "works with dotted module name" + , "Foo.Bar" + ) + , ( "works with doubly-dotted module name" + , "Foo.Bar.Baz" + ) + , ( "doesn't work with lower-case letter after the dot" + , "Foo.bar" + ) + ] + ) + + +singleQuote : String -> String +singleQuote txt = + "'" ++ txt ++ "'" + + +doubleQuote : String -> String +doubleQuote txt = + "\"" ++ txt ++ "\"" + + +tripleQuote : String -> String +tripleQuote txt = + "\"\"\"" ++ txt ++ "\"\"\"" + + +expr : Test +expr = + let + runSection ( description, tests ) = + describe description + (List.map runTest tests) + in + describe "Stage.Parse.Parser.expr" + (List.map runSection + [ ( "lambda" + , [ ( "works with single argument" + , "\\x -> x + 1" + ) + , ( "multiline" + , """ + \\x -> + x + 1 + """ + |> String.unindent + |> String.removeNewlinesAtEnds + ) + , ( "works with multiple arguments" + , "\\x y -> x + y" + ) + ] + ) + , ( "call" + , [ ( "simple" + , "fn 1" + ) + , ( "with var" + , "fn arg" + ) + , ( "multiple" + , "fn arg1 arg2" + ) + , ( "space not needed if parenthesized arg" + , "fn(arg1)" + ) + , ( "multiline" + , """ + fn + arg1 + arg2 + """ + |> String.unindent + |> String.removeNewlinesAtEnds + ) + ] + ) + , ( "if" + , [ ( "with one space" + , "if 1 then 2 else 3" + ) + , ( "with multiple spaces" + , "if 1 then 2 else 3" + ) + , ( "multiline" + , """ + if 1 then + 2 + else + 3 + """ + |> String.unindent + |> String.removeNewlinesAtEnds + ) + ] + ) + , ( "literal int" + , [ ( "positive" + , "123" + ) + , ( "zero" + , "0" + ) + , ( "negative zero" + , "-0" + ) + , ( "hexadecimal int" + , "0x123abc" + ) + , ( "hexadecimal int - uppercase" + , "0x789DEF" + ) + , ( "hexadecimal int - mixed case" + , "0x789dEf" + ) + , ( "negative int" + , "-42" + ) + , ( "negative hexadecimal" + , "-0x123abc" + ) + , ( "starting with zero disallowed" + , "0123" + ) + , ( "e is interpreted as hex 14, not scientific notation" + , "0xABCe5" + ) + ] + ) + , ( "literal float" + , [ ( "positive" + , "12.3" + ) + , ( "zero" + , "0.0" + ) + , ( "negative zero" + , "-0.0" + ) + , ( "negative float" + , "-4.2" + ) + , ( "Scientific notation" + , "5e2" + ) + , ( "Scientific notation with dot" + , "5.12e2" + ) + , ( "Uppercase scientific notation" + , "5.12E2" + ) + , ( "Negative scientific notation" + , "-5.12e2" + ) + , ( "Exponent with explicit plus sign" + , "5e+2" + ) + , ( "Uppercase E and exponent with explicit plus sign" + , "5E+2" + ) + , ( "Negative exponent" + , "5e-2" + ) + , ( "Zero - exhibit 1" + , "0.0e5" + ) + , ( "Zero - exhibit 2" + , "0e5" + ) + , ( "ending with dot disallowed" + , "123." + ) + ] + ) + , ( "literal char" + , [ ( "number" + , "'1'" + ) + , ( "space" + , "' '" + ) + , ( "newline shouldn't work" + , "'\n'" + ) + , ( "letter lowercase" + , "'a'" + ) + , ( "letter uppercase" + , "'A'" + ) + + -- https://github.com/elm/compiler/blob/dcbe51fa22879f83b5d94642e117440cb5249bb1/compiler/src/Parse/String.hs#L279-L285 + , ( "escape backslash" + , singleQuote "\\\\" + ) + , ( "escape n" + , singleQuote "\\n" + ) + , ( "escape r" + , singleQuote "\\r" + ) + , ( "escape t" + , singleQuote "\\t" + ) + , ( "double quote" + , singleQuote "\"" + ) + , ( "single quote" + , singleQuote "\\'" + ) + , ( "emoji" + , singleQuote "😃" + ) + , ( "escaped unicode code point" + , singleQuote "\\u{1F648}" + ) + ] + ) + , ( "literal string" + , [ ( "empty" + , doubleQuote "" + ) + , ( "one space" + , doubleQuote " " + ) + , ( "newline shouldn't work" + , doubleQuote "\n" + ) + , ( "two numbers" + , doubleQuote "42" + ) + , ( "single quote" + , doubleQuote "'" + ) + , ( "double quote" + , doubleQuote "\\\"" + ) + , ( "escape backslash" + , doubleQuote "\\\\" + ) + , ( "escape n" + , doubleQuote "\\n" + ) + , ( "escape r" + , doubleQuote "\\r" + ) + , ( "escape t" + , doubleQuote "\\t" + ) + , ( "emoji" + , doubleQuote "😃" + ) + , ( "escaped unicode code point" + , doubleQuote "\\u{1F648}" + ) + , ( "combo of escapes and chars" + , doubleQuote "\\u{1F648}\\n\\r\\t\\\\abc123" + ) + ] + ) + , ( "literal multiline string" + , [ ( "empty" + , tripleQuote "" + ) + , ( "one space" + , tripleQuote " " + ) + , ( "newline" + , tripleQuote "\n" + ) + , ( "two numbers" + , tripleQuote "42" + ) + , ( "single quote" + , tripleQuote "'" + ) + , ( "double quote" + , tripleQuote " \" " + ) + , ( "escape backslash" + , tripleQuote "\\\\" + ) + , ( "escape n" + , tripleQuote "\\n" + ) + , ( "escape r" + , tripleQuote "\\r" + ) + , ( "escape t" + , tripleQuote "\\t" + ) + , ( "emoji" + , tripleQuote "😃" + ) + , ( "escaped unicode code point" + , tripleQuote "\\u{1F648}" + ) + , ( "combo of escapes, newlines, and chars" + , tripleQuote "\\u{1F648}\\n\n\n\\r\\t\\\\abc123" + ) + ] + ) + , ( "literal bool" + , [ ( "True" + , "True" + ) + , ( "False" + , "False" + ) + ] + ) + , ( "let" + , [ ( "one liner" + , "let x = 1 in 2" + ) + , ( "one binding, generous whitespace" + , """ + let + x = + 1 + in + 2 + """ + |> String.unindent + |> String.removeNewlinesAtEnds + ) + , ( "doesn't allow bindings on the same indentation level as `let`" + , """ + let + x = 1 + in + 2 + """ + |> String.unindent + |> String.removeNewlinesAtEnds + ) + , ( "allows result expr on the same indentation level as `let`" + , """ + let + x = 1 + in + 2 + """ + |> String.unindent + |> String.removeNewlinesAtEnds + ) + , ( "multiple bindings" + , """ + let + x = 1 + y = 2 + in + 3 + """ + |> String.unindent + |> String.removeNewlinesAtEnds + ) + , ( "doesn't allow bindings to have different indentation from each other" + , """ + let + x = 1 + y = 2 + in + 3 + """ + |> String.unindent + |> String.removeNewlinesAtEnds + ) + , ( "doesn't allow bindings to have different indentation from each other - the other way" + , """ + let + x = 1 + y = 2 + in + 3 + """ + |> String.unindent + |> String.removeNewlinesAtEnds + ) + , ( "one binding that's used in the body" + , """ + let + x = 2 + in + 1 + x + """ + |> String.unindent + |> String.removeNewlinesAtEnds + ) + , ( "two bindings where one is dependent on the other" + , """ + let + x = 2 + y = x + 1 + in + 42 + """ + |> String.unindent + |> String.removeNewlinesAtEnds + ) + ] + ) + , ( "list" + , [ ( "empty list" + , "[]" + ) + , ( "empty list with inner spaces" + , "[ ]" + ) + , ( "single item in list" + , "[1]" + ) + , ( "single item in list with inner spaces" + , "[ 1 ]" + ) + , ( "simple list" + , "[1,2,3]" + ) + , ( "simple list with inner spaces" + , "[ 1, 2 , 3 ]" + ) + , ( "list concat" + , "[] ++ []" + ) + , ( "multiline" + , """ + [ 1 + , 2 + , 3 + ] + """ + |> String.unindent + |> String.removeNewlinesAtEnds + ) + ] + ) + , ( "unit" + , [ ( "simple case" + , "()" + ) + ] + ) + , ( "tuple" + , [ ( "without spaces" + , "(1,2)" + ) + , ( "with inner spaces" + , "( 3 , 4 )" + ) + , ( "nested tuple" + , "(5,(6,7))" + ) + ] + ) + , ( "tuple3" + , [ ( "without spaces" + , "(1,2,3)" + ) + , ( "with inner spaces" + , "( 4 , 5 , 6 )" + ) + ] + ) + , ( "cons" + , [ ( "simple case" + , "1 :: []" + ) + , ( "multiple values case" + , "1 :: 2 :: []" + ) + , ( "no spaces" + , "1::[]" + ) + , ( "multiple spaces" + , "1 :: []" + ) + ] + ) + , ( "record" + , [ ( "empty record" + , "{}" + ) + , ( "empty record with spaces" + , "{ }" + ) + , ( "one field record" + , "{ a = 42 }" + ) + , ( "one field record without spaces" + , "{a=42}" + ) + , ( "two fields record" + , """{ a = 42, b = "hello" }""" + ) + , ( "multiline" + , """ + { a = 42 + , b = "hello" + } + """ + ) + ] + ) + , ( "case" + , [ ( "simple case" + , "case True of _->True" + ) + , ( "multiline case" + , """ + case 21 of + 31 -> True + 5 -> True + 0xABC -> True + _ -> False + """ + |> String.unindent + |> String.removeNewlinesAtEnds + ) + , ( "complex case" + , """ + case arg of + ('c', 23) -> + True + ("string") -> + True + ((arg1, arg2), 435.4) -> + False + [_, 45, (67.7)] -> + False + fst :: snd :: tail -> + False + ({ count } as alias1) as alias2 -> + False + """ + |> String.unindent + |> String.removeNewlinesAtEnds + ) + ] + ) + , ( "operators" + , [ ( "add" + , "5 + 5" + ) + , ( "sub" + , """ + 6 - 10 + """ + ) + , ( "unary subtract" + , """ + - hello + """ + ) + , ( "chained" + , """ + 5 *5 + 8 + 1 - (4 + 7) ^ 2 + """ + ) + ] + ) + ] + ) + + +expectEqualParseResult : + String + -> a + -> Result (List (P.DeadEnd Never LexProblem)) a + -> Expectation +expectEqualParseResult input expected actual = + case actual of + Err deadEnds -> + Expect.fail + (String.join "\n" + (input + :: "===>" + :: "Err" + :: List.map deadEndToString deadEnds + ) + ) + + Ok actual_ -> + actual_ + |> Expect.equal expected + + +deadEndToString : P.DeadEnd Never LexProblem -> String +deadEndToString deadEnd = + "\n(" + ++ String.fromInt (deadEnd.row - 1) + ++ "," + ++ String.fromInt (deadEnd.col - 1) + ++ ") " + ++ Debug.toString deadEnd.problem + + +type_ : Test +type_ = + describe "Stage.Parse.Parser.type_" + (List.map runTest + [ ( "int", "Int" ) + , ( "unit", "()" ) + , ( "type var a", "a" ) + , ( "function" + , "Int -> ()" + ) + , ( "multiple-arg function" + , "Int -> () -> Char" + ) + , ( "float", "Float" ) + , ( "char", "Char" ) + , ( "string", "String" ) + , ( "bool", "Bool" ) + , ( "list", "List ()" ) + , ( "tuple" + , "(Int, String)" + ) + , ( "tuple with different whitespace" + , "( Int,String )" + ) + , ( "tuple with yet different whitespace" + , "( Int , String )" + ) + , ( "tuple3" + , "(Int, String, Bool)" + ) + , ( "custom type or alias" + , "NonemptyList" + ) + , ( "parametric type" + , "Maybe a" + ) + , ( "qualified custom type" + , "Foo.Bar" + ) + , ( "qualified custom type with params" + , "Foo.Bar a Int" + ) + , ( "empty record" + , "{}" + ) + , ( "empty record with whitespace" + , "{ }" + ) + , ( "record with one field" + , "{ x : Int }" + ) + , ( "record with two fields" + , "{ x : Int, y : String }" + ) + , ( "multiline record" + , """ + { x : Int + , y : String + } + """ + |> String.unindent + |> String.removeNewlinesAtEnds + ) + , ( "parenthesized type" + , "(Int)" + ) + , ( "parenthesized type with whitespace" + , "( Int )" + ) + ] + ) + + +valueDeclaration : Test +valueDeclaration = + -- TODO add various whitespace behavior tests + describe "Stage.Parse.Parser.valueDeclaration" <| + List.map runTest + [ ( "simple without annotation" + , "x = ()" + ) + , ( "simple with annotation" + , """ + y : () + y = () + """ + |> String.unindent + |> String.removeNewlinesAtEnds + ) + , ( "user defined type with argument - newline+space" + , """ + x : Foo + () + x = () + """ + |> String.unindent + |> String.removeNewlinesAtEnds + ) + , ( "user defined type with argument - newline only" + , """ + x : Foo + () + x = () + """ + |> String.unindent + |> String.removeNewlinesAtEnds + ) + , ( "type on a newline+space" + , """ + x : + () + x = () + """ + |> String.unindent + |> String.removeNewlinesAtEnds + ) + , ( "type on a newline without space" + , """ + x : + () + x = () + """ + |> String.unindent + |> String.removeNewlinesAtEnds + ) + ] + + +typeAliasDeclaration : Test +typeAliasDeclaration = + describe "Stage.Parse.Parser.typeAliasDeclaration" <| + List.map runTest <| + [ ( "simple" + , "type alias Foo = ()" + ) + , ( "with params" + , "type alias Bar a = ()" + ) + , ( "a bit more advanced" + , "type alias Foo = Maybe Int" + ) + , {- TODO create integration test that this fails + (`a` on right must be present on the left too) + -} + ( "to something that itself has params" + , "type alias Foo = Maybe a" + ) + , ( "params on both sides" + , "type alias Foo a = Maybe a" + ) + ] + + +customTypeDeclaration : Test +customTypeDeclaration = + describe "Stage.Parse.Parser.customTypeDeclaration" <| + List.map runTest <| + [ ( "simple" + , "type Foo = Bar" + ) + , ( "with params" + , "type Bar a = Baz" + ) + , ( "a bit more advanced" + , "type Foo = Bar Int" + ) + , {- TODO create integration test that this fails + (`a` on right must be present on the left too) + -} + ( "to something that itself has parameters" + , "type Foo = Bar a" + ) + , ( "params on both sides" + , "type Foo a = Bar (Maybe a)" + ) + , ( "multiple constructors" + , "type Foo = Bar | Baz" + ) + ] + + +portDeclaration : Test +portDeclaration = + describe "Stage.Parse.Parser.portDeclaration" <| + List.map runTest <| + [ ( "outgoing" + , "port foo : String -> Cmd msg" + ) + , ( "incoming" + , "port bar : (String -> msg) -> Sub msg" + ) + , ( "wacky multiline" + , """ + port + foo + : + String -> Cmd msg + """ + |> String.unindent + |> String.removeNewlinesAtEnds + ) + ] diff --git a/tests/OptimizeTest.elm b/tests/OptimizeTest.elm index 230ce0e8..7253ece4 100644 --- a/tests/OptimizeTest.elm +++ b/tests/OptimizeTest.elm @@ -1,6 +1,7 @@ module OptimizeTest exposing (optimize) import Elm.AST.Typed as Typed exposing (Expr_(..)) +import Elm.Data.Operator as Operator exposing (Operator) import Elm.Data.Type as Type exposing (TypeOrId(..)) import Expect import Stage.Optimize @@ -31,7 +32,8 @@ optimize = (List.map runTest [ ( "works with two literal ints" , located - ( Plus + ( Operator + (located Operator.Add) (typedInt 2) (typedInt 5) , Type Type.Int @@ -40,13 +42,15 @@ optimize = ) , ( "doesn't work if left is not int" , located - ( Plus + ( Operator + (located Operator.Add) (located ( Argument "x", Type Type.Int )) (typedInt 5) , Type Type.Int ) , located - ( Plus + ( Operator + (located Operator.Add) (located ( Argument "x", Type Type.Int )) (typedInt 5) , Type Type.Int @@ -54,13 +58,15 @@ optimize = ) , ( "doesn't work if right is not int" , located - ( Plus + ( Operator + (located Operator.Add) (typedInt 5) (located ( Argument "x", Type Type.Int )) , Type Type.Int ) , located - ( Plus + ( Operator + (located Operator.Add) (typedInt 5) (located ( Argument "x", Type Type.Int )) , Type Type.Int @@ -72,7 +78,8 @@ optimize = (List.map runTest [ ( "works with one value" , located - ( Cons + ( Operator + (located Operator.Cons) (typedInt 1) (typedIntList [ 2, 3 ]) , Type Type.Int diff --git a/tests/ParserLexerTest.elm b/tests/ParserLexerTest.elm new file mode 100644 index 00000000..f420c453 --- /dev/null +++ b/tests/ParserLexerTest.elm @@ -0,0 +1,115 @@ +module ParserLexerTest exposing (tests) + +import Elm.Data.Located as Located exposing (Located) +import Expect +import Fuzz +import Parser.Advanced as P +import ParserLexerTestCases +import Stage.Parse.Contextualize as Contextualize +import Stage.Parse.Lexer as Lexer +import Test exposing (Test, describe, fuzz, test) + + +tests = + describe "parser lexer test" + [ describe "helpers" + [ fuzz (Fuzz.list Fuzz.int) "collectList" <| + \ls -> + ls + |> Contextualize.collectList Ok + |> Expect.equal (Ok ls) + ] + , describe "generated test cases" + [ describe "lexing" + ((ParserLexerTestCases.shouldParseTestCases ++ ParserLexerTestCases.shouldNotParseTestCases) + |> List.map + (\{ name, source, lexed } -> + test name <| + \() -> + source + |> P.run Lexer.parser + |> Expect.equal (lexed |> Result.mapError never) + ) + ) + , describe "test cases are up to date" + (ParserLexerTestCases.shouldNotParseTestCases + ++ ParserLexerTestCases.shouldParseTestCases + |> List.map + (\{ name, source, lexed, contextualized } -> + test name <| + \() -> + case ( lexed, contextualized ) of + ( Ok lexed_, Just contextualized_ ) -> + lexed_ + |> Contextualize.run + |> Expect.equal contextualized_ + + ( Err _, _ ) -> + Expect.fail "bug: cannot lex" + + ( Ok _, Nothing ) -> + Expect.fail "bug: cannot lex" + ) + ) + , describe "should parse" + (ParserLexerTestCases.shouldParseTestCases + |> List.map + (\{ name, source, lexed, contextualized } -> + test name <| + \() -> + case ( lexed, contextualized ) of + ( Ok lexed_, Just contextualized_ ) -> + () + |> Expect.all + (lexed_ + |> Contextualize.run + |> List.map + (\rBlock () -> + case rBlock of + Ok _ -> + Expect.pass + + Err _ -> + Expect.fail "it does not parse" + ) + ) + + ( Err _, _ ) -> + Expect.fail "bug: cannot lex" + + ( Ok _, Nothing ) -> + Expect.fail "bug: cannot lex" + ) + ) + , describe "should not parse" + (ParserLexerTestCases.shouldNotParseTestCases + |> List.map + (\{ name, source, lexed, contextualized } -> + test name <| + \() -> + case ( lexed, contextualized ) of + ( Ok lexed_, Just contextualized_ ) -> + () + |> Expect.all + (lexed_ + |> Contextualize.run + |> List.map + (\rBlock () -> + case rBlock of + Ok _ -> + Expect.fail "it did parse" + + Err _ -> + Expect.pass + ) + ) + + ( Err _, _ ) -> + Expect.fail "bug: cannot lex" + + ( Ok _, Nothing ) -> + Expect.fail "bug: cannot lex" + ) + ) + ] + ] diff --git a/tests/ParserLexerTestCases.elm b/tests/ParserLexerTestCases.elm new file mode 100644 index 00000000..8a89e910 --- /dev/null +++ b/tests/ParserLexerTestCases.elm @@ -0,0 +1,5671 @@ +module ParserLexerTestCases exposing (shouldNotParseTestCases, shouldParseTestCases) + +import Dict +import Elm.AST.Frontend as Frontend +import Elm.Data.Located exposing (Located(..)) +import Elm.Data.Operator exposing (Operator(..)) +import Elm.Data.Qualifiedness exposing (PossiblyQualified(..)) +import Elm.Data.Type.Concrete exposing (ConcreteType(..)) +import Stage.Parse.Contextualize as Contextualize exposing (..) +import Stage.Parse.Lexer exposing (..) +import Stage.Parse.Token exposing (Keyword(..), LowerCase(..), Token(..), UpperCase(..)) + + + +-- AUTO GENERATED TEST CASES +-- +-- Do not edit below this line or your changes will be overwritten by +-- tests/parser-tests/update.js + + +shouldParseTestCases : + List + { contextualized : Maybe (List Contextualize.RunResult) + , pretty : String + , lexed : Result Never (List (Located LexItem)) + , name : String + , source : String + } +shouldParseTestCases = + [ { name = "expression-int" + , source = """a = 5 + +b = 78 +""" + , pretty = """ + ( ( Ok + , ( ValueDeclaration + , ( name, a ) + , ( args, () ) + , ( valueExpr__ + , ( Int, 5 ) + ) + ) + ) + , ( Ok + , ( ValueDeclaration + , ( name, b ) + , ( args, () ) + , ( valueExpr__ + , ( Int, 78 ) + ) + ) + ) + ) +""" + , contextualized = + Just + [ Ok (ValueDeclaration { args = [], name = Located { end = { col = 2, row = 1 }, start = { col = 1, row = 1 } } (LowerCase "a"), valueExpr__ = Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Frontend.Int 5) }) + , Ok (ValueDeclaration { args = [], name = Located { end = { col = 2, row = 3 }, start = { col = 1, row = 3 } } (LowerCase "b"), valueExpr__ = Located { end = { col = 7, row = 3 }, start = { col = 5, row = 3 } } (Frontend.Int 78) }) + ] + , lexed = + Ok + [ Located { end = { col = 2, row = 1 }, start = { col = 1, row = 1 } } (Token (Identifier { name = TokenLowerCase (LowerCase "a"), qualifiers = [] })) + , Located { end = { col = 3, row = 1 }, start = { col = 2, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 4, row = 1 }, start = { col = 3, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 5, row = 1 }, start = { col = 4, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Token (NumericLiteral "5")) + , Located { end = { col = 1, row = 3 }, start = { col = 6, row = 1 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 2, row = 3 }, start = { col = 1, row = 3 } } (Token (Identifier { name = TokenLowerCase (LowerCase "b"), qualifiers = [] })) + , Located { end = { col = 3, row = 3 }, start = { col = 2, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 4, row = 3 }, start = { col = 3, row = 3 } } (Token (Sigil Assign)) + , Located { end = { col = 5, row = 3 }, start = { col = 4, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 7, row = 3 }, start = { col = 5, row = 3 } } (Token (NumericLiteral "78")) + , Located { end = { col = 1, row = 4 }, start = { col = 7, row = 3 } } (Newlines [] 0) + ] + } + , { name = "expression-int-add" + , source = """a = 5 + 5 + +b = 78 + 5 + 2+ 4 +""" + , pretty = """ + ( ( Ok + , ( ValueDeclaration + , ( name, a ) + , ( args, () ) + , ( valueExpr__ + , ( Operator + , ( ( op, + ) + , ( lhs + , ( Int, 5 ) + ) + , ( rhs + , ( Int, 5 ) + ) + ) + ) + ) + ) + ) + , ( Ok + , ( ValueDeclaration + , ( name, b ) + , ( args, () ) + , ( valueExpr__ + , ( Operator + , ( ( op, + ) + , ( lhs + , ( Operator + , ( ( op, + ) + , ( lhs + , ( Operator + , ( ( op, + ) + , ( lhs + , ( Int, 78 ) + ) + , ( rhs + , ( Int, 5 ) + ) + ) + ) + ) + , ( rhs + , ( Int, 2 ) + ) + ) + ) + ) + , ( rhs + , ( Int, 4 ) + ) + ) + ) + ) + ) + ) + ) +""" + , contextualized = + Just + [ Ok (ValueDeclaration { args = [], name = Located { end = { col = 2, row = 1 }, start = { col = 1, row = 1 } } (LowerCase "a"), valueExpr__ = Located { end = { col = 10, row = 1 }, start = { col = 5, row = 1 } } (Frontend.Operator (Located { end = { col = 8, row = 1 }, start = { col = 7, row = 1 } } Add) (Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Frontend.Int 5)) (Located { end = { col = 10, row = 1 }, start = { col = 9, row = 1 } } (Frontend.Int 5))) }) + , Ok (ValueDeclaration { args = [], name = Located { end = { col = 2, row = 3 }, start = { col = 1, row = 3 } } (LowerCase "b"), valueExpr__ = Located { end = { col = 18, row = 3 }, start = { col = 5, row = 3 } } (Frontend.Operator (Located { end = { col = 16, row = 3 }, start = { col = 15, row = 3 } } Add) (Located { end = { col = 15, row = 3 }, start = { col = 5, row = 3 } } (Frontend.Operator (Located { end = { col = 13, row = 3 }, start = { col = 12, row = 3 } } Add) (Located { end = { col = 11, row = 3 }, start = { col = 5, row = 3 } } (Frontend.Operator (Located { end = { col = 9, row = 3 }, start = { col = 8, row = 3 } } Add) (Located { end = { col = 7, row = 3 }, start = { col = 5, row = 3 } } (Frontend.Int 78)) (Located { end = { col = 11, row = 3 }, start = { col = 10, row = 3 } } (Frontend.Int 5)))) (Located { end = { col = 15, row = 3 }, start = { col = 14, row = 3 } } (Frontend.Int 2)))) (Located { end = { col = 18, row = 3 }, start = { col = 17, row = 3 } } (Frontend.Int 4))) }) + ] + , lexed = + Ok + [ Located { end = { col = 2, row = 1 }, start = { col = 1, row = 1 } } (Token (Identifier { name = TokenLowerCase (LowerCase "a"), qualifiers = [] })) + , Located { end = { col = 3, row = 1 }, start = { col = 2, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 4, row = 1 }, start = { col = 3, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 5, row = 1 }, start = { col = 4, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Token (NumericLiteral "5")) + , Located { end = { col = 7, row = 1 }, start = { col = 6, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 8, row = 1 }, start = { col = 7, row = 1 } } (Token (Sigil (Operator Add))) + , Located { end = { col = 9, row = 1 }, start = { col = 8, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 10, row = 1 }, start = { col = 9, row = 1 } } (Token (NumericLiteral "5")) + , Located { end = { col = 1, row = 3 }, start = { col = 10, row = 1 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 2, row = 3 }, start = { col = 1, row = 3 } } (Token (Identifier { name = TokenLowerCase (LowerCase "b"), qualifiers = [] })) + , Located { end = { col = 3, row = 3 }, start = { col = 2, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 4, row = 3 }, start = { col = 3, row = 3 } } (Token (Sigil Assign)) + , Located { end = { col = 5, row = 3 }, start = { col = 4, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 7, row = 3 }, start = { col = 5, row = 3 } } (Token (NumericLiteral "78")) + , Located { end = { col = 8, row = 3 }, start = { col = 7, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 9, row = 3 }, start = { col = 8, row = 3 } } (Token (Sigil (Operator Add))) + , Located { end = { col = 10, row = 3 }, start = { col = 9, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 3 }, start = { col = 10, row = 3 } } (Token (NumericLiteral "5")) + , Located { end = { col = 12, row = 3 }, start = { col = 11, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 13, row = 3 }, start = { col = 12, row = 3 } } (Token (Sigil (Operator Add))) + , Located { end = { col = 14, row = 3 }, start = { col = 13, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 15, row = 3 }, start = { col = 14, row = 3 } } (Token (NumericLiteral "2")) + , Located { end = { col = 16, row = 3 }, start = { col = 15, row = 3 } } (Token (Sigil (Operator Add))) + , Located { end = { col = 17, row = 3 }, start = { col = 16, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 3 }, start = { col = 17, row = 3 } } (Token (NumericLiteral "4")) + , Located { end = { col = 1, row = 4 }, start = { col = 18, row = 3 } } (Newlines [] 0) + ] + } + , { name = "expression-int-multiply" + , source = """a = 5 * 5 + +b = 78 * 5 * 2 / 4 * 5 +""" + , pretty = """ + ( ( Ok + , ( ValueDeclaration + , ( name, a ) + , ( args, () ) + , ( valueExpr__ + , ( Operator + , ( ( op, * ) + , ( lhs + , ( Int, 5 ) + ) + , ( rhs + , ( Int, 5 ) + ) + ) + ) + ) + ) + ) + , ( Ok + , ( ValueDeclaration + , ( name, b ) + , ( args, () ) + , ( valueExpr__ + , ( Operator + , ( ( op, * ) + , ( lhs + , ( Operator + , ( ( op, / ) + , ( lhs + , ( Operator + , ( ( op, * ) + , ( lhs + , ( Operator + , ( ( op, * ) + , ( lhs + , ( Int, 78 ) + ) + , ( rhs + , ( Int, 5 ) + ) + ) + ) + ) + , ( rhs + , ( Int, 2 ) + ) + ) + ) + ) + , ( rhs + , ( Int, 4 ) + ) + ) + ) + ) + , ( rhs + , ( Int, 5 ) + ) + ) + ) + ) + ) + ) + ) +""" + , contextualized = + Just + [ Ok (ValueDeclaration { args = [], name = Located { end = { col = 2, row = 1 }, start = { col = 1, row = 1 } } (LowerCase "a"), valueExpr__ = Located { end = { col = 10, row = 1 }, start = { col = 5, row = 1 } } (Frontend.Operator (Located { end = { col = 8, row = 1 }, start = { col = 7, row = 1 } } Multiply) (Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Frontend.Int 5)) (Located { end = { col = 10, row = 1 }, start = { col = 9, row = 1 } } (Frontend.Int 5))) }) + , Ok (ValueDeclaration { args = [], name = Located { end = { col = 2, row = 3 }, start = { col = 1, row = 3 } } (LowerCase "b"), valueExpr__ = Located { end = { col = 23, row = 3 }, start = { col = 5, row = 3 } } (Frontend.Operator (Located { end = { col = 21, row = 3 }, start = { col = 20, row = 3 } } Multiply) (Located { end = { col = 19, row = 3 }, start = { col = 5, row = 3 } } (Frontend.Operator (Located { end = { col = 17, row = 3 }, start = { col = 16, row = 3 } } Divide) (Located { end = { col = 15, row = 3 }, start = { col = 5, row = 3 } } (Frontend.Operator (Located { end = { col = 13, row = 3 }, start = { col = 12, row = 3 } } Multiply) (Located { end = { col = 11, row = 3 }, start = { col = 5, row = 3 } } (Frontend.Operator (Located { end = { col = 9, row = 3 }, start = { col = 8, row = 3 } } Multiply) (Located { end = { col = 7, row = 3 }, start = { col = 5, row = 3 } } (Frontend.Int 78)) (Located { end = { col = 11, row = 3 }, start = { col = 10, row = 3 } } (Frontend.Int 5)))) (Located { end = { col = 15, row = 3 }, start = { col = 14, row = 3 } } (Frontend.Int 2)))) (Located { end = { col = 19, row = 3 }, start = { col = 18, row = 3 } } (Frontend.Int 4)))) (Located { end = { col = 23, row = 3 }, start = { col = 22, row = 3 } } (Frontend.Int 5))) }) + ] + , lexed = + Ok + [ Located { end = { col = 2, row = 1 }, start = { col = 1, row = 1 } } (Token (Identifier { name = TokenLowerCase (LowerCase "a"), qualifiers = [] })) + , Located { end = { col = 3, row = 1 }, start = { col = 2, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 4, row = 1 }, start = { col = 3, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 5, row = 1 }, start = { col = 4, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Token (NumericLiteral "5")) + , Located { end = { col = 7, row = 1 }, start = { col = 6, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 8, row = 1 }, start = { col = 7, row = 1 } } (Token (Sigil (Operator Multiply))) + , Located { end = { col = 9, row = 1 }, start = { col = 8, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 10, row = 1 }, start = { col = 9, row = 1 } } (Token (NumericLiteral "5")) + , Located { end = { col = 1, row = 3 }, start = { col = 10, row = 1 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 2, row = 3 }, start = { col = 1, row = 3 } } (Token (Identifier { name = TokenLowerCase (LowerCase "b"), qualifiers = [] })) + , Located { end = { col = 3, row = 3 }, start = { col = 2, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 4, row = 3 }, start = { col = 3, row = 3 } } (Token (Sigil Assign)) + , Located { end = { col = 5, row = 3 }, start = { col = 4, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 7, row = 3 }, start = { col = 5, row = 3 } } (Token (NumericLiteral "78")) + , Located { end = { col = 8, row = 3 }, start = { col = 7, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 9, row = 3 }, start = { col = 8, row = 3 } } (Token (Sigil (Operator Multiply))) + , Located { end = { col = 10, row = 3 }, start = { col = 9, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 3 }, start = { col = 10, row = 3 } } (Token (NumericLiteral "5")) + , Located { end = { col = 12, row = 3 }, start = { col = 11, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 13, row = 3 }, start = { col = 12, row = 3 } } (Token (Sigil (Operator Multiply))) + , Located { end = { col = 14, row = 3 }, start = { col = 13, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 15, row = 3 }, start = { col = 14, row = 3 } } (Token (NumericLiteral "2")) + , Located { end = { col = 16, row = 3 }, start = { col = 15, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 17, row = 3 }, start = { col = 16, row = 3 } } (Token (Sigil (Operator Divide))) + , Located { end = { col = 18, row = 3 }, start = { col = 17, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 19, row = 3 }, start = { col = 18, row = 3 } } (Token (NumericLiteral "4")) + , Located { end = { col = 20, row = 3 }, start = { col = 19, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 21, row = 3 }, start = { col = 20, row = 3 } } (Token (Sigil (Operator Multiply))) + , Located { end = { col = 22, row = 3 }, start = { col = 21, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 23, row = 3 }, start = { col = 22, row = 3 } } (Token (NumericLiteral "5")) + , Located { end = { col = 1, row = 4 }, start = { col = 23, row = 3 } } (Newlines [] 0) + ] + } + , { name = "expression-int-multiply-and-add" + , source = """a = 5 * 5 + 6 +a1 = 7 + 5 * 5 +a11 = 7 + 5 * 5 + 6 +a2 = 100 + 5 * 5 +a3 = 345 * 2234 + 2342 * 1010 + + +b = 78 + 5 * 2 / 4 * 5 +b1 = 78 * 5 * 2 / 4 - 5 +b2 = 78 * 5 - 2 / 4 * 5 +b3 = 78 - 5 + 2 / 4 * 5 +b4 = 78 / 5 / 2 / 4 + 5 + +""" + , pretty = """ + ( ( Ok + , ( ValueDeclaration + , ( name, a ) + , ( args, () ) + , ( valueExpr__ + , ( Operator + , ( ( op, + ) + , ( lhs + , ( Operator + , ( ( op, * ) + , ( lhs + , ( Int, 5 ) + ) + , ( rhs + , ( Int, 5 ) + ) + ) + ) + ) + , ( rhs + , ( Int, 6 ) + ) + ) + ) + ) + ) + ) + , ( Ok + , ( ValueDeclaration + , ( name, a1 ) + , ( args, () ) + , ( valueExpr__ + , ( Operator + , ( ( op, + ) + , ( lhs + , ( Int, 7 ) + ) + , ( rhs + , ( Operator + , ( ( op, * ) + , ( lhs + , ( Int, 5 ) + ) + , ( rhs + , ( Int, 5 ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + , ( Ok + , ( ValueDeclaration + , ( name, a11 ) + , ( args, () ) + , ( valueExpr__ + , ( Operator + , ( ( op, + ) + , ( lhs + , ( Int, 7 ) + ) + , ( rhs + , ( Operator + , ( ( op, + ) + , ( lhs + , ( Operator + , ( ( op, * ) + , ( lhs + , ( Int, 5 ) + ) + , ( rhs + , ( Int, 5 ) + ) + ) + ) + ) + , ( rhs + , ( Int, 6 ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + , ( Ok + , ( ValueDeclaration + , ( name, a2 ) + , ( args, () ) + , ( valueExpr__ + , ( Operator + , ( ( op, + ) + , ( lhs + , ( Int, 100 ) + ) + , ( rhs + , ( Operator + , ( ( op, * ) + , ( lhs + , ( Int, 5 ) + ) + , ( rhs + , ( Int, 5 ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + , ( Ok + , ( ValueDeclaration + , ( name, a3 ) + , ( args, () ) + , ( valueExpr__ + , ( Operator + , ( ( op, + ) + , ( lhs + , ( Operator + , ( ( op, * ) + , ( lhs + , ( Int, 345 ) + ) + , ( rhs + , ( Int, 2234 ) + ) + ) + ) + ) + , ( rhs + , ( Operator + , ( ( op, * ) + , ( lhs + , ( Int, 2342 ) + ) + , ( rhs + , ( Int, 1010 ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + , ( Ok + , ( ValueDeclaration + , ( name, b ) + , ( args, () ) + , ( valueExpr__ + , ( Operator + , ( ( op, + ) + , ( lhs + , ( Int, 78 ) + ) + , ( rhs + , ( Operator + , ( ( op, * ) + , ( lhs + , ( Operator + , ( ( op, / ) + , ( lhs + , ( Operator + , ( ( op, * ) + , ( lhs + , ( Int, 5 ) + ) + , ( rhs + , ( Int, 2 ) + ) + ) + ) + ) + , ( rhs + , ( Int, 4 ) + ) + ) + ) + ) + , ( rhs + , ( Int, 5 ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + , ( Ok + , ( ValueDeclaration + , ( name, b1 ) + , ( args, () ) + , ( valueExpr__ + , ( Operator + , ( ( op, - ) + , ( lhs + , ( Operator + , ( ( op, / ) + , ( lhs + , ( Operator + , ( ( op, * ) + , ( lhs + , ( Operator + , ( ( op, * ) + , ( lhs + , ( Int, 78 ) + ) + , ( rhs + , ( Int, 5 ) + ) + ) + ) + ) + , ( rhs + , ( Int, 2 ) + ) + ) + ) + ) + , ( rhs + , ( Int, 4 ) + ) + ) + ) + ) + , ( rhs + , ( Int, 5 ) + ) + ) + ) + ) + ) + ) + , ( Ok + , ( ValueDeclaration + , ( name, b2 ) + , ( args, () ) + , ( valueExpr__ + , ( Operator + , ( ( op, - ) + , ( lhs + , ( Operator + , ( ( op, * ) + , ( lhs + , ( Int, 78 ) + ) + , ( rhs + , ( Int, 5 ) + ) + ) + ) + ) + , ( rhs + , ( Operator + , ( ( op, * ) + , ( lhs + , ( Operator + , ( ( op, / ) + , ( lhs + , ( Int, 2 ) + ) + , ( rhs + , ( Int, 4 ) + ) + ) + ) + ) + , ( rhs + , ( Int, 5 ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + , ( Ok + , ( ValueDeclaration + , ( name, b3 ) + , ( args, () ) + , ( valueExpr__ + , ( Operator + , ( ( op, + ) + , ( lhs + , ( Operator + , ( ( op, - ) + , ( lhs + , ( Int, 78 ) + ) + , ( rhs + , ( Int, 5 ) + ) + ) + ) + ) + , ( rhs + , ( Operator + , ( ( op, * ) + , ( lhs + , ( Operator + , ( ( op, / ) + , ( lhs + , ( Int, 2 ) + ) + , ( rhs + , ( Int, 4 ) + ) + ) + ) + ) + , ( rhs + , ( Int, 5 ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + , ( Ok + , ( ValueDeclaration + , ( name, b4 ) + , ( args, () ) + , ( valueExpr__ + , ( Operator + , ( ( op, + ) + , ( lhs + , ( Operator + , ( ( op, / ) + , ( lhs + , ( Operator + , ( ( op, / ) + , ( lhs + , ( Operator + , ( ( op, / ) + , ( lhs + , ( Int, 78 ) + ) + , ( rhs + , ( Int, 5 ) + ) + ) + ) + ) + , ( rhs + , ( Int, 2 ) + ) + ) + ) + ) + , ( rhs + , ( Int, 4 ) + ) + ) + ) + ) + , ( rhs + , ( Int, 5 ) + ) + ) + ) + ) + ) + ) + ) +""" + , contextualized = + Just + [ Ok (ValueDeclaration { args = [], name = Located { end = { col = 2, row = 1 }, start = { col = 1, row = 1 } } (LowerCase "a"), valueExpr__ = Located { end = { col = 14, row = 1 }, start = { col = 5, row = 1 } } (Frontend.Operator (Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } Add) (Located { end = { col = 10, row = 1 }, start = { col = 5, row = 1 } } (Frontend.Operator (Located { end = { col = 8, row = 1 }, start = { col = 7, row = 1 } } Multiply) (Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Frontend.Int 5)) (Located { end = { col = 10, row = 1 }, start = { col = 9, row = 1 } } (Frontend.Int 5)))) (Located { end = { col = 14, row = 1 }, start = { col = 13, row = 1 } } (Frontend.Int 6))) }) + , Ok (ValueDeclaration { args = [], name = Located { end = { col = 3, row = 2 }, start = { col = 1, row = 2 } } (LowerCase "a1"), valueExpr__ = Located { end = { col = 16, row = 2 }, start = { col = 7, row = 2 } } (Frontend.Operator (Located { end = { col = 10, row = 2 }, start = { col = 9, row = 2 } } Add) (Located { end = { col = 8, row = 2 }, start = { col = 7, row = 2 } } (Frontend.Int 7)) (Located { end = { col = 16, row = 2 }, start = { col = 11, row = 2 } } (Frontend.Operator (Located { end = { col = 14, row = 2 }, start = { col = 13, row = 2 } } Multiply) (Located { end = { col = 12, row = 2 }, start = { col = 11, row = 2 } } (Frontend.Int 5)) (Located { end = { col = 16, row = 2 }, start = { col = 15, row = 2 } } (Frontend.Int 5))))) }) + , Ok (ValueDeclaration { args = [], name = Located { end = { col = 4, row = 3 }, start = { col = 1, row = 3 } } (LowerCase "a11"), valueExpr__ = Located { end = { col = 21, row = 3 }, start = { col = 8, row = 3 } } (Frontend.Operator (Located { end = { col = 11, row = 3 }, start = { col = 10, row = 3 } } Add) (Located { end = { col = 9, row = 3 }, start = { col = 8, row = 3 } } (Frontend.Int 7)) (Located { end = { col = 21, row = 3 }, start = { col = 12, row = 3 } } (Frontend.Operator (Located { end = { col = 19, row = 3 }, start = { col = 18, row = 3 } } Add) (Located { end = { col = 17, row = 3 }, start = { col = 12, row = 3 } } (Frontend.Operator (Located { end = { col = 15, row = 3 }, start = { col = 14, row = 3 } } Multiply) (Located { end = { col = 13, row = 3 }, start = { col = 12, row = 3 } } (Frontend.Int 5)) (Located { end = { col = 17, row = 3 }, start = { col = 16, row = 3 } } (Frontend.Int 5)))) (Located { end = { col = 21, row = 3 }, start = { col = 20, row = 3 } } (Frontend.Int 6))))) }) + , Ok (ValueDeclaration { args = [], name = Located { end = { col = 3, row = 4 }, start = { col = 1, row = 4 } } (LowerCase "a2"), valueExpr__ = Located { end = { col = 18, row = 4 }, start = { col = 6, row = 4 } } (Frontend.Operator (Located { end = { col = 12, row = 4 }, start = { col = 11, row = 4 } } Add) (Located { end = { col = 9, row = 4 }, start = { col = 6, row = 4 } } (Frontend.Int 100)) (Located { end = { col = 18, row = 4 }, start = { col = 13, row = 4 } } (Frontend.Operator (Located { end = { col = 16, row = 4 }, start = { col = 15, row = 4 } } Multiply) (Located { end = { col = 14, row = 4 }, start = { col = 13, row = 4 } } (Frontend.Int 5)) (Located { end = { col = 18, row = 4 }, start = { col = 17, row = 4 } } (Frontend.Int 5))))) }) + , Ok (ValueDeclaration { args = [], name = Located { end = { col = 3, row = 5 }, start = { col = 1, row = 5 } } (LowerCase "a3"), valueExpr__ = Located { end = { col = 30, row = 5 }, start = { col = 6, row = 5 } } (Frontend.Operator (Located { end = { col = 18, row = 5 }, start = { col = 17, row = 5 } } Add) (Located { end = { col = 16, row = 5 }, start = { col = 6, row = 5 } } (Frontend.Operator (Located { end = { col = 11, row = 5 }, start = { col = 10, row = 5 } } Multiply) (Located { end = { col = 9, row = 5 }, start = { col = 6, row = 5 } } (Frontend.Int 345)) (Located { end = { col = 16, row = 5 }, start = { col = 12, row = 5 } } (Frontend.Int 2234)))) (Located { end = { col = 30, row = 5 }, start = { col = 19, row = 5 } } (Frontend.Operator (Located { end = { col = 25, row = 5 }, start = { col = 24, row = 5 } } Multiply) (Located { end = { col = 23, row = 5 }, start = { col = 19, row = 5 } } (Frontend.Int 2342)) (Located { end = { col = 30, row = 5 }, start = { col = 26, row = 5 } } (Frontend.Int 1010))))) }) + , Ok (ValueDeclaration { args = [], name = Located { end = { col = 2, row = 8 }, start = { col = 1, row = 8 } } (LowerCase "b"), valueExpr__ = Located { end = { col = 23, row = 8 }, start = { col = 5, row = 8 } } (Frontend.Operator (Located { end = { col = 9, row = 8 }, start = { col = 8, row = 8 } } Add) (Located { end = { col = 7, row = 8 }, start = { col = 5, row = 8 } } (Frontend.Int 78)) (Located { end = { col = 23, row = 8 }, start = { col = 10, row = 8 } } (Frontend.Operator (Located { end = { col = 21, row = 8 }, start = { col = 20, row = 8 } } Multiply) (Located { end = { col = 19, row = 8 }, start = { col = 10, row = 8 } } (Frontend.Operator (Located { end = { col = 17, row = 8 }, start = { col = 16, row = 8 } } Divide) (Located { end = { col = 15, row = 8 }, start = { col = 10, row = 8 } } (Frontend.Operator (Located { end = { col = 13, row = 8 }, start = { col = 12, row = 8 } } Multiply) (Located { end = { col = 11, row = 8 }, start = { col = 10, row = 8 } } (Frontend.Int 5)) (Located { end = { col = 15, row = 8 }, start = { col = 14, row = 8 } } (Frontend.Int 2)))) (Located { end = { col = 19, row = 8 }, start = { col = 18, row = 8 } } (Frontend.Int 4)))) (Located { end = { col = 23, row = 8 }, start = { col = 22, row = 8 } } (Frontend.Int 5))))) }) + , Ok (ValueDeclaration { args = [], name = Located { end = { col = 3, row = 9 }, start = { col = 1, row = 9 } } (LowerCase "b1"), valueExpr__ = Located { end = { col = 24, row = 9 }, start = { col = 6, row = 9 } } (Frontend.Operator (Located { end = { col = 22, row = 9 }, start = { col = 21, row = 9 } } Subtract) (Located { end = { col = 20, row = 9 }, start = { col = 6, row = 9 } } (Frontend.Operator (Located { end = { col = 18, row = 9 }, start = { col = 17, row = 9 } } Divide) (Located { end = { col = 16, row = 9 }, start = { col = 6, row = 9 } } (Frontend.Operator (Located { end = { col = 14, row = 9 }, start = { col = 13, row = 9 } } Multiply) (Located { end = { col = 12, row = 9 }, start = { col = 6, row = 9 } } (Frontend.Operator (Located { end = { col = 10, row = 9 }, start = { col = 9, row = 9 } } Multiply) (Located { end = { col = 8, row = 9 }, start = { col = 6, row = 9 } } (Frontend.Int 78)) (Located { end = { col = 12, row = 9 }, start = { col = 11, row = 9 } } (Frontend.Int 5)))) (Located { end = { col = 16, row = 9 }, start = { col = 15, row = 9 } } (Frontend.Int 2)))) (Located { end = { col = 20, row = 9 }, start = { col = 19, row = 9 } } (Frontend.Int 4)))) (Located { end = { col = 24, row = 9 }, start = { col = 23, row = 9 } } (Frontend.Int 5))) }) + , Ok (ValueDeclaration { args = [], name = Located { end = { col = 3, row = 10 }, start = { col = 1, row = 10 } } (LowerCase "b2"), valueExpr__ = Located { end = { col = 24, row = 10 }, start = { col = 6, row = 10 } } (Frontend.Operator (Located { end = { col = 14, row = 10 }, start = { col = 13, row = 10 } } Subtract) (Located { end = { col = 12, row = 10 }, start = { col = 6, row = 10 } } (Frontend.Operator (Located { end = { col = 10, row = 10 }, start = { col = 9, row = 10 } } Multiply) (Located { end = { col = 8, row = 10 }, start = { col = 6, row = 10 } } (Frontend.Int 78)) (Located { end = { col = 12, row = 10 }, start = { col = 11, row = 10 } } (Frontend.Int 5)))) (Located { end = { col = 24, row = 10 }, start = { col = 15, row = 10 } } (Frontend.Operator (Located { end = { col = 22, row = 10 }, start = { col = 21, row = 10 } } Multiply) (Located { end = { col = 20, row = 10 }, start = { col = 15, row = 10 } } (Frontend.Operator (Located { end = { col = 18, row = 10 }, start = { col = 17, row = 10 } } Divide) (Located { end = { col = 16, row = 10 }, start = { col = 15, row = 10 } } (Frontend.Int 2)) (Located { end = { col = 20, row = 10 }, start = { col = 19, row = 10 } } (Frontend.Int 4)))) (Located { end = { col = 24, row = 10 }, start = { col = 23, row = 10 } } (Frontend.Int 5))))) }) + , Ok (ValueDeclaration { args = [], name = Located { end = { col = 3, row = 11 }, start = { col = 1, row = 11 } } (LowerCase "b3"), valueExpr__ = Located { end = { col = 24, row = 11 }, start = { col = 6, row = 11 } } (Frontend.Operator (Located { end = { col = 14, row = 11 }, start = { col = 13, row = 11 } } Add) (Located { end = { col = 12, row = 11 }, start = { col = 6, row = 11 } } (Frontend.Operator (Located { end = { col = 10, row = 11 }, start = { col = 9, row = 11 } } Subtract) (Located { end = { col = 8, row = 11 }, start = { col = 6, row = 11 } } (Frontend.Int 78)) (Located { end = { col = 12, row = 11 }, start = { col = 11, row = 11 } } (Frontend.Int 5)))) (Located { end = { col = 24, row = 11 }, start = { col = 15, row = 11 } } (Frontend.Operator (Located { end = { col = 22, row = 11 }, start = { col = 21, row = 11 } } Multiply) (Located { end = { col = 20, row = 11 }, start = { col = 15, row = 11 } } (Frontend.Operator (Located { end = { col = 18, row = 11 }, start = { col = 17, row = 11 } } Divide) (Located { end = { col = 16, row = 11 }, start = { col = 15, row = 11 } } (Frontend.Int 2)) (Located { end = { col = 20, row = 11 }, start = { col = 19, row = 11 } } (Frontend.Int 4)))) (Located { end = { col = 24, row = 11 }, start = { col = 23, row = 11 } } (Frontend.Int 5))))) }) + , Ok (ValueDeclaration { args = [], name = Located { end = { col = 3, row = 12 }, start = { col = 1, row = 12 } } (LowerCase "b4"), valueExpr__ = Located { end = { col = 24, row = 12 }, start = { col = 6, row = 12 } } (Frontend.Operator (Located { end = { col = 22, row = 12 }, start = { col = 21, row = 12 } } Add) (Located { end = { col = 20, row = 12 }, start = { col = 6, row = 12 } } (Frontend.Operator (Located { end = { col = 18, row = 12 }, start = { col = 17, row = 12 } } Divide) (Located { end = { col = 16, row = 12 }, start = { col = 6, row = 12 } } (Frontend.Operator (Located { end = { col = 14, row = 12 }, start = { col = 13, row = 12 } } Divide) (Located { end = { col = 12, row = 12 }, start = { col = 6, row = 12 } } (Frontend.Operator (Located { end = { col = 10, row = 12 }, start = { col = 9, row = 12 } } Divide) (Located { end = { col = 8, row = 12 }, start = { col = 6, row = 12 } } (Frontend.Int 78)) (Located { end = { col = 12, row = 12 }, start = { col = 11, row = 12 } } (Frontend.Int 5)))) (Located { end = { col = 16, row = 12 }, start = { col = 15, row = 12 } } (Frontend.Int 2)))) (Located { end = { col = 20, row = 12 }, start = { col = 19, row = 12 } } (Frontend.Int 4)))) (Located { end = { col = 24, row = 12 }, start = { col = 23, row = 12 } } (Frontend.Int 5))) }) + ] + , lexed = + Ok + [ Located { end = { col = 2, row = 1 }, start = { col = 1, row = 1 } } (Token (Identifier { name = TokenLowerCase (LowerCase "a"), qualifiers = [] })) + , Located { end = { col = 3, row = 1 }, start = { col = 2, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 4, row = 1 }, start = { col = 3, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 5, row = 1 }, start = { col = 4, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Token (NumericLiteral "5")) + , Located { end = { col = 7, row = 1 }, start = { col = 6, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 8, row = 1 }, start = { col = 7, row = 1 } } (Token (Sigil (Operator Multiply))) + , Located { end = { col = 9, row = 1 }, start = { col = 8, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 10, row = 1 }, start = { col = 9, row = 1 } } (Token (NumericLiteral "5")) + , Located { end = { col = 11, row = 1 }, start = { col = 10, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Token (Sigil (Operator Add))) + , Located { end = { col = 13, row = 1 }, start = { col = 12, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 1 }, start = { col = 13, row = 1 } } (Token (NumericLiteral "6")) + , Located { end = { col = 1, row = 2 }, start = { col = 14, row = 1 } } (Newlines [] 0) + , Located { end = { col = 3, row = 2 }, start = { col = 1, row = 2 } } (Token (Identifier { name = TokenLowerCase (LowerCase "a1"), qualifiers = [] })) + , Located { end = { col = 4, row = 2 }, start = { col = 3, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 5, row = 2 }, start = { col = 4, row = 2 } } (Token (Sigil Assign)) + , Located { end = { col = 7, row = 2 }, start = { col = 5, row = 2 } } (Ignorable (Whitespace 2)) + , Located { end = { col = 8, row = 2 }, start = { col = 7, row = 2 } } (Token (NumericLiteral "7")) + , Located { end = { col = 9, row = 2 }, start = { col = 8, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 10, row = 2 }, start = { col = 9, row = 2 } } (Token (Sigil (Operator Add))) + , Located { end = { col = 11, row = 2 }, start = { col = 10, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 12, row = 2 }, start = { col = 11, row = 2 } } (Token (NumericLiteral "5")) + , Located { end = { col = 13, row = 2 }, start = { col = 12, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 2 }, start = { col = 13, row = 2 } } (Token (Sigil (Operator Multiply))) + , Located { end = { col = 15, row = 2 }, start = { col = 14, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 2 }, start = { col = 15, row = 2 } } (Token (NumericLiteral "5")) + , Located { end = { col = 1, row = 3 }, start = { col = 16, row = 2 } } (Newlines [] 0) + , Located { end = { col = 4, row = 3 }, start = { col = 1, row = 3 } } (Token (Identifier { name = TokenLowerCase (LowerCase "a11"), qualifiers = [] })) + , Located { end = { col = 5, row = 3 }, start = { col = 4, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 6, row = 3 }, start = { col = 5, row = 3 } } (Token (Sigil Assign)) + , Located { end = { col = 8, row = 3 }, start = { col = 6, row = 3 } } (Ignorable (Whitespace 2)) + , Located { end = { col = 9, row = 3 }, start = { col = 8, row = 3 } } (Token (NumericLiteral "7")) + , Located { end = { col = 10, row = 3 }, start = { col = 9, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 3 }, start = { col = 10, row = 3 } } (Token (Sigil (Operator Add))) + , Located { end = { col = 12, row = 3 }, start = { col = 11, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 13, row = 3 }, start = { col = 12, row = 3 } } (Token (NumericLiteral "5")) + , Located { end = { col = 14, row = 3 }, start = { col = 13, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 15, row = 3 }, start = { col = 14, row = 3 } } (Token (Sigil (Operator Multiply))) + , Located { end = { col = 16, row = 3 }, start = { col = 15, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 17, row = 3 }, start = { col = 16, row = 3 } } (Token (NumericLiteral "5")) + , Located { end = { col = 18, row = 3 }, start = { col = 17, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 19, row = 3 }, start = { col = 18, row = 3 } } (Token (Sigil (Operator Add))) + , Located { end = { col = 20, row = 3 }, start = { col = 19, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 21, row = 3 }, start = { col = 20, row = 3 } } (Token (NumericLiteral "6")) + , Located { end = { col = 1, row = 4 }, start = { col = 21, row = 3 } } (Newlines [] 0) + , Located { end = { col = 3, row = 4 }, start = { col = 1, row = 4 } } (Token (Identifier { name = TokenLowerCase (LowerCase "a2"), qualifiers = [] })) + , Located { end = { col = 4, row = 4 }, start = { col = 3, row = 4 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 5, row = 4 }, start = { col = 4, row = 4 } } (Token (Sigil Assign)) + , Located { end = { col = 6, row = 4 }, start = { col = 5, row = 4 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 9, row = 4 }, start = { col = 6, row = 4 } } (Token (NumericLiteral "100")) + , Located { end = { col = 11, row = 4 }, start = { col = 9, row = 4 } } (Ignorable (Whitespace 2)) + , Located { end = { col = 12, row = 4 }, start = { col = 11, row = 4 } } (Token (Sigil (Operator Add))) + , Located { end = { col = 13, row = 4 }, start = { col = 12, row = 4 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 4 }, start = { col = 13, row = 4 } } (Token (NumericLiteral "5")) + , Located { end = { col = 15, row = 4 }, start = { col = 14, row = 4 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 4 }, start = { col = 15, row = 4 } } (Token (Sigil (Operator Multiply))) + , Located { end = { col = 17, row = 4 }, start = { col = 16, row = 4 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 4 }, start = { col = 17, row = 4 } } (Token (NumericLiteral "5")) + , Located { end = { col = 1, row = 5 }, start = { col = 18, row = 4 } } (Newlines [] 0) + , Located { end = { col = 3, row = 5 }, start = { col = 1, row = 5 } } (Token (Identifier { name = TokenLowerCase (LowerCase "a3"), qualifiers = [] })) + , Located { end = { col = 4, row = 5 }, start = { col = 3, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 5, row = 5 }, start = { col = 4, row = 5 } } (Token (Sigil Assign)) + , Located { end = { col = 6, row = 5 }, start = { col = 5, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 9, row = 5 }, start = { col = 6, row = 5 } } (Token (NumericLiteral "345")) + , Located { end = { col = 10, row = 5 }, start = { col = 9, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 5 }, start = { col = 10, row = 5 } } (Token (Sigil (Operator Multiply))) + , Located { end = { col = 12, row = 5 }, start = { col = 11, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 5 }, start = { col = 12, row = 5 } } (Token (NumericLiteral "2234")) + , Located { end = { col = 17, row = 5 }, start = { col = 16, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 5 }, start = { col = 17, row = 5 } } (Token (Sigil (Operator Add))) + , Located { end = { col = 19, row = 5 }, start = { col = 18, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 23, row = 5 }, start = { col = 19, row = 5 } } (Token (NumericLiteral "2342")) + , Located { end = { col = 24, row = 5 }, start = { col = 23, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 25, row = 5 }, start = { col = 24, row = 5 } } (Token (Sigil (Operator Multiply))) + , Located { end = { col = 26, row = 5 }, start = { col = 25, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 30, row = 5 }, start = { col = 26, row = 5 } } (Token (NumericLiteral "1010")) + , Located { end = { col = 1, row = 8 }, start = { col = 30, row = 5 } } + (Newlines + [ 0 + , 0 + ] + 0 + ) + , Located { end = { col = 2, row = 8 }, start = { col = 1, row = 8 } } (Token (Identifier { name = TokenLowerCase (LowerCase "b"), qualifiers = [] })) + , Located { end = { col = 3, row = 8 }, start = { col = 2, row = 8 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 4, row = 8 }, start = { col = 3, row = 8 } } (Token (Sigil Assign)) + , Located { end = { col = 5, row = 8 }, start = { col = 4, row = 8 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 7, row = 8 }, start = { col = 5, row = 8 } } (Token (NumericLiteral "78")) + , Located { end = { col = 8, row = 8 }, start = { col = 7, row = 8 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 9, row = 8 }, start = { col = 8, row = 8 } } (Token (Sigil (Operator Add))) + , Located { end = { col = 10, row = 8 }, start = { col = 9, row = 8 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 8 }, start = { col = 10, row = 8 } } (Token (NumericLiteral "5")) + , Located { end = { col = 12, row = 8 }, start = { col = 11, row = 8 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 13, row = 8 }, start = { col = 12, row = 8 } } (Token (Sigil (Operator Multiply))) + , Located { end = { col = 14, row = 8 }, start = { col = 13, row = 8 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 15, row = 8 }, start = { col = 14, row = 8 } } (Token (NumericLiteral "2")) + , Located { end = { col = 16, row = 8 }, start = { col = 15, row = 8 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 17, row = 8 }, start = { col = 16, row = 8 } } (Token (Sigil (Operator Divide))) + , Located { end = { col = 18, row = 8 }, start = { col = 17, row = 8 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 19, row = 8 }, start = { col = 18, row = 8 } } (Token (NumericLiteral "4")) + , Located { end = { col = 20, row = 8 }, start = { col = 19, row = 8 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 21, row = 8 }, start = { col = 20, row = 8 } } (Token (Sigil (Operator Multiply))) + , Located { end = { col = 22, row = 8 }, start = { col = 21, row = 8 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 23, row = 8 }, start = { col = 22, row = 8 } } (Token (NumericLiteral "5")) + , Located { end = { col = 1, row = 9 }, start = { col = 23, row = 8 } } (Newlines [] 0) + , Located { end = { col = 3, row = 9 }, start = { col = 1, row = 9 } } (Token (Identifier { name = TokenLowerCase (LowerCase "b1"), qualifiers = [] })) + , Located { end = { col = 4, row = 9 }, start = { col = 3, row = 9 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 5, row = 9 }, start = { col = 4, row = 9 } } (Token (Sigil Assign)) + , Located { end = { col = 6, row = 9 }, start = { col = 5, row = 9 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 8, row = 9 }, start = { col = 6, row = 9 } } (Token (NumericLiteral "78")) + , Located { end = { col = 9, row = 9 }, start = { col = 8, row = 9 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 10, row = 9 }, start = { col = 9, row = 9 } } (Token (Sigil (Operator Multiply))) + , Located { end = { col = 11, row = 9 }, start = { col = 10, row = 9 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 12, row = 9 }, start = { col = 11, row = 9 } } (Token (NumericLiteral "5")) + , Located { end = { col = 13, row = 9 }, start = { col = 12, row = 9 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 9 }, start = { col = 13, row = 9 } } (Token (Sigil (Operator Multiply))) + , Located { end = { col = 15, row = 9 }, start = { col = 14, row = 9 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 9 }, start = { col = 15, row = 9 } } (Token (NumericLiteral "2")) + , Located { end = { col = 17, row = 9 }, start = { col = 16, row = 9 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 9 }, start = { col = 17, row = 9 } } (Token (Sigil (Operator Divide))) + , Located { end = { col = 19, row = 9 }, start = { col = 18, row = 9 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 20, row = 9 }, start = { col = 19, row = 9 } } (Token (NumericLiteral "4")) + , Located { end = { col = 21, row = 9 }, start = { col = 20, row = 9 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 22, row = 9 }, start = { col = 21, row = 9 } } (Token (Sigil (Operator Subtract))) + , Located { end = { col = 23, row = 9 }, start = { col = 22, row = 9 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 24, row = 9 }, start = { col = 23, row = 9 } } (Token (NumericLiteral "5")) + , Located { end = { col = 1, row = 10 }, start = { col = 24, row = 9 } } (Newlines [] 0) + , Located { end = { col = 3, row = 10 }, start = { col = 1, row = 10 } } (Token (Identifier { name = TokenLowerCase (LowerCase "b2"), qualifiers = [] })) + , Located { end = { col = 4, row = 10 }, start = { col = 3, row = 10 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 5, row = 10 }, start = { col = 4, row = 10 } } (Token (Sigil Assign)) + , Located { end = { col = 6, row = 10 }, start = { col = 5, row = 10 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 8, row = 10 }, start = { col = 6, row = 10 } } (Token (NumericLiteral "78")) + , Located { end = { col = 9, row = 10 }, start = { col = 8, row = 10 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 10, row = 10 }, start = { col = 9, row = 10 } } (Token (Sigil (Operator Multiply))) + , Located { end = { col = 11, row = 10 }, start = { col = 10, row = 10 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 12, row = 10 }, start = { col = 11, row = 10 } } (Token (NumericLiteral "5")) + , Located { end = { col = 13, row = 10 }, start = { col = 12, row = 10 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 10 }, start = { col = 13, row = 10 } } (Token (Sigil (Operator Subtract))) + , Located { end = { col = 15, row = 10 }, start = { col = 14, row = 10 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 10 }, start = { col = 15, row = 10 } } (Token (NumericLiteral "2")) + , Located { end = { col = 17, row = 10 }, start = { col = 16, row = 10 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 10 }, start = { col = 17, row = 10 } } (Token (Sigil (Operator Divide))) + , Located { end = { col = 19, row = 10 }, start = { col = 18, row = 10 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 20, row = 10 }, start = { col = 19, row = 10 } } (Token (NumericLiteral "4")) + , Located { end = { col = 21, row = 10 }, start = { col = 20, row = 10 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 22, row = 10 }, start = { col = 21, row = 10 } } (Token (Sigil (Operator Multiply))) + , Located { end = { col = 23, row = 10 }, start = { col = 22, row = 10 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 24, row = 10 }, start = { col = 23, row = 10 } } (Token (NumericLiteral "5")) + , Located { end = { col = 1, row = 11 }, start = { col = 24, row = 10 } } (Newlines [] 0) + , Located { end = { col = 3, row = 11 }, start = { col = 1, row = 11 } } (Token (Identifier { name = TokenLowerCase (LowerCase "b3"), qualifiers = [] })) + , Located { end = { col = 4, row = 11 }, start = { col = 3, row = 11 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 5, row = 11 }, start = { col = 4, row = 11 } } (Token (Sigil Assign)) + , Located { end = { col = 6, row = 11 }, start = { col = 5, row = 11 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 8, row = 11 }, start = { col = 6, row = 11 } } (Token (NumericLiteral "78")) + , Located { end = { col = 9, row = 11 }, start = { col = 8, row = 11 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 10, row = 11 }, start = { col = 9, row = 11 } } (Token (Sigil (Operator Subtract))) + , Located { end = { col = 11, row = 11 }, start = { col = 10, row = 11 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 12, row = 11 }, start = { col = 11, row = 11 } } (Token (NumericLiteral "5")) + , Located { end = { col = 13, row = 11 }, start = { col = 12, row = 11 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 11 }, start = { col = 13, row = 11 } } (Token (Sigil (Operator Add))) + , Located { end = { col = 15, row = 11 }, start = { col = 14, row = 11 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 11 }, start = { col = 15, row = 11 } } (Token (NumericLiteral "2")) + , Located { end = { col = 17, row = 11 }, start = { col = 16, row = 11 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 11 }, start = { col = 17, row = 11 } } (Token (Sigil (Operator Divide))) + , Located { end = { col = 19, row = 11 }, start = { col = 18, row = 11 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 20, row = 11 }, start = { col = 19, row = 11 } } (Token (NumericLiteral "4")) + , Located { end = { col = 21, row = 11 }, start = { col = 20, row = 11 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 22, row = 11 }, start = { col = 21, row = 11 } } (Token (Sigil (Operator Multiply))) + , Located { end = { col = 23, row = 11 }, start = { col = 22, row = 11 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 24, row = 11 }, start = { col = 23, row = 11 } } (Token (NumericLiteral "5")) + , Located { end = { col = 1, row = 12 }, start = { col = 24, row = 11 } } (Newlines [] 0) + , Located { end = { col = 3, row = 12 }, start = { col = 1, row = 12 } } (Token (Identifier { name = TokenLowerCase (LowerCase "b4"), qualifiers = [] })) + , Located { end = { col = 4, row = 12 }, start = { col = 3, row = 12 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 5, row = 12 }, start = { col = 4, row = 12 } } (Token (Sigil Assign)) + , Located { end = { col = 6, row = 12 }, start = { col = 5, row = 12 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 8, row = 12 }, start = { col = 6, row = 12 } } (Token (NumericLiteral "78")) + , Located { end = { col = 9, row = 12 }, start = { col = 8, row = 12 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 10, row = 12 }, start = { col = 9, row = 12 } } (Token (Sigil (Operator Divide))) + , Located { end = { col = 11, row = 12 }, start = { col = 10, row = 12 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 12, row = 12 }, start = { col = 11, row = 12 } } (Token (NumericLiteral "5")) + , Located { end = { col = 13, row = 12 }, start = { col = 12, row = 12 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 12 }, start = { col = 13, row = 12 } } (Token (Sigil (Operator Divide))) + , Located { end = { col = 15, row = 12 }, start = { col = 14, row = 12 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 12 }, start = { col = 15, row = 12 } } (Token (NumericLiteral "2")) + , Located { end = { col = 17, row = 12 }, start = { col = 16, row = 12 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 12 }, start = { col = 17, row = 12 } } (Token (Sigil (Operator Divide))) + , Located { end = { col = 19, row = 12 }, start = { col = 18, row = 12 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 20, row = 12 }, start = { col = 19, row = 12 } } (Token (NumericLiteral "4")) + , Located { end = { col = 21, row = 12 }, start = { col = 20, row = 12 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 22, row = 12 }, start = { col = 21, row = 12 } } (Token (Sigil (Operator Add))) + , Located { end = { col = 23, row = 12 }, start = { col = 22, row = 12 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 24, row = 12 }, start = { col = 23, row = 12 } } (Token (NumericLiteral "5")) + , Located { end = { col = 1, row = 14 }, start = { col = 24, row = 12 } } + (Newlines + [ 0 + ] + 0 + ) + ] + } + , { name = "expression-int-subtract" + , source = """a = 5 - 5 + +b = 78 + 5 + 2 - 4 + 5 +""" + , pretty = """ + ( ( Ok + , ( ValueDeclaration + , ( name, a ) + , ( args, () ) + , ( valueExpr__ + , ( Operator + , ( ( op, - ) + , ( lhs + , ( Int, 5 ) + ) + , ( rhs + , ( Int, 5 ) + ) + ) + ) + ) + ) + ) + , ( Ok + , ( ValueDeclaration + , ( name, b ) + , ( args, () ) + , ( valueExpr__ + , ( Operator + , ( ( op, + ) + , ( lhs + , ( Operator + , ( ( op, - ) + , ( lhs + , ( Operator + , ( ( op, + ) + , ( lhs + , ( Operator + , ( ( op, + ) + , ( lhs + , ( Int, 78 ) + ) + , ( rhs + , ( Int, 5 ) + ) + ) + ) + ) + , ( rhs + , ( Int, 2 ) + ) + ) + ) + ) + , ( rhs + , ( Int, 4 ) + ) + ) + ) + ) + , ( rhs + , ( Int, 5 ) + ) + ) + ) + ) + ) + ) + ) +""" + , contextualized = + Just + [ Ok (ValueDeclaration { args = [], name = Located { end = { col = 2, row = 1 }, start = { col = 1, row = 1 } } (LowerCase "a"), valueExpr__ = Located { end = { col = 10, row = 1 }, start = { col = 5, row = 1 } } (Frontend.Operator (Located { end = { col = 8, row = 1 }, start = { col = 7, row = 1 } } Subtract) (Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Frontend.Int 5)) (Located { end = { col = 10, row = 1 }, start = { col = 9, row = 1 } } (Frontend.Int 5))) }) + , Ok (ValueDeclaration { args = [], name = Located { end = { col = 2, row = 3 }, start = { col = 1, row = 3 } } (LowerCase "b"), valueExpr__ = Located { end = { col = 23, row = 3 }, start = { col = 5, row = 3 } } (Frontend.Operator (Located { end = { col = 21, row = 3 }, start = { col = 20, row = 3 } } Add) (Located { end = { col = 19, row = 3 }, start = { col = 5, row = 3 } } (Frontend.Operator (Located { end = { col = 17, row = 3 }, start = { col = 16, row = 3 } } Subtract) (Located { end = { col = 15, row = 3 }, start = { col = 5, row = 3 } } (Frontend.Operator (Located { end = { col = 13, row = 3 }, start = { col = 12, row = 3 } } Add) (Located { end = { col = 11, row = 3 }, start = { col = 5, row = 3 } } (Frontend.Operator (Located { end = { col = 9, row = 3 }, start = { col = 8, row = 3 } } Add) (Located { end = { col = 7, row = 3 }, start = { col = 5, row = 3 } } (Frontend.Int 78)) (Located { end = { col = 11, row = 3 }, start = { col = 10, row = 3 } } (Frontend.Int 5)))) (Located { end = { col = 15, row = 3 }, start = { col = 14, row = 3 } } (Frontend.Int 2)))) (Located { end = { col = 19, row = 3 }, start = { col = 18, row = 3 } } (Frontend.Int 4)))) (Located { end = { col = 23, row = 3 }, start = { col = 22, row = 3 } } (Frontend.Int 5))) }) + ] + , lexed = + Ok + [ Located { end = { col = 2, row = 1 }, start = { col = 1, row = 1 } } (Token (Identifier { name = TokenLowerCase (LowerCase "a"), qualifiers = [] })) + , Located { end = { col = 3, row = 1 }, start = { col = 2, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 4, row = 1 }, start = { col = 3, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 5, row = 1 }, start = { col = 4, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Token (NumericLiteral "5")) + , Located { end = { col = 7, row = 1 }, start = { col = 6, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 8, row = 1 }, start = { col = 7, row = 1 } } (Token (Sigil (Operator Subtract))) + , Located { end = { col = 9, row = 1 }, start = { col = 8, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 10, row = 1 }, start = { col = 9, row = 1 } } (Token (NumericLiteral "5")) + , Located { end = { col = 1, row = 3 }, start = { col = 10, row = 1 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 2, row = 3 }, start = { col = 1, row = 3 } } (Token (Identifier { name = TokenLowerCase (LowerCase "b"), qualifiers = [] })) + , Located { end = { col = 3, row = 3 }, start = { col = 2, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 4, row = 3 }, start = { col = 3, row = 3 } } (Token (Sigil Assign)) + , Located { end = { col = 5, row = 3 }, start = { col = 4, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 7, row = 3 }, start = { col = 5, row = 3 } } (Token (NumericLiteral "78")) + , Located { end = { col = 8, row = 3 }, start = { col = 7, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 9, row = 3 }, start = { col = 8, row = 3 } } (Token (Sigil (Operator Add))) + , Located { end = { col = 10, row = 3 }, start = { col = 9, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 3 }, start = { col = 10, row = 3 } } (Token (NumericLiteral "5")) + , Located { end = { col = 12, row = 3 }, start = { col = 11, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 13, row = 3 }, start = { col = 12, row = 3 } } (Token (Sigil (Operator Add))) + , Located { end = { col = 14, row = 3 }, start = { col = 13, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 15, row = 3 }, start = { col = 14, row = 3 } } (Token (NumericLiteral "2")) + , Located { end = { col = 16, row = 3 }, start = { col = 15, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 17, row = 3 }, start = { col = 16, row = 3 } } (Token (Sigil (Operator Subtract))) + , Located { end = { col = 18, row = 3 }, start = { col = 17, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 19, row = 3 }, start = { col = 18, row = 3 } } (Token (NumericLiteral "4")) + , Located { end = { col = 20, row = 3 }, start = { col = 19, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 21, row = 3 }, start = { col = 20, row = 3 } } (Token (Sigil (Operator Add))) + , Located { end = { col = 22, row = 3 }, start = { col = 21, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 23, row = 3 }, start = { col = 22, row = 3 } } (Token (NumericLiteral "5")) + , Located { end = { col = 1, row = 4 }, start = { col = 23, row = 3 } } (Newlines [] 0) + ] + } + , { name = "type-alias" + , source = """type alias Model = List Int +""" + , pretty = """ + ( ( Ok + , ( TypeAlias + , ( ty, Model ) + , ( genericArgs, () ) + , ( expr + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, List ) + , ( args + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, Int ) + , ( args, () ) + ) + ) ) + ) + ) + ) + ) + ) + ) ) +""" + , contextualized = + Just + [ Ok + (TypeAlias + { expr = + UserDefinedType + { args = + [ UserDefinedType + { args = [] + , name = "Int" + , qualifiedness = PossiblyQualified Nothing + } + ] + , name = "List" + , qualifiedness = PossiblyQualified Nothing + } + , genericArgs = [] + , ty = UpperCase "Model" + } + ) + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 17, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Model"), qualifiers = [] })) + , Located { end = { col = 18, row = 1 }, start = { col = 17, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 19, row = 1 }, start = { col = 18, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 20, row = 1 }, start = { col = 19, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 24, row = 1 }, start = { col = 20, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "List"), qualifiers = [] })) + , Located { end = { col = 25, row = 1 }, start = { col = 24, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 28, row = 1 }, start = { col = 25, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 1, row = 2 }, start = { col = 28, row = 1 } } (Newlines [] 0) + ] + } + , { name = "type-alias-and-expression" + , source = """type alias Model = List Int + +expr hi = 77 +""" + , pretty = """ + ( ( Ok + , ( TypeAlias + , ( ty, Model ) + , ( genericArgs, () ) + , ( expr + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, List ) + , ( args + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, Int ) + , ( args, () ) + ) + ) ) + ) + ) + ) + ) + ) + ) + , ( Ok + , ( ValueDeclaration + , ( name, expr ) + , ( args + , ( hi ) + ) + , ( valueExpr__ + , ( Int, 77 ) + ) + ) + ) + ) +""" + , contextualized = + Just + [ Ok + (TypeAlias + { expr = + UserDefinedType + { args = + [ UserDefinedType + { args = [] + , name = "Int" + , qualifiedness = PossiblyQualified Nothing + } + ] + , name = "List" + , qualifiedness = PossiblyQualified Nothing + } + , genericArgs = [] + , ty = UpperCase "Model" + } + ) + , Ok + (ValueDeclaration + { args = + [ Located { end = { col = 8, row = 3 }, start = { col = 6, row = 3 } } (LowerCase "hi") + ] + , name = Located { end = { col = 5, row = 3 }, start = { col = 1, row = 3 } } (LowerCase "expr") + , valueExpr__ = Located { end = { col = 13, row = 3 }, start = { col = 11, row = 3 } } (Frontend.Int 77) + } + ) + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 17, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Model"), qualifiers = [] })) + , Located { end = { col = 18, row = 1 }, start = { col = 17, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 19, row = 1 }, start = { col = 18, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 20, row = 1 }, start = { col = 19, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 24, row = 1 }, start = { col = 20, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "List"), qualifiers = [] })) + , Located { end = { col = 25, row = 1 }, start = { col = 24, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 28, row = 1 }, start = { col = 25, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 1, row = 3 }, start = { col = 28, row = 1 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 5, row = 3 }, start = { col = 1, row = 3 } } (Token (Identifier { name = TokenLowerCase (LowerCase "expr"), qualifiers = [] })) + , Located { end = { col = 6, row = 3 }, start = { col = 5, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 8, row = 3 }, start = { col = 6, row = 3 } } (Token (Identifier { name = TokenLowerCase (LowerCase "hi"), qualifiers = [] })) + , Located { end = { col = 9, row = 3 }, start = { col = 8, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 10, row = 3 }, start = { col = 9, row = 3 } } (Token (Sigil Assign)) + , Located { end = { col = 11, row = 3 }, start = { col = 10, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 13, row = 3 }, start = { col = 11, row = 3 } } (Token (NumericLiteral "77")) + , Located { end = { col = 1, row = 4 }, start = { col = 13, row = 3 } } (Newlines [] 0) + ] + } + , { name = "type-alias-bracket-in-record" + , source = """type alias Ty = { hi: (Int) } +""" + , pretty = """ + ( ( Ok + , ( TypeAlias + , ( ty, Ty ) + , ( genericArgs, () ) + , ( expr + , ( Record + , ( ( hi + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, Int ) + , ( args, () ) + ) + ) + ) ) + ) + ) + ) + ) ) +""" + , contextualized = + Just + [ Ok + (TypeAlias + { expr = + Record + (Dict.fromList + [ ( "hi" + , UserDefinedType + { args = [] + , name = "Int" + , qualifiedness = PossiblyQualified Nothing + } + ) + ] + ) + , genericArgs = [] + , ty = UpperCase "Ty" + } + ) + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Ty"), qualifiers = [] })) + , Located { end = { col = 15, row = 1 }, start = { col = 14, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 1 }, start = { col = 15, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 17, row = 1 }, start = { col = 16, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 1 }, start = { col = 17, row = 1 } } (Token (Sigil (Bracket Curly Open))) + , Located { end = { col = 19, row = 1 }, start = { col = 18, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 21, row = 1 }, start = { col = 19, row = 1 } } (Token (Identifier { name = TokenLowerCase (LowerCase "hi"), qualifiers = [] })) + , Located { end = { col = 22, row = 1 }, start = { col = 21, row = 1 } } (Token (Sigil Colon)) + , Located { end = { col = 23, row = 1 }, start = { col = 22, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 24, row = 1 }, start = { col = 23, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 27, row = 1 }, start = { col = 24, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 28, row = 1 }, start = { col = 27, row = 1 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 29, row = 1 }, start = { col = 28, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 30, row = 1 }, start = { col = 29, row = 1 } } (Token (Sigil (Bracket Curly Close))) + , Located { end = { col = 1, row = 2 }, start = { col = 30, row = 1 } } (Newlines [] 0) + ] + } + , { name = "type-alias-function" + , source = """type alias Function = List Int -> List (List Int) +""" + , pretty = """ + ( ( Ok + , ( TypeAlias + , ( ty, Function ) + , ( genericArgs, () ) + , ( expr + , ( Function + , ( ( from + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, List ) + , ( args + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, Int ) + , ( args, () ) + ) + ) ) + ) + ) + ) + ) + , ( to + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, List ) + , ( args + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, List ) + , ( args + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, Int ) + , ( args, () ) + ) + ) ) + ) + ) + ) ) + ) + ) + ) + ) + ) + ) + ) + ) + ) ) +""" + , contextualized = + Just + [ Ok + (TypeAlias + { expr = + Function + { from = + UserDefinedType + { args = + [ UserDefinedType + { args = [] + , name = "Int" + , qualifiedness = PossiblyQualified Nothing + } + ] + , name = "List" + , qualifiedness = PossiblyQualified Nothing + } + , to = + UserDefinedType + { args = + [ UserDefinedType + { args = + [ UserDefinedType + { args = [] + , name = "Int" + , qualifiedness = PossiblyQualified Nothing + } + ] + , name = "List" + , qualifiedness = PossiblyQualified Nothing + } + ] + , name = "List" + , qualifiedness = PossiblyQualified Nothing + } + } + , genericArgs = [] + , ty = UpperCase "Function" + } + ) + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 20, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Function"), qualifiers = [] })) + , Located { end = { col = 21, row = 1 }, start = { col = 20, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 22, row = 1 }, start = { col = 21, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 23, row = 1 }, start = { col = 22, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 27, row = 1 }, start = { col = 23, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "List"), qualifiers = [] })) + , Located { end = { col = 28, row = 1 }, start = { col = 27, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 31, row = 1 }, start = { col = 28, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 32, row = 1 }, start = { col = 31, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 34, row = 1 }, start = { col = 32, row = 1 } } (Token (Sigil ThinArrow)) + , Located { end = { col = 35, row = 1 }, start = { col = 34, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 39, row = 1 }, start = { col = 35, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "List"), qualifiers = [] })) + , Located { end = { col = 40, row = 1 }, start = { col = 39, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 41, row = 1 }, start = { col = 40, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 45, row = 1 }, start = { col = 41, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "List"), qualifiers = [] })) + , Located { end = { col = 46, row = 1 }, start = { col = 45, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 49, row = 1 }, start = { col = 46, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 50, row = 1 }, start = { col = 49, row = 1 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 1, row = 2 }, start = { col = 50, row = 1 } } (Newlines [] 0) + ] + } + , { name = "type-alias-function-binding-order" + , source = """type alias Function = A -> B -> C +type alias Function = A -> B -> C -> D +""" + , pretty = """ + ( ( Ok + , ( TypeAlias + , ( ty, Function ) + , ( genericArgs, () ) + , ( expr + , ( Function + , ( ( from + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, A ) + , ( args, () ) + ) + ) + ) + , ( to + , ( Function + , ( ( from + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, B ) + , ( args, () ) + ) + ) + ) + , ( to + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, C ) + , ( args, () ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + , ( Ok + , ( TypeAlias + , ( ty, Function ) + , ( genericArgs, () ) + , ( expr + , ( Function + , ( ( from + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, A ) + , ( args, () ) + ) + ) + ) + , ( to + , ( Function + , ( ( from + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, B ) + , ( args, () ) + ) + ) + ) + , ( to + , ( Function + , ( ( from + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, C ) + , ( args, () ) + ) + ) + ) + , ( to + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, D ) + , ( args, () ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) +""" + , contextualized = + Just + [ Ok + (TypeAlias + { expr = + Function + { from = + UserDefinedType + { args = [] + , name = "A" + , qualifiedness = PossiblyQualified Nothing + } + , to = + Function + { from = + UserDefinedType + { args = [] + , name = "B" + , qualifiedness = PossiblyQualified Nothing + } + , to = + UserDefinedType + { args = [] + , name = "C" + , qualifiedness = PossiblyQualified Nothing + } + } + } + , genericArgs = [] + , ty = UpperCase "Function" + } + ) + , Ok + (TypeAlias + { expr = + Function + { from = + UserDefinedType + { args = [] + , name = "A" + , qualifiedness = PossiblyQualified Nothing + } + , to = + Function + { from = + UserDefinedType + { args = [] + , name = "B" + , qualifiedness = PossiblyQualified Nothing + } + , to = + Function + { from = + UserDefinedType + { args = [] + , name = "C" + , qualifiedness = PossiblyQualified Nothing + } + , to = + UserDefinedType + { args = [] + , name = "D" + , qualifiedness = PossiblyQualified Nothing + } + } + } + } + , genericArgs = [] + , ty = UpperCase "Function" + } + ) + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 20, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Function"), qualifiers = [] })) + , Located { end = { col = 21, row = 1 }, start = { col = 20, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 22, row = 1 }, start = { col = 21, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 23, row = 1 }, start = { col = 22, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 24, row = 1 }, start = { col = 23, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "A"), qualifiers = [] })) + , Located { end = { col = 25, row = 1 }, start = { col = 24, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 27, row = 1 }, start = { col = 25, row = 1 } } (Token (Sigil ThinArrow)) + , Located { end = { col = 28, row = 1 }, start = { col = 27, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 29, row = 1 }, start = { col = 28, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "B"), qualifiers = [] })) + , Located { end = { col = 30, row = 1 }, start = { col = 29, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 32, row = 1 }, start = { col = 30, row = 1 } } (Token (Sigil ThinArrow)) + , Located { end = { col = 33, row = 1 }, start = { col = 32, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 34, row = 1 }, start = { col = 33, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "C"), qualifiers = [] })) + , Located { end = { col = 1, row = 2 }, start = { col = 34, row = 1 } } (Newlines [] 0) + , Located { end = { col = 5, row = 2 }, start = { col = 1, row = 2 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 2 }, start = { col = 5, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 2 }, start = { col = 6, row = 2 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 2 }, start = { col = 11, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 20, row = 2 }, start = { col = 12, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Function"), qualifiers = [] })) + , Located { end = { col = 21, row = 2 }, start = { col = 20, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 22, row = 2 }, start = { col = 21, row = 2 } } (Token (Sigil Assign)) + , Located { end = { col = 23, row = 2 }, start = { col = 22, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 24, row = 2 }, start = { col = 23, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "A"), qualifiers = [] })) + , Located { end = { col = 25, row = 2 }, start = { col = 24, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 27, row = 2 }, start = { col = 25, row = 2 } } (Token (Sigil ThinArrow)) + , Located { end = { col = 28, row = 2 }, start = { col = 27, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 29, row = 2 }, start = { col = 28, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "B"), qualifiers = [] })) + , Located { end = { col = 30, row = 2 }, start = { col = 29, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 32, row = 2 }, start = { col = 30, row = 2 } } (Token (Sigil ThinArrow)) + , Located { end = { col = 33, row = 2 }, start = { col = 32, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 34, row = 2 }, start = { col = 33, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "C"), qualifiers = [] })) + , Located { end = { col = 35, row = 2 }, start = { col = 34, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 37, row = 2 }, start = { col = 35, row = 2 } } (Token (Sigil ThinArrow)) + , Located { end = { col = 38, row = 2 }, start = { col = 37, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 39, row = 2 }, start = { col = 38, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "D"), qualifiers = [] })) + , Located { end = { col = 1, row = 3 }, start = { col = 39, row = 2 } } (Newlines [] 0) + ] + } + , { name = "type-alias-function-generic" + , source = """type alias Function a = List Int -> List (List a) + +type alias Function b c = b -> c""" + , pretty = """ + ( ( Ok + , ( TypeAlias + , ( ty, Function ) + , ( genericArgs + , ( a ) + ) + , ( expr + , ( Function + , ( ( from + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, List ) + , ( args + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, Int ) + , ( args, () ) + ) + ) ) + ) + ) + ) + ) + , ( to + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, List ) + , ( args + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, List ) + , ( args + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, a ) + , ( args, () ) + ) + ) ) + ) + ) + ) ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + , ( Ok + , ( TypeAlias + , ( ty, Function ) + , ( genericArgs + , ( b, c ) + ) + , ( expr + , ( Function + , ( ( from + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, b ) + , ( args, () ) + ) + ) + ) + , ( to + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, c ) + , ( args, () ) + ) + ) + ) + ) + ) + ) + ) + ) + ) +""" + , contextualized = + Just + [ Ok + (TypeAlias + { expr = + Function + { from = + UserDefinedType + { args = + [ UserDefinedType + { args = [] + , name = "Int" + , qualifiedness = PossiblyQualified Nothing + } + ] + , name = "List" + , qualifiedness = PossiblyQualified Nothing + } + , to = + UserDefinedType + { args = + [ UserDefinedType + { args = + [ UserDefinedType + { args = [] + , name = "a" + , qualifiedness = PossiblyQualified Nothing + } + ] + , name = "List" + , qualifiedness = PossiblyQualified Nothing + } + ] + , name = "List" + , qualifiedness = PossiblyQualified Nothing + } + } + , genericArgs = + [ LowerCase "a" + ] + , ty = UpperCase "Function" + } + ) + , Ok + (TypeAlias + { expr = + Function + { from = + UserDefinedType + { args = [] + , name = "b" + , qualifiedness = PossiblyQualified Nothing + } + , to = + UserDefinedType + { args = [] + , name = "c" + , qualifiedness = PossiblyQualified Nothing + } + } + , genericArgs = + [ LowerCase "b" + , LowerCase "c" + ] + , ty = UpperCase "Function" + } + ) + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 20, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Function"), qualifiers = [] })) + , Located { end = { col = 21, row = 1 }, start = { col = 20, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 22, row = 1 }, start = { col = 21, row = 1 } } (Token (Identifier { name = TokenLowerCase (LowerCase "a"), qualifiers = [] })) + , Located { end = { col = 23, row = 1 }, start = { col = 22, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 24, row = 1 }, start = { col = 23, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 25, row = 1 }, start = { col = 24, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 29, row = 1 }, start = { col = 25, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "List"), qualifiers = [] })) + , Located { end = { col = 30, row = 1 }, start = { col = 29, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 33, row = 1 }, start = { col = 30, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 34, row = 1 }, start = { col = 33, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 36, row = 1 }, start = { col = 34, row = 1 } } (Token (Sigil ThinArrow)) + , Located { end = { col = 37, row = 1 }, start = { col = 36, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 41, row = 1 }, start = { col = 37, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "List"), qualifiers = [] })) + , Located { end = { col = 42, row = 1 }, start = { col = 41, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 43, row = 1 }, start = { col = 42, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 47, row = 1 }, start = { col = 43, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "List"), qualifiers = [] })) + , Located { end = { col = 48, row = 1 }, start = { col = 47, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 49, row = 1 }, start = { col = 48, row = 1 } } (Token (Identifier { name = TokenLowerCase (LowerCase "a"), qualifiers = [] })) + , Located { end = { col = 50, row = 1 }, start = { col = 49, row = 1 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 1, row = 3 }, start = { col = 50, row = 1 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 5, row = 3 }, start = { col = 1, row = 3 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 3 }, start = { col = 5, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 3 }, start = { col = 6, row = 3 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 3 }, start = { col = 11, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 20, row = 3 }, start = { col = 12, row = 3 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Function"), qualifiers = [] })) + , Located { end = { col = 21, row = 3 }, start = { col = 20, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 22, row = 3 }, start = { col = 21, row = 3 } } (Token (Identifier { name = TokenLowerCase (LowerCase "b"), qualifiers = [] })) + , Located { end = { col = 23, row = 3 }, start = { col = 22, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 24, row = 3 }, start = { col = 23, row = 3 } } (Token (Identifier { name = TokenLowerCase (LowerCase "c"), qualifiers = [] })) + , Located { end = { col = 25, row = 3 }, start = { col = 24, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 26, row = 3 }, start = { col = 25, row = 3 } } (Token (Sigil Assign)) + , Located { end = { col = 27, row = 3 }, start = { col = 26, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 28, row = 3 }, start = { col = 27, row = 3 } } (Token (Identifier { name = TokenLowerCase (LowerCase "b"), qualifiers = [] })) + , Located { end = { col = 29, row = 3 }, start = { col = 28, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 31, row = 3 }, start = { col = 29, row = 3 } } (Token (Sigil ThinArrow)) + , Located { end = { col = 32, row = 3 }, start = { col = 31, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 33, row = 3 }, start = { col = 32, row = 3 } } (Token (Identifier { name = TokenLowerCase (LowerCase "c"), qualifiers = [] })) + ] + } + , { name = "type-alias-function-nested" + , source = """type alias Function = (() -> (Int, String)) + +type alias Function2 = { a: () -> (Int, String) } + +type alias Function3 = (() -> (Int, String), ()) + +type alias Function3 = (Int, () -> (Int, String), ()) +""" + , pretty = """ + ( ( Ok + , ( TypeAlias + , ( ty, Function ) + , ( genericArgs, () ) + , ( expr + , ( Function + , ( ( from, Unit ) + , ( to + , ( Tuple + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, Int ) + , ( args, () ) + ) + ) + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, String ) + , ( args, () ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + , ( Ok + , ( TypeAlias + , ( ty, Function2 ) + , ( genericArgs, () ) + , ( expr + , ( Record + , ( ( a + , ( Function + , ( ( from, Unit ) + , ( to + , ( Tuple + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, Int ) + , ( args, () ) + ) + ) + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, String ) + , ( args, () ) + ) + ) + ) + ) + ) + ) + ) + ) ) + ) + ) + ) + ) + , ( Ok + , ( TypeAlias + , ( ty, Function3 ) + , ( genericArgs, () ) + , ( expr + , ( Tuple + , ( ( Function + , ( ( from, Unit ) + , ( to + , ( Tuple + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, Int ) + , ( args, () ) + ) + ) + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, String ) + , ( args, () ) + ) + ) + ) + ) + ) + ) + ) + , Unit + ) + ) + ) + ) + ) + , ( Ok + , ( TypeAlias + , ( ty, Function3 ) + , ( genericArgs, () ) + , ( expr + , ( Tuple + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, Int ) + , ( args, () ) + ) + ) + , ( Function + , ( ( from, Unit ) + , ( to + , ( Tuple + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, Int ) + , ( args, () ) + ) + ) + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, String ) + , ( args, () ) + ) + ) + ) + ) + ) + ) + ) + , Unit + ) + ) + ) + ) + ) + ) +""" + , contextualized = + Just + [ Ok + (TypeAlias + { expr = + Function + { from = Unit + , to = + Tuple + (UserDefinedType + { args = [] + , name = "Int" + , qualifiedness = PossiblyQualified Nothing + } + ) + (UserDefinedType + { args = [] + , name = "String" + , qualifiedness = PossiblyQualified Nothing + } + ) + } + , genericArgs = [] + , ty = UpperCase "Function" + } + ) + , Ok + (TypeAlias + { expr = + Record + (Dict.fromList + [ ( "a" + , Function + { from = Unit + , to = + Tuple + (UserDefinedType + { args = [] + , name = "Int" + , qualifiedness = PossiblyQualified Nothing + } + ) + (UserDefinedType + { args = [] + , name = "String" + , qualifiedness = PossiblyQualified Nothing + } + ) + } + ) + ] + ) + , genericArgs = [] + , ty = UpperCase "Function2" + } + ) + , Ok + (TypeAlias + { expr = + Tuple + (Function + { from = Unit + , to = + Tuple + (UserDefinedType + { args = [] + , name = "Int" + , qualifiedness = PossiblyQualified Nothing + } + ) + (UserDefinedType + { args = [] + , name = "String" + , qualifiedness = PossiblyQualified Nothing + } + ) + } + ) + Unit + , genericArgs = [] + , ty = UpperCase "Function3" + } + ) + , Ok + (TypeAlias + { expr = + Tuple3 + (UserDefinedType + { args = [] + , name = "Int" + , qualifiedness = PossiblyQualified Nothing + } + ) + (Function + { from = Unit + , to = + Tuple + (UserDefinedType + { args = [] + , name = "Int" + , qualifiedness = PossiblyQualified Nothing + } + ) + (UserDefinedType + { args = [] + , name = "String" + , qualifiedness = PossiblyQualified Nothing + } + ) + } + ) + Unit + , genericArgs = [] + , ty = UpperCase "Function3" + } + ) + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 20, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Function"), qualifiers = [] })) + , Located { end = { col = 21, row = 1 }, start = { col = 20, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 22, row = 1 }, start = { col = 21, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 23, row = 1 }, start = { col = 22, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 24, row = 1 }, start = { col = 23, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 25, row = 1 }, start = { col = 24, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 26, row = 1 }, start = { col = 25, row = 1 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 27, row = 1 }, start = { col = 26, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 29, row = 1 }, start = { col = 27, row = 1 } } (Token (Sigil ThinArrow)) + , Located { end = { col = 30, row = 1 }, start = { col = 29, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 31, row = 1 }, start = { col = 30, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 34, row = 1 }, start = { col = 31, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 35, row = 1 }, start = { col = 34, row = 1 } } (Token (Sigil Comma)) + , Located { end = { col = 36, row = 1 }, start = { col = 35, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 42, row = 1 }, start = { col = 36, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "String"), qualifiers = [] })) + , Located { end = { col = 43, row = 1 }, start = { col = 42, row = 1 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 44, row = 1 }, start = { col = 43, row = 1 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 1, row = 3 }, start = { col = 44, row = 1 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 5, row = 3 }, start = { col = 1, row = 3 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 3 }, start = { col = 5, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 3 }, start = { col = 6, row = 3 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 3 }, start = { col = 11, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 21, row = 3 }, start = { col = 12, row = 3 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Function2"), qualifiers = [] })) + , Located { end = { col = 22, row = 3 }, start = { col = 21, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 23, row = 3 }, start = { col = 22, row = 3 } } (Token (Sigil Assign)) + , Located { end = { col = 24, row = 3 }, start = { col = 23, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 25, row = 3 }, start = { col = 24, row = 3 } } (Token (Sigil (Bracket Curly Open))) + , Located { end = { col = 26, row = 3 }, start = { col = 25, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 27, row = 3 }, start = { col = 26, row = 3 } } (Token (Identifier { name = TokenLowerCase (LowerCase "a"), qualifiers = [] })) + , Located { end = { col = 28, row = 3 }, start = { col = 27, row = 3 } } (Token (Sigil Colon)) + , Located { end = { col = 29, row = 3 }, start = { col = 28, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 30, row = 3 }, start = { col = 29, row = 3 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 31, row = 3 }, start = { col = 30, row = 3 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 32, row = 3 }, start = { col = 31, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 34, row = 3 }, start = { col = 32, row = 3 } } (Token (Sigil ThinArrow)) + , Located { end = { col = 35, row = 3 }, start = { col = 34, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 36, row = 3 }, start = { col = 35, row = 3 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 39, row = 3 }, start = { col = 36, row = 3 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 40, row = 3 }, start = { col = 39, row = 3 } } (Token (Sigil Comma)) + , Located { end = { col = 41, row = 3 }, start = { col = 40, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 47, row = 3 }, start = { col = 41, row = 3 } } (Token (Identifier { name = TokenUpperCase (UpperCase "String"), qualifiers = [] })) + , Located { end = { col = 48, row = 3 }, start = { col = 47, row = 3 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 49, row = 3 }, start = { col = 48, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 50, row = 3 }, start = { col = 49, row = 3 } } (Token (Sigil (Bracket Curly Close))) + , Located { end = { col = 1, row = 5 }, start = { col = 50, row = 3 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 5, row = 5 }, start = { col = 1, row = 5 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 5 }, start = { col = 5, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 5 }, start = { col = 6, row = 5 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 5 }, start = { col = 11, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 21, row = 5 }, start = { col = 12, row = 5 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Function3"), qualifiers = [] })) + , Located { end = { col = 22, row = 5 }, start = { col = 21, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 23, row = 5 }, start = { col = 22, row = 5 } } (Token (Sigil Assign)) + , Located { end = { col = 24, row = 5 }, start = { col = 23, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 25, row = 5 }, start = { col = 24, row = 5 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 26, row = 5 }, start = { col = 25, row = 5 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 27, row = 5 }, start = { col = 26, row = 5 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 28, row = 5 }, start = { col = 27, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 30, row = 5 }, start = { col = 28, row = 5 } } (Token (Sigil ThinArrow)) + , Located { end = { col = 31, row = 5 }, start = { col = 30, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 32, row = 5 }, start = { col = 31, row = 5 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 35, row = 5 }, start = { col = 32, row = 5 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 36, row = 5 }, start = { col = 35, row = 5 } } (Token (Sigil Comma)) + , Located { end = { col = 37, row = 5 }, start = { col = 36, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 43, row = 5 }, start = { col = 37, row = 5 } } (Token (Identifier { name = TokenUpperCase (UpperCase "String"), qualifiers = [] })) + , Located { end = { col = 44, row = 5 }, start = { col = 43, row = 5 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 45, row = 5 }, start = { col = 44, row = 5 } } (Token (Sigil Comma)) + , Located { end = { col = 46, row = 5 }, start = { col = 45, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 47, row = 5 }, start = { col = 46, row = 5 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 48, row = 5 }, start = { col = 47, row = 5 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 49, row = 5 }, start = { col = 48, row = 5 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 1, row = 7 }, start = { col = 49, row = 5 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 5, row = 7 }, start = { col = 1, row = 7 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 7 }, start = { col = 5, row = 7 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 7 }, start = { col = 6, row = 7 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 7 }, start = { col = 11, row = 7 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 21, row = 7 }, start = { col = 12, row = 7 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Function3"), qualifiers = [] })) + , Located { end = { col = 22, row = 7 }, start = { col = 21, row = 7 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 23, row = 7 }, start = { col = 22, row = 7 } } (Token (Sigil Assign)) + , Located { end = { col = 24, row = 7 }, start = { col = 23, row = 7 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 25, row = 7 }, start = { col = 24, row = 7 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 28, row = 7 }, start = { col = 25, row = 7 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 29, row = 7 }, start = { col = 28, row = 7 } } (Token (Sigil Comma)) + , Located { end = { col = 30, row = 7 }, start = { col = 29, row = 7 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 31, row = 7 }, start = { col = 30, row = 7 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 32, row = 7 }, start = { col = 31, row = 7 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 33, row = 7 }, start = { col = 32, row = 7 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 35, row = 7 }, start = { col = 33, row = 7 } } (Token (Sigil ThinArrow)) + , Located { end = { col = 36, row = 7 }, start = { col = 35, row = 7 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 37, row = 7 }, start = { col = 36, row = 7 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 40, row = 7 }, start = { col = 37, row = 7 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 41, row = 7 }, start = { col = 40, row = 7 } } (Token (Sigil Comma)) + , Located { end = { col = 42, row = 7 }, start = { col = 41, row = 7 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 48, row = 7 }, start = { col = 42, row = 7 } } (Token (Identifier { name = TokenUpperCase (UpperCase "String"), qualifiers = [] })) + , Located { end = { col = 49, row = 7 }, start = { col = 48, row = 7 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 50, row = 7 }, start = { col = 49, row = 7 } } (Token (Sigil Comma)) + , Located { end = { col = 51, row = 7 }, start = { col = 50, row = 7 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 52, row = 7 }, start = { col = 51, row = 7 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 53, row = 7 }, start = { col = 52, row = 7 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 54, row = 7 }, start = { col = 53, row = 7 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 1, row = 8 }, start = { col = 54, row = 7 } } (Newlines [] 0) + ] + } + , { name = "type-alias-function-record" + , source = """type alias Function = { a: { b: C}, d: E } -> {} +""" + , pretty = """ + ( ( Ok + , ( TypeAlias + , ( ty, Function ) + , ( genericArgs, () ) + , ( expr + , ( Function + , ( ( from + , ( Record + , ( ( a + , ( Record + , ( ( b + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, C ) + , ( args, () ) + ) + ) + ) ) + ) + ) + , ( d + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, E ) + , ( args, () ) + ) + ) + ) + ) + ) + ) + , ( to + , ( Record, () ) + ) + ) + ) + ) + ) + ) ) +""" + , contextualized = + Just + [ Ok + (TypeAlias + { expr = + Function + { from = + Record + (Dict.fromList + [ ( "a" + , Record + (Dict.fromList + [ ( "b" + , UserDefinedType + { args = [] + , name = "C" + , qualifiedness = PossiblyQualified Nothing + } + ) + ] + ) + ) + , ( "d" + , UserDefinedType + { args = [] + , name = "E" + , qualifiedness = PossiblyQualified Nothing + } + ) + ] + ) + , to = Record (Dict.fromList []) + } + , genericArgs = [] + , ty = UpperCase "Function" + } + ) + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 20, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Function"), qualifiers = [] })) + , Located { end = { col = 21, row = 1 }, start = { col = 20, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 22, row = 1 }, start = { col = 21, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 23, row = 1 }, start = { col = 22, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 24, row = 1 }, start = { col = 23, row = 1 } } (Token (Sigil (Bracket Curly Open))) + , Located { end = { col = 25, row = 1 }, start = { col = 24, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 26, row = 1 }, start = { col = 25, row = 1 } } (Token (Identifier { name = TokenLowerCase (LowerCase "a"), qualifiers = [] })) + , Located { end = { col = 27, row = 1 }, start = { col = 26, row = 1 } } (Token (Sigil Colon)) + , Located { end = { col = 28, row = 1 }, start = { col = 27, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 29, row = 1 }, start = { col = 28, row = 1 } } (Token (Sigil (Bracket Curly Open))) + , Located { end = { col = 30, row = 1 }, start = { col = 29, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 31, row = 1 }, start = { col = 30, row = 1 } } (Token (Identifier { name = TokenLowerCase (LowerCase "b"), qualifiers = [] })) + , Located { end = { col = 32, row = 1 }, start = { col = 31, row = 1 } } (Token (Sigil Colon)) + , Located { end = { col = 33, row = 1 }, start = { col = 32, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 34, row = 1 }, start = { col = 33, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "C"), qualifiers = [] })) + , Located { end = { col = 35, row = 1 }, start = { col = 34, row = 1 } } (Token (Sigil (Bracket Curly Close))) + , Located { end = { col = 36, row = 1 }, start = { col = 35, row = 1 } } (Token (Sigil Comma)) + , Located { end = { col = 37, row = 1 }, start = { col = 36, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 38, row = 1 }, start = { col = 37, row = 1 } } (Token (Identifier { name = TokenLowerCase (LowerCase "d"), qualifiers = [] })) + , Located { end = { col = 39, row = 1 }, start = { col = 38, row = 1 } } (Token (Sigil Colon)) + , Located { end = { col = 40, row = 1 }, start = { col = 39, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 41, row = 1 }, start = { col = 40, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "E"), qualifiers = [] })) + , Located { end = { col = 42, row = 1 }, start = { col = 41, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 43, row = 1 }, start = { col = 42, row = 1 } } (Token (Sigil (Bracket Curly Close))) + , Located { end = { col = 44, row = 1 }, start = { col = 43, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 46, row = 1 }, start = { col = 44, row = 1 } } (Token (Sigil ThinArrow)) + , Located { end = { col = 47, row = 1 }, start = { col = 46, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 48, row = 1 }, start = { col = 47, row = 1 } } (Token (Sigil (Bracket Curly Open))) + , Located { end = { col = 49, row = 1 }, start = { col = 48, row = 1 } } (Token (Sigil (Bracket Curly Close))) + , Located { end = { col = 1, row = 2 }, start = { col = 49, row = 1 } } (Newlines [] 0) + ] + } + , { name = "type-alias-function-tuple" + , source = """type alias Function = () -> (Int, String) +""" + , pretty = """ + ( ( Ok + , ( TypeAlias + , ( ty, Function ) + , ( genericArgs, () ) + , ( expr + , ( Function + , ( ( from, Unit ) + , ( to + , ( Tuple + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, Int ) + , ( args, () ) + ) + ) + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, String ) + , ( args, () ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) ) +""" + , contextualized = + Just + [ Ok + (TypeAlias + { expr = + Function + { from = Unit + , to = + Tuple + (UserDefinedType + { args = [] + , name = "Int" + , qualifiedness = PossiblyQualified Nothing + } + ) + (UserDefinedType + { args = [] + , name = "String" + , qualifiedness = PossiblyQualified Nothing + } + ) + } + , genericArgs = [] + , ty = UpperCase "Function" + } + ) + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 20, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Function"), qualifiers = [] })) + , Located { end = { col = 21, row = 1 }, start = { col = 20, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 22, row = 1 }, start = { col = 21, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 23, row = 1 }, start = { col = 22, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 24, row = 1 }, start = { col = 23, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 25, row = 1 }, start = { col = 24, row = 1 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 26, row = 1 }, start = { col = 25, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 28, row = 1 }, start = { col = 26, row = 1 } } (Token (Sigil ThinArrow)) + , Located { end = { col = 29, row = 1 }, start = { col = 28, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 30, row = 1 }, start = { col = 29, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 33, row = 1 }, start = { col = 30, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 34, row = 1 }, start = { col = 33, row = 1 } } (Token (Sigil Comma)) + , Located { end = { col = 35, row = 1 }, start = { col = 34, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 41, row = 1 }, start = { col = 35, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "String"), qualifiers = [] })) + , Located { end = { col = 42, row = 1 }, start = { col = 41, row = 1 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 1, row = 2 }, start = { col = 42, row = 1 } } (Newlines [] 0) + ] + } + , { name = "type-alias-function-type-args" + , source = """type alias Function = List A -> List B C D -> List D E F +""" + , pretty = """ + ( ( Ok + , ( TypeAlias + , ( ty, Function ) + , ( genericArgs, () ) + , ( expr + , ( Function + , ( ( from + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, List ) + , ( args + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, A ) + , ( args, () ) + ) + ) ) + ) + ) + ) + ) + , ( to + , ( Function + , ( ( from + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, List ) + , ( args + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, B ) + , ( args, () ) + ) + ) + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, C ) + , ( args, () ) + ) + ) + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, D ) + , ( args, () ) + ) + ) + ) + ) + ) + ) + ) + , ( to + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, List ) + , ( args + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, D ) + , ( args, () ) + ) + ) + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, E ) + , ( args, () ) + ) + ) + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, F ) + , ( args, () ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) ) +""" + , contextualized = + Just + [ Ok + (TypeAlias + { expr = + Function + { from = + UserDefinedType + { args = + [ UserDefinedType + { args = [] + , name = "A" + , qualifiedness = PossiblyQualified Nothing + } + ] + , name = "List" + , qualifiedness = PossiblyQualified Nothing + } + , to = + Function + { from = + UserDefinedType + { args = + [ UserDefinedType + { args = [] + , name = "B" + , qualifiedness = PossiblyQualified Nothing + } + , UserDefinedType + { args = [] + , name = "C" + , qualifiedness = PossiblyQualified Nothing + } + , UserDefinedType + { args = [] + , name = "D" + , qualifiedness = PossiblyQualified Nothing + } + ] + , name = "List" + , qualifiedness = PossiblyQualified Nothing + } + , to = + UserDefinedType + { args = + [ UserDefinedType + { args = [] + , name = "D" + , qualifiedness = PossiblyQualified Nothing + } + , UserDefinedType + { args = [] + , name = "E" + , qualifiedness = PossiblyQualified Nothing + } + , UserDefinedType + { args = [] + , name = "F" + , qualifiedness = PossiblyQualified Nothing + } + ] + , name = "List" + , qualifiedness = PossiblyQualified Nothing + } + } + } + , genericArgs = [] + , ty = UpperCase "Function" + } + ) + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 20, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Function"), qualifiers = [] })) + , Located { end = { col = 21, row = 1 }, start = { col = 20, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 22, row = 1 }, start = { col = 21, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 23, row = 1 }, start = { col = 22, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 27, row = 1 }, start = { col = 23, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "List"), qualifiers = [] })) + , Located { end = { col = 28, row = 1 }, start = { col = 27, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 29, row = 1 }, start = { col = 28, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "A"), qualifiers = [] })) + , Located { end = { col = 30, row = 1 }, start = { col = 29, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 32, row = 1 }, start = { col = 30, row = 1 } } (Token (Sigil ThinArrow)) + , Located { end = { col = 33, row = 1 }, start = { col = 32, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 37, row = 1 }, start = { col = 33, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "List"), qualifiers = [] })) + , Located { end = { col = 38, row = 1 }, start = { col = 37, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 39, row = 1 }, start = { col = 38, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "B"), qualifiers = [] })) + , Located { end = { col = 40, row = 1 }, start = { col = 39, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 41, row = 1 }, start = { col = 40, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "C"), qualifiers = [] })) + , Located { end = { col = 42, row = 1 }, start = { col = 41, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 43, row = 1 }, start = { col = 42, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "D"), qualifiers = [] })) + , Located { end = { col = 44, row = 1 }, start = { col = 43, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 46, row = 1 }, start = { col = 44, row = 1 } } (Token (Sigil ThinArrow)) + , Located { end = { col = 47, row = 1 }, start = { col = 46, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 51, row = 1 }, start = { col = 47, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "List"), qualifiers = [] })) + , Located { end = { col = 52, row = 1 }, start = { col = 51, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 53, row = 1 }, start = { col = 52, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "D"), qualifiers = [] })) + , Located { end = { col = 54, row = 1 }, start = { col = 53, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 55, row = 1 }, start = { col = 54, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "E"), qualifiers = [] })) + , Located { end = { col = 56, row = 1 }, start = { col = 55, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 57, row = 1 }, start = { col = 56, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "F"), qualifiers = [] })) + , Located { end = { col = 1, row = 2 }, start = { col = 57, row = 1 } } (Newlines [] 0) + ] + } + , { name = "type-alias-funky-indentation" + , source = """type alias + Model = List Int +""" + , pretty = """ + ( ( Ok + , ( TypeAlias + , ( ty, Model ) + , ( genericArgs, () ) + , ( expr + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, List ) + , ( args + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, Int ) + , ( args, () ) + ) + ) ) + ) + ) + ) + ) + ) + ) ) +""" + , contextualized = + Just + [ Ok + (TypeAlias + { expr = + UserDefinedType + { args = + [ UserDefinedType + { args = [] + , name = "Int" + , qualifiedness = PossiblyQualified Nothing + } + ] + , name = "List" + , qualifiedness = PossiblyQualified Nothing + } + , genericArgs = [] + , ty = UpperCase "Model" + } + ) + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 5, row = 2 }, start = { col = 11, row = 1 } } (Newlines [] 4) + , Located { end = { col = 10, row = 2 }, start = { col = 5, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Model"), qualifiers = [] })) + , Located { end = { col = 11, row = 2 }, start = { col = 10, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 12, row = 2 }, start = { col = 11, row = 2 } } (Token (Sigil Assign)) + , Located { end = { col = 13, row = 2 }, start = { col = 12, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 17, row = 2 }, start = { col = 13, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "List"), qualifiers = [] })) + , Located { end = { col = 18, row = 2 }, start = { col = 17, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 21, row = 2 }, start = { col = 18, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 1, row = 3 }, start = { col = 21, row = 2 } } (Newlines [] 0) + ] + } + , { name = "type-alias-funky-indentation-2" + , source = """type alias + Model = + List Int +""" + , pretty = """ + ( ( Ok + , ( TypeAlias + , ( ty, Model ) + , ( genericArgs, () ) + , ( expr + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, List ) + , ( args + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, Int ) + , ( args, () ) + ) + ) ) + ) + ) + ) + ) + ) + ) ) +""" + , contextualized = + Just + [ Ok + (TypeAlias + { expr = + UserDefinedType + { args = + [ UserDefinedType + { args = [] + , name = "Int" + , qualifiedness = PossiblyQualified Nothing + } + ] + , name = "List" + , qualifiedness = PossiblyQualified Nothing + } + , genericArgs = [] + , ty = UpperCase "Model" + } + ) + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 5, row = 2 }, start = { col = 11, row = 1 } } (Newlines [] 4) + , Located { end = { col = 10, row = 2 }, start = { col = 5, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Model"), qualifiers = [] })) + , Located { end = { col = 11, row = 2 }, start = { col = 10, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 12, row = 2 }, start = { col = 11, row = 2 } } (Token (Sigil Assign)) + , Located { end = { col = 2, row = 3 }, start = { col = 12, row = 2 } } (Newlines [] 1) + , Located { end = { col = 6, row = 3 }, start = { col = 2, row = 3 } } (Token (Identifier { name = TokenUpperCase (UpperCase "List"), qualifiers = [] })) + , Located { end = { col = 7, row = 3 }, start = { col = 6, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 10, row = 3 }, start = { col = 7, row = 3 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 1, row = 4 }, start = { col = 10, row = 3 } } (Newlines [] 0) + ] + } + , { name = "type-alias-qualified-type" + , source = """type alias A = B.C.D + +type alias A = List B.C.D""" + , pretty = """ + ( ( Ok + , ( TypeAlias + , ( ty, A ) + , ( genericArgs, () ) + , ( expr + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified + , ( Just, B.C ) + ) + ) + , ( name, D ) + , ( args, () ) + ) + ) + ) + ) + ) + , ( Ok + , ( TypeAlias + , ( ty, A ) + , ( genericArgs, () ) + , ( expr + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified + , ( Just, B.C ) + ) + ) + , ( name, List ) + , ( args + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified + , ( Just, B.C ) + ) + ) + , ( name, D ) + , ( args, () ) + ) + ) ) + ) + ) + ) + ) + ) + ) + ) +""" + , contextualized = + Just + [ Ok + (TypeAlias + { expr = + UserDefinedType + { args = [] + , name = "D" + , qualifiedness = PossiblyQualified (Just "B.C") + } + , genericArgs = [] + , ty = UpperCase "A" + } + ) + , Ok + (TypeAlias + { expr = + UserDefinedType + { args = + [ UserDefinedType + { args = [] + , name = "D" + , qualifiedness = PossiblyQualified (Just "B.C") + } + ] + , name = "List" + , qualifiedness = PossiblyQualified (Just "B.C") + } + , genericArgs = [] + , ty = UpperCase "A" + } + ) + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 13, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "A"), qualifiers = [] })) + , Located { end = { col = 14, row = 1 }, start = { col = 13, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 15, row = 1 }, start = { col = 14, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 16, row = 1 }, start = { col = 15, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 21, row = 1 }, start = { col = 16, row = 1 } } + (Token + (Identifier + { name = TokenUpperCase (UpperCase "D") + , qualifiers = + [ UpperCase "B" + , UpperCase "C" + ] + } + ) + ) + , Located { end = { col = 1, row = 3 }, start = { col = 21, row = 1 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 5, row = 3 }, start = { col = 1, row = 3 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 3 }, start = { col = 5, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 3 }, start = { col = 6, row = 3 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 3 }, start = { col = 11, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 13, row = 3 }, start = { col = 12, row = 3 } } (Token (Identifier { name = TokenUpperCase (UpperCase "A"), qualifiers = [] })) + , Located { end = { col = 14, row = 3 }, start = { col = 13, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 15, row = 3 }, start = { col = 14, row = 3 } } (Token (Sigil Assign)) + , Located { end = { col = 16, row = 3 }, start = { col = 15, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 20, row = 3 }, start = { col = 16, row = 3 } } (Token (Identifier { name = TokenUpperCase (UpperCase "List"), qualifiers = [] })) + , Located { end = { col = 21, row = 3 }, start = { col = 20, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 26, row = 3 }, start = { col = 21, row = 3 } } + (Token + (Identifier + { name = TokenUpperCase (UpperCase "D") + , qualifiers = + [ UpperCase "B" + , UpperCase "C" + ] + } + ) + ) + ] + } + , { name = "type-alias-record-3-entries" + , source = """type alias Ty = { a: A, b: B, c: C } +""" + , pretty = """ + ( ( Ok + , ( TypeAlias + , ( ty, Ty ) + , ( genericArgs, () ) + , ( expr + , ( Record + , ( ( a + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, A ) + , ( args, () ) + ) + ) + ) + , ( b + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, B ) + , ( args, () ) + ) + ) + ) + , ( c + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, C ) + , ( args, () ) + ) + ) + ) + ) + ) + ) + ) + ) ) +""" + , contextualized = + Just + [ Ok + (TypeAlias + { expr = + Record + (Dict.fromList + [ ( "a" + , UserDefinedType + { args = [] + , name = "A" + , qualifiedness = PossiblyQualified Nothing + } + ) + , ( "b" + , UserDefinedType + { args = [] + , name = "B" + , qualifiedness = PossiblyQualified Nothing + } + ) + , ( "c" + , UserDefinedType + { args = [] + , name = "C" + , qualifiedness = PossiblyQualified Nothing + } + ) + ] + ) + , genericArgs = [] + , ty = UpperCase "Ty" + } + ) + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Ty"), qualifiers = [] })) + , Located { end = { col = 15, row = 1 }, start = { col = 14, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 1 }, start = { col = 15, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 17, row = 1 }, start = { col = 16, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 1 }, start = { col = 17, row = 1 } } (Token (Sigil (Bracket Curly Open))) + , Located { end = { col = 19, row = 1 }, start = { col = 18, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 20, row = 1 }, start = { col = 19, row = 1 } } (Token (Identifier { name = TokenLowerCase (LowerCase "a"), qualifiers = [] })) + , Located { end = { col = 21, row = 1 }, start = { col = 20, row = 1 } } (Token (Sigil Colon)) + , Located { end = { col = 22, row = 1 }, start = { col = 21, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 23, row = 1 }, start = { col = 22, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "A"), qualifiers = [] })) + , Located { end = { col = 24, row = 1 }, start = { col = 23, row = 1 } } (Token (Sigil Comma)) + , Located { end = { col = 25, row = 1 }, start = { col = 24, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 26, row = 1 }, start = { col = 25, row = 1 } } (Token (Identifier { name = TokenLowerCase (LowerCase "b"), qualifiers = [] })) + , Located { end = { col = 27, row = 1 }, start = { col = 26, row = 1 } } (Token (Sigil Colon)) + , Located { end = { col = 28, row = 1 }, start = { col = 27, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 29, row = 1 }, start = { col = 28, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "B"), qualifiers = [] })) + , Located { end = { col = 30, row = 1 }, start = { col = 29, row = 1 } } (Token (Sigil Comma)) + , Located { end = { col = 31, row = 1 }, start = { col = 30, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 32, row = 1 }, start = { col = 31, row = 1 } } (Token (Identifier { name = TokenLowerCase (LowerCase "c"), qualifiers = [] })) + , Located { end = { col = 33, row = 1 }, start = { col = 32, row = 1 } } (Token (Sigil Colon)) + , Located { end = { col = 34, row = 1 }, start = { col = 33, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 35, row = 1 }, start = { col = 34, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "C"), qualifiers = [] })) + , Located { end = { col = 36, row = 1 }, start = { col = 35, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 37, row = 1 }, start = { col = 36, row = 1 } } (Token (Sigil (Bracket Curly Close))) + , Located { end = { col = 1, row = 2 }, start = { col = 37, row = 1 } } (Newlines [] 0) + ] + } + , { name = "type-alias-record-empty" + , source = """type alias Ty = {} +""" + , pretty = """ + ( ( Ok + , ( TypeAlias + , ( ty, Ty ) + , ( genericArgs, () ) + , ( expr + , ( Record, () ) + ) + ) + ) ) +""" + , contextualized = + Just + [ Ok (TypeAlias { expr = Record (Dict.fromList []), genericArgs = [], ty = UpperCase "Ty" }) + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Ty"), qualifiers = [] })) + , Located { end = { col = 15, row = 1 }, start = { col = 14, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 1 }, start = { col = 15, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 17, row = 1 }, start = { col = 16, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 1 }, start = { col = 17, row = 1 } } (Token (Sigil (Bracket Curly Open))) + , Located { end = { col = 19, row = 1 }, start = { col = 18, row = 1 } } (Token (Sigil (Bracket Curly Close))) + , Located { end = { col = 1, row = 2 }, start = { col = 19, row = 1 } } (Newlines [] 0) + ] + } + , { name = "type-alias-record-empty-multiline" + , source = """type alias Ty = { + + + } +""" + , pretty = """ + ( ( Ok + , ( TypeAlias + , ( ty, Ty ) + , ( genericArgs, () ) + , ( expr + , ( Record, () ) + ) + ) + ) ) +""" + , contextualized = + Just + [ Ok (TypeAlias { expr = Record (Dict.fromList []), genericArgs = [], ty = UpperCase "Ty" }) + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Ty"), qualifiers = [] })) + , Located { end = { col = 15, row = 1 }, start = { col = 14, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 1 }, start = { col = 15, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 17, row = 1 }, start = { col = 16, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 1 }, start = { col = 17, row = 1 } } (Token (Sigil (Bracket Curly Open))) + , Located { end = { col = 5, row = 4 }, start = { col = 18, row = 1 } } + (Newlines + [ 0 + , 0 + ] + 4 + ) + , Located { end = { col = 6, row = 4 }, start = { col = 5, row = 4 } } (Token (Sigil (Bracket Curly Close))) + , Located { end = { col = 1, row = 5 }, start = { col = 6, row = 4 } } (Newlines [] 0) + ] + } + , { name = "type-alias-record-in-bracket" + , source = """type alias Ty = ({ hi: Int }) +""" + , pretty = """ + ( ( Ok + , ( TypeAlias + , ( ty, Ty ) + , ( genericArgs, () ) + , ( expr + , ( Record + , ( ( hi + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, Int ) + , ( args, () ) + ) + ) + ) ) + ) + ) + ) + ) ) +""" + , contextualized = + Just + [ Ok + (TypeAlias + { expr = + Record + (Dict.fromList + [ ( "hi" + , UserDefinedType + { args = [] + , name = "Int" + , qualifiedness = PossiblyQualified Nothing + } + ) + ] + ) + , genericArgs = [] + , ty = UpperCase "Ty" + } + ) + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Ty"), qualifiers = [] })) + , Located { end = { col = 15, row = 1 }, start = { col = 14, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 1 }, start = { col = 15, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 17, row = 1 }, start = { col = 16, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 1 }, start = { col = 17, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 19, row = 1 }, start = { col = 18, row = 1 } } (Token (Sigil (Bracket Curly Open))) + , Located { end = { col = 20, row = 1 }, start = { col = 19, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 22, row = 1 }, start = { col = 20, row = 1 } } (Token (Identifier { name = TokenLowerCase (LowerCase "hi"), qualifiers = [] })) + , Located { end = { col = 23, row = 1 }, start = { col = 22, row = 1 } } (Token (Sigil Colon)) + , Located { end = { col = 24, row = 1 }, start = { col = 23, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 27, row = 1 }, start = { col = 24, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 28, row = 1 }, start = { col = 27, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 29, row = 1 }, start = { col = 28, row = 1 } } (Token (Sigil (Bracket Curly Close))) + , Located { end = { col = 30, row = 1 }, start = { col = 29, row = 1 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 1, row = 2 }, start = { col = 30, row = 1 } } (Newlines [] 0) + ] + } + , { name = "type-alias-record-nested" + , source = """type alias Ty = + { hi: { a: Int, b: List String } + , ih: CustomType A B C (D E) + } +""" + , pretty = """ + ( ( Ok + , ( TypeAlias + , ( ty, Ty ) + , ( genericArgs, () ) + , ( expr + , ( Record + , ( ( hi + , ( Record + , ( ( a + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, Int ) + , ( args, () ) + ) + ) + ) + , ( b + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, List ) + , ( args + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, String ) + , ( args, () ) + ) + ) ) + ) + ) + ) + ) + ) + ) + ) + , ( ih + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, CustomType ) + , ( args + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, A ) + , ( args, () ) + ) + ) + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, B ) + , ( args, () ) + ) + ) + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, C ) + , ( args, () ) + ) + ) + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, D ) + , ( args + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, E ) + , ( args, () ) + ) + ) ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) ) +""" + , contextualized = + Just + [ Ok + (TypeAlias + { expr = + Record + (Dict.fromList + [ ( "hi" + , Record + (Dict.fromList + [ ( "a" + , UserDefinedType + { args = [] + , name = "Int" + , qualifiedness = PossiblyQualified Nothing + } + ) + , ( "b" + , UserDefinedType + { args = + [ UserDefinedType + { args = [] + , name = "String" + , qualifiedness = PossiblyQualified Nothing + } + ] + , name = "List" + , qualifiedness = PossiblyQualified Nothing + } + ) + ] + ) + ) + , ( "ih" + , UserDefinedType + { args = + [ UserDefinedType + { args = [] + , name = "A" + , qualifiedness = PossiblyQualified Nothing + } + , UserDefinedType + { args = [] + , name = "B" + , qualifiedness = PossiblyQualified Nothing + } + , UserDefinedType + { args = [] + , name = "C" + , qualifiedness = PossiblyQualified Nothing + } + , UserDefinedType + { args = + [ UserDefinedType + { args = [] + , name = "E" + , qualifiedness = PossiblyQualified Nothing + } + ] + , name = "D" + , qualifiedness = PossiblyQualified Nothing + } + ] + , name = "CustomType" + , qualifiedness = PossiblyQualified Nothing + } + ) + ] + ) + , genericArgs = [] + , ty = UpperCase "Ty" + } + ) + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Ty"), qualifiers = [] })) + , Located { end = { col = 15, row = 1 }, start = { col = 14, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 1 }, start = { col = 15, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 5, row = 2 }, start = { col = 16, row = 1 } } (Newlines [] 4) + , Located { end = { col = 6, row = 2 }, start = { col = 5, row = 2 } } (Token (Sigil (Bracket Curly Open))) + , Located { end = { col = 7, row = 2 }, start = { col = 6, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 9, row = 2 }, start = { col = 7, row = 2 } } (Token (Identifier { name = TokenLowerCase (LowerCase "hi"), qualifiers = [] })) + , Located { end = { col = 10, row = 2 }, start = { col = 9, row = 2 } } (Token (Sigil Colon)) + , Located { end = { col = 12, row = 2 }, start = { col = 10, row = 2 } } (Ignorable (Whitespace 2)) + , Located { end = { col = 13, row = 2 }, start = { col = 12, row = 2 } } (Token (Sigil (Bracket Curly Open))) + , Located { end = { col = 14, row = 2 }, start = { col = 13, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 15, row = 2 }, start = { col = 14, row = 2 } } (Token (Identifier { name = TokenLowerCase (LowerCase "a"), qualifiers = [] })) + , Located { end = { col = 16, row = 2 }, start = { col = 15, row = 2 } } (Token (Sigil Colon)) + , Located { end = { col = 17, row = 2 }, start = { col = 16, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 20, row = 2 }, start = { col = 17, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 21, row = 2 }, start = { col = 20, row = 2 } } (Token (Sigil Comma)) + , Located { end = { col = 22, row = 2 }, start = { col = 21, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 23, row = 2 }, start = { col = 22, row = 2 } } (Token (Identifier { name = TokenLowerCase (LowerCase "b"), qualifiers = [] })) + , Located { end = { col = 24, row = 2 }, start = { col = 23, row = 2 } } (Token (Sigil Colon)) + , Located { end = { col = 25, row = 2 }, start = { col = 24, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 29, row = 2 }, start = { col = 25, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "List"), qualifiers = [] })) + , Located { end = { col = 30, row = 2 }, start = { col = 29, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 36, row = 2 }, start = { col = 30, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "String"), qualifiers = [] })) + , Located { end = { col = 37, row = 2 }, start = { col = 36, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 38, row = 2 }, start = { col = 37, row = 2 } } (Token (Sigil (Bracket Curly Close))) + , Located { end = { col = 5, row = 3 }, start = { col = 38, row = 2 } } (Newlines [] 4) + , Located { end = { col = 6, row = 3 }, start = { col = 5, row = 3 } } (Token (Sigil Comma)) + , Located { end = { col = 7, row = 3 }, start = { col = 6, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 9, row = 3 }, start = { col = 7, row = 3 } } (Token (Identifier { name = TokenLowerCase (LowerCase "ih"), qualifiers = [] })) + , Located { end = { col = 10, row = 3 }, start = { col = 9, row = 3 } } (Token (Sigil Colon)) + , Located { end = { col = 11, row = 3 }, start = { col = 10, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 21, row = 3 }, start = { col = 11, row = 3 } } (Token (Identifier { name = TokenUpperCase (UpperCase "CustomType"), qualifiers = [] })) + , Located { end = { col = 22, row = 3 }, start = { col = 21, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 23, row = 3 }, start = { col = 22, row = 3 } } (Token (Identifier { name = TokenUpperCase (UpperCase "A"), qualifiers = [] })) + , Located { end = { col = 24, row = 3 }, start = { col = 23, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 25, row = 3 }, start = { col = 24, row = 3 } } (Token (Identifier { name = TokenUpperCase (UpperCase "B"), qualifiers = [] })) + , Located { end = { col = 26, row = 3 }, start = { col = 25, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 27, row = 3 }, start = { col = 26, row = 3 } } (Token (Identifier { name = TokenUpperCase (UpperCase "C"), qualifiers = [] })) + , Located { end = { col = 28, row = 3 }, start = { col = 27, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 29, row = 3 }, start = { col = 28, row = 3 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 30, row = 3 }, start = { col = 29, row = 3 } } (Token (Identifier { name = TokenUpperCase (UpperCase "D"), qualifiers = [] })) + , Located { end = { col = 31, row = 3 }, start = { col = 30, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 32, row = 3 }, start = { col = 31, row = 3 } } (Token (Identifier { name = TokenUpperCase (UpperCase "E"), qualifiers = [] })) + , Located { end = { col = 33, row = 3 }, start = { col = 32, row = 3 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 5, row = 4 }, start = { col = 33, row = 3 } } (Newlines [] 4) + , Located { end = { col = 6, row = 4 }, start = { col = 5, row = 4 } } (Token (Sigil (Bracket Curly Close))) + , Located { end = { col = 1, row = 5 }, start = { col = 6, row = 4 } } (Newlines [] 0) + ] + } + , { name = "type-alias-record-simple" + , source = """type alias Ty = { hi: Int } +""" + , pretty = """ + ( ( Ok + , ( TypeAlias + , ( ty, Ty ) + , ( genericArgs, () ) + , ( expr + , ( Record + , ( ( hi + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, Int ) + , ( args, () ) + ) + ) + ) ) + ) + ) + ) + ) ) +""" + , contextualized = + Just + [ Ok + (TypeAlias + { expr = + Record + (Dict.fromList + [ ( "hi" + , UserDefinedType + { args = [] + , name = "Int" + , qualifiedness = PossiblyQualified Nothing + } + ) + ] + ) + , genericArgs = [] + , ty = UpperCase "Ty" + } + ) + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Ty"), qualifiers = [] })) + , Located { end = { col = 15, row = 1 }, start = { col = 14, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 1 }, start = { col = 15, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 17, row = 1 }, start = { col = 16, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 1 }, start = { col = 17, row = 1 } } (Token (Sigil (Bracket Curly Open))) + , Located { end = { col = 19, row = 1 }, start = { col = 18, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 21, row = 1 }, start = { col = 19, row = 1 } } (Token (Identifier { name = TokenLowerCase (LowerCase "hi"), qualifiers = [] })) + , Located { end = { col = 22, row = 1 }, start = { col = 21, row = 1 } } (Token (Sigil Colon)) + , Located { end = { col = 23, row = 1 }, start = { col = 22, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 26, row = 1 }, start = { col = 23, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 27, row = 1 }, start = { col = 26, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 28, row = 1 }, start = { col = 27, row = 1 } } (Token (Sigil (Bracket Curly Close))) + , Located { end = { col = 1, row = 2 }, start = { col = 28, row = 1 } } (Newlines [] 0) + ] + } + , { name = "type-alias-record-two-entries" + , source = """type alias Ty = { hi: (), buy: String } +""" + , pretty = """ + ( ( Ok + , ( TypeAlias + , ( ty, Ty ) + , ( genericArgs, () ) + , ( expr + , ( Record + , ( ( buy + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, String ) + , ( args, () ) + ) + ) + ) + , ( hi, Unit ) + ) + ) + ) + ) + ) ) +""" + , contextualized = + Just + [ Ok + (TypeAlias + { expr = + Record + (Dict.fromList + [ ( "buy" + , UserDefinedType + { args = [] + , name = "String" + , qualifiedness = PossiblyQualified Nothing + } + ) + , ( "hi", Unit ) + ] + ) + , genericArgs = [] + , ty = UpperCase "Ty" + } + ) + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Ty"), qualifiers = [] })) + , Located { end = { col = 15, row = 1 }, start = { col = 14, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 1 }, start = { col = 15, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 17, row = 1 }, start = { col = 16, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 1 }, start = { col = 17, row = 1 } } (Token (Sigil (Bracket Curly Open))) + , Located { end = { col = 19, row = 1 }, start = { col = 18, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 21, row = 1 }, start = { col = 19, row = 1 } } (Token (Identifier { name = TokenLowerCase (LowerCase "hi"), qualifiers = [] })) + , Located { end = { col = 22, row = 1 }, start = { col = 21, row = 1 } } (Token (Sigil Colon)) + , Located { end = { col = 23, row = 1 }, start = { col = 22, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 24, row = 1 }, start = { col = 23, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 25, row = 1 }, start = { col = 24, row = 1 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 26, row = 1 }, start = { col = 25, row = 1 } } (Token (Sigil Comma)) + , Located { end = { col = 27, row = 1 }, start = { col = 26, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 30, row = 1 }, start = { col = 27, row = 1 } } (Token (Identifier { name = TokenLowerCase (LowerCase "buy"), qualifiers = [] })) + , Located { end = { col = 31, row = 1 }, start = { col = 30, row = 1 } } (Token (Sigil Colon)) + , Located { end = { col = 32, row = 1 }, start = { col = 31, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 38, row = 1 }, start = { col = 32, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "String"), qualifiers = [] })) + , Located { end = { col = 39, row = 1 }, start = { col = 38, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 40, row = 1 }, start = { col = 39, row = 1 } } (Token (Sigil (Bracket Curly Close))) + , Located { end = { col = 1, row = 2 }, start = { col = 40, row = 1 } } (Newlines [] 0) + ] + } + , { name = "type-alias-unit" + , source = """type alias Hi = () +""" + , pretty = """ + ( ( Ok + , ( TypeAlias + , ( ty, Hi ) + , ( genericArgs, () ) + , ( expr, Unit ) + ) + ) ) +""" + , contextualized = + Just + [ Ok (TypeAlias { expr = Unit, genericArgs = [], ty = UpperCase "Hi" }) + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Hi"), qualifiers = [] })) + , Located { end = { col = 15, row = 1 }, start = { col = 14, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 1 }, start = { col = 15, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 17, row = 1 }, start = { col = 16, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 1 }, start = { col = 17, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 19, row = 1 }, start = { col = 18, row = 1 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 1, row = 2 }, start = { col = 19, row = 1 } } (Newlines [] 0) + ] + } + , { name = "type-alias-with-bracket" + , source = """type alias Hi = (Int) +""" + , pretty = """ + ( ( Ok + , ( TypeAlias + , ( ty, Hi ) + , ( genericArgs, () ) + , ( expr + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, Int ) + , ( args, () ) + ) + ) + ) + ) + ) ) +""" + , contextualized = + Just + [ Ok + (TypeAlias + { expr = + UserDefinedType + { args = [] + , name = "Int" + , qualifiedness = PossiblyQualified Nothing + } + , genericArgs = [] + , ty = UpperCase "Hi" + } + ) + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Hi"), qualifiers = [] })) + , Located { end = { col = 15, row = 1 }, start = { col = 14, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 1 }, start = { col = 15, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 17, row = 1 }, start = { col = 16, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 1 }, start = { col = 17, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 21, row = 1 }, start = { col = 18, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 22, row = 1 }, start = { col = 21, row = 1 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 1, row = 2 }, start = { col = 22, row = 1 } } (Newlines [] 0) + ] + } + , { name = "type-alias-with-bracket-2" + , source = """type alias Hi = (List Int) +""" + , pretty = """ + ( ( Ok + , ( TypeAlias + , ( ty, Hi ) + , ( genericArgs, () ) + , ( expr + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, List ) + , ( args + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, Int ) + , ( args, () ) + ) + ) ) + ) + ) + ) + ) + ) + ) ) +""" + , contextualized = + Just + [ Ok + (TypeAlias + { expr = + UserDefinedType + { args = + [ UserDefinedType + { args = [] + , name = "Int" + , qualifiedness = PossiblyQualified Nothing + } + ] + , name = "List" + , qualifiedness = PossiblyQualified Nothing + } + , genericArgs = [] + , ty = UpperCase "Hi" + } + ) + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Hi"), qualifiers = [] })) + , Located { end = { col = 15, row = 1 }, start = { col = 14, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 1 }, start = { col = 15, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 17, row = 1 }, start = { col = 16, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 1 }, start = { col = 17, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 22, row = 1 }, start = { col = 18, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "List"), qualifiers = [] })) + , Located { end = { col = 23, row = 1 }, start = { col = 22, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 26, row = 1 }, start = { col = 23, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 27, row = 1 }, start = { col = 26, row = 1 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 1, row = 2 }, start = { col = 27, row = 1 } } (Newlines [] 0) + ] + } + , { name = "type-alias-with-pair" + , source = """type alias Hi = (Int, List String) +type alias Hi = (Int) +""" + , pretty = """ + ( ( Ok + , ( TypeAlias + , ( ty, Hi ) + , ( genericArgs, () ) + , ( expr + , ( Tuple + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, Int ) + , ( args, () ) + ) + ) + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, List ) + , ( args + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, String ) + , ( args, () ) + ) + ) ) + ) + ) + ) + ) + ) + ) + ) + ) + , ( Ok + , ( TypeAlias + , ( ty, Hi ) + , ( genericArgs, () ) + , ( expr + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, Int ) + , ( args, () ) + ) + ) + ) + ) + ) + ) +""" + , contextualized = + Just + [ Ok + (TypeAlias + { expr = + Tuple + (UserDefinedType + { args = [] + , name = "Int" + , qualifiedness = PossiblyQualified Nothing + } + ) + (UserDefinedType + { args = + [ UserDefinedType + { args = [] + , name = "String" + , qualifiedness = PossiblyQualified Nothing + } + ] + , name = "List" + , qualifiedness = PossiblyQualified Nothing + } + ) + , genericArgs = [] + , ty = UpperCase "Hi" + } + ) + , Ok + (TypeAlias + { expr = + UserDefinedType + { args = [] + , name = "Int" + , qualifiedness = PossiblyQualified Nothing + } + , genericArgs = [] + , ty = UpperCase "Hi" + } + ) + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Hi"), qualifiers = [] })) + , Located { end = { col = 15, row = 1 }, start = { col = 14, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 1 }, start = { col = 15, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 17, row = 1 }, start = { col = 16, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 1 }, start = { col = 17, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 21, row = 1 }, start = { col = 18, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 22, row = 1 }, start = { col = 21, row = 1 } } (Token (Sigil Comma)) + , Located { end = { col = 23, row = 1 }, start = { col = 22, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 27, row = 1 }, start = { col = 23, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "List"), qualifiers = [] })) + , Located { end = { col = 28, row = 1 }, start = { col = 27, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 34, row = 1 }, start = { col = 28, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "String"), qualifiers = [] })) + , Located { end = { col = 35, row = 1 }, start = { col = 34, row = 1 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 1, row = 2 }, start = { col = 35, row = 1 } } (Newlines [] 0) + , Located { end = { col = 5, row = 2 }, start = { col = 1, row = 2 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 2 }, start = { col = 5, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 2 }, start = { col = 6, row = 2 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 2 }, start = { col = 11, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 2 }, start = { col = 12, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Hi"), qualifiers = [] })) + , Located { end = { col = 15, row = 2 }, start = { col = 14, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 2 }, start = { col = 15, row = 2 } } (Token (Sigil Assign)) + , Located { end = { col = 17, row = 2 }, start = { col = 16, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 2 }, start = { col = 17, row = 2 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 21, row = 2 }, start = { col = 18, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 22, row = 2 }, start = { col = 21, row = 2 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 1, row = 3 }, start = { col = 22, row = 2 } } (Newlines [] 0) + ] + } + , { name = "type-alias-with-tripple" + , source = """type alias Hi = (Int, Two, Three) +type alias Hi = ((), (), ()) +""" + , pretty = """ + ( ( Ok + , ( TypeAlias + , ( ty, Hi ) + , ( genericArgs, () ) + , ( expr + , ( Tuple + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, Int ) + , ( args, () ) + ) + ) + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, Two ) + , ( args, () ) + ) + ) + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, Three ) + , ( args, () ) + ) + ) + ) + ) + ) + ) + ) + , ( Ok + , ( TypeAlias + , ( ty, Hi ) + , ( genericArgs, () ) + , ( expr + , ( Tuple + , ( Unit + , Unit + , Unit + ) + ) + ) + ) + ) + ) +""" + , contextualized = + Just + [ Ok + (TypeAlias + { expr = + Tuple3 + (UserDefinedType + { args = [] + , name = "Int" + , qualifiedness = PossiblyQualified Nothing + } + ) + (UserDefinedType + { args = [] + , name = "Two" + , qualifiedness = PossiblyQualified Nothing + } + ) + (UserDefinedType + { args = [] + , name = "Three" + , qualifiedness = PossiblyQualified Nothing + } + ) + , genericArgs = [] + , ty = UpperCase "Hi" + } + ) + , Ok (TypeAlias { expr = Tuple3 Unit Unit Unit, genericArgs = [], ty = UpperCase "Hi" }) + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Hi"), qualifiers = [] })) + , Located { end = { col = 15, row = 1 }, start = { col = 14, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 1 }, start = { col = 15, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 17, row = 1 }, start = { col = 16, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 1 }, start = { col = 17, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 21, row = 1 }, start = { col = 18, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 22, row = 1 }, start = { col = 21, row = 1 } } (Token (Sigil Comma)) + , Located { end = { col = 23, row = 1 }, start = { col = 22, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 26, row = 1 }, start = { col = 23, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Two"), qualifiers = [] })) + , Located { end = { col = 27, row = 1 }, start = { col = 26, row = 1 } } (Token (Sigil Comma)) + , Located { end = { col = 28, row = 1 }, start = { col = 27, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 33, row = 1 }, start = { col = 28, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Three"), qualifiers = [] })) + , Located { end = { col = 34, row = 1 }, start = { col = 33, row = 1 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 1, row = 2 }, start = { col = 34, row = 1 } } (Newlines [] 0) + , Located { end = { col = 5, row = 2 }, start = { col = 1, row = 2 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 2 }, start = { col = 5, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 2 }, start = { col = 6, row = 2 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 2 }, start = { col = 11, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 2 }, start = { col = 12, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Hi"), qualifiers = [] })) + , Located { end = { col = 15, row = 2 }, start = { col = 14, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 2 }, start = { col = 15, row = 2 } } (Token (Sigil Assign)) + , Located { end = { col = 17, row = 2 }, start = { col = 16, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 2 }, start = { col = 17, row = 2 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 19, row = 2 }, start = { col = 18, row = 2 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 20, row = 2 }, start = { col = 19, row = 2 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 21, row = 2 }, start = { col = 20, row = 2 } } (Token (Sigil Comma)) + , Located { end = { col = 22, row = 2 }, start = { col = 21, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 23, row = 2 }, start = { col = 22, row = 2 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 24, row = 2 }, start = { col = 23, row = 2 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 25, row = 2 }, start = { col = 24, row = 2 } } (Token (Sigil Comma)) + , Located { end = { col = 26, row = 2 }, start = { col = 25, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 27, row = 2 }, start = { col = 26, row = 2 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 28, row = 2 }, start = { col = 27, row = 2 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 29, row = 2 }, start = { col = 28, row = 2 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 1, row = 3 }, start = { col = 29, row = 2 } } (Newlines [] 0) + ] + } + , { name = "type-alias-with-tripple-in-record" + , source = """type alias Hi = + { a: (Int, Int, Int) + , b: ({ good_bye: () }) + } +""" + , pretty = """ + ( ( Ok + , ( TypeAlias + , ( ty, Hi ) + , ( genericArgs, () ) + , ( expr + , ( Record + , ( ( a + , ( Tuple + , ( ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, Int ) + , ( args, () ) + ) + ) + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, Int ) + , ( args, () ) + ) + ) + , ( UserDefinedType + , ( ( qualifiedness + , ( PossiblyQualified, Nothing ) + ) + , ( name, Int ) + , ( args, () ) + ) + ) + ) + ) + ) + , ( b + , ( Record + , ( ( good_bye, Unit ) ) + ) + ) + ) + ) + ) + ) + ) ) +""" + , contextualized = + Just + [ Ok + (TypeAlias + { expr = + Record + (Dict.fromList + [ ( "a" + , Tuple3 + (UserDefinedType + { args = [] + , name = "Int" + , qualifiedness = PossiblyQualified Nothing + } + ) + (UserDefinedType + { args = [] + , name = "Int" + , qualifiedness = PossiblyQualified Nothing + } + ) + (UserDefinedType + { args = [] + , name = "Int" + , qualifiedness = PossiblyQualified Nothing + } + ) + ) + , ( "b" + , Record + (Dict.fromList + [ ( "good_bye", Unit ) + ] + ) + ) + ] + ) + , genericArgs = [] + , ty = UpperCase "Hi" + } + ) + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Hi"), qualifiers = [] })) + , Located { end = { col = 15, row = 1 }, start = { col = 14, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 1 }, start = { col = 15, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 5, row = 2 }, start = { col = 16, row = 1 } } (Newlines [] 4) + , Located { end = { col = 6, row = 2 }, start = { col = 5, row = 2 } } (Token (Sigil (Bracket Curly Open))) + , Located { end = { col = 7, row = 2 }, start = { col = 6, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 8, row = 2 }, start = { col = 7, row = 2 } } (Token (Identifier { name = TokenLowerCase (LowerCase "a"), qualifiers = [] })) + , Located { end = { col = 9, row = 2 }, start = { col = 8, row = 2 } } (Token (Sigil Colon)) + , Located { end = { col = 10, row = 2 }, start = { col = 9, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 2 }, start = { col = 10, row = 2 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 14, row = 2 }, start = { col = 11, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 15, row = 2 }, start = { col = 14, row = 2 } } (Token (Sigil Comma)) + , Located { end = { col = 16, row = 2 }, start = { col = 15, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 19, row = 2 }, start = { col = 16, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 20, row = 2 }, start = { col = 19, row = 2 } } (Token (Sigil Comma)) + , Located { end = { col = 21, row = 2 }, start = { col = 20, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 24, row = 2 }, start = { col = 21, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 25, row = 2 }, start = { col = 24, row = 2 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 5, row = 3 }, start = { col = 25, row = 2 } } (Newlines [] 4) + , Located { end = { col = 6, row = 3 }, start = { col = 5, row = 3 } } (Token (Sigil Comma)) + , Located { end = { col = 7, row = 3 }, start = { col = 6, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 8, row = 3 }, start = { col = 7, row = 3 } } (Token (Identifier { name = TokenLowerCase (LowerCase "b"), qualifiers = [] })) + , Located { end = { col = 9, row = 3 }, start = { col = 8, row = 3 } } (Token (Sigil Colon)) + , Located { end = { col = 10, row = 3 }, start = { col = 9, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 3 }, start = { col = 10, row = 3 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 12, row = 3 }, start = { col = 11, row = 3 } } (Token (Sigil (Bracket Curly Open))) + , Located { end = { col = 13, row = 3 }, start = { col = 12, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 21, row = 3 }, start = { col = 13, row = 3 } } (Token (Identifier { name = TokenLowerCase (LowerCase "good_bye"), qualifiers = [] })) + , Located { end = { col = 22, row = 3 }, start = { col = 21, row = 3 } } (Token (Sigil Colon)) + , Located { end = { col = 23, row = 3 }, start = { col = 22, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 24, row = 3 }, start = { col = 23, row = 3 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 25, row = 3 }, start = { col = 24, row = 3 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 26, row = 3 }, start = { col = 25, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 27, row = 3 }, start = { col = 26, row = 3 } } (Token (Sigil (Bracket Curly Close))) + , Located { end = { col = 28, row = 3 }, start = { col = 27, row = 3 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 5, row = 4 }, start = { col = 28, row = 3 } } (Newlines [] 4) + , Located { end = { col = 6, row = 4 }, start = { col = 5, row = 4 } } (Token (Sigil (Bracket Curly Close))) + , Located { end = { col = 1, row = 5 }, start = { col = 6, row = 4 } } (Newlines [] 0) + ] + } + ] + + +shouldNotParseTestCases : + List + { contextualized : Maybe (List Contextualize.RunResult) + , pretty : String + , lexed : Result Never (List (Located LexItem)) + , name : String + , source : String + } +shouldNotParseTestCases = + [ { name = "dots" + , source = """Foo. + +Foo.Bar + +Foo.Bar.baz + +Boor.Bing. + +Bor. Big. + +.sf + +sfsdf .sdfsd + +asfasf.sdgsghj + +(shdf).helloLiteral + +(sjhsf) .helloFunction + +sfhsdf(.helloFunction) + +case.hi + +Hi.case + +case .hi + +Hi. case""" + , pretty = """ + ( ( Err, todo ) + , ( Err, todo ) + , ( Err, todo ) + , ( Err, todo ) + , ( Err, todo ) + , ( Err, todo ) + , ( Err, todo ) + , ( Err, todo ) + , ( Err, todo ) + , ( Err, todo ) + , ( Err, todo ) + , ( Err, todo ) + , ( Err, todo ) + , ( Err, todo ) + , ( Err, todo ) + , ( Err, todo ) + ) +""" + , contextualized = + Just + [ Err + { error = Error_InvalidToken Expecting_Unknown + , item = Just (Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Invalid (IdentifierWithTrailingDot { name = UpperCase "Foo", qualifiers = [] }))) + , state = State_BlockStart + } + , Err + { error = + Error_BlockStartsWithQualifiedName + { name = TokenUpperCase (UpperCase "Bar") + , qualifiers = + [ UpperCase "Foo" + ] + } + , item = + Just + (Located { end = { col = 8, row = 3 }, start = { col = 1, row = 3 } } + (Token + (Identifier + { name = TokenUpperCase (UpperCase "Bar") + , qualifiers = + [ UpperCase "Foo" + ] + } + ) + ) + ) + , state = State_BlockStart + } + , Err + { error = + Error_BlockStartsWithQualifiedName + { name = TokenLowerCase (LowerCase "baz") + , qualifiers = + [ UpperCase "Foo" + , UpperCase "Bar" + ] + } + , item = + Just + (Located { end = { col = 12, row = 5 }, start = { col = 1, row = 5 } } + (Token + (Identifier + { name = TokenLowerCase (LowerCase "baz") + , qualifiers = + [ UpperCase "Foo" + , UpperCase "Bar" + ] + } + ) + ) + ) + , state = State_BlockStart + } + , Err + { error = Error_InvalidToken Expecting_Unknown + , item = + Just + (Located { end = { col = 11, row = 7 }, start = { col = 1, row = 7 } } + (Invalid + (IdentifierWithTrailingDot + { name = UpperCase "Bing" + , qualifiers = + [ UpperCase "Boor" + ] + } + ) + ) + ) + , state = State_BlockStart + } + , Err + { error = Error_InvalidToken Expecting_Unknown + , item = Just (Located { end = { col = 5, row = 9 }, start = { col = 1, row = 9 } } (Invalid (IdentifierWithTrailingDot { name = UpperCase "Bor", qualifiers = [] }))) + , state = State_BlockStart + } + , Err + { error = Error_InvalidToken Expecting_Unknown + , item = Just (Located { end = { col = 10, row = 9 }, start = { col = 6, row = 9 } } (Invalid (IdentifierWithTrailingDot { name = UpperCase "Big", qualifiers = [] }))) + , state = State_Error_Recovery + } + , Err + { error = Error_InvalidToken Expecting_Block + , item = Just (Located { end = { col = 4, row = 11 }, start = { col = 1, row = 11 } } (Token (RecordAccessorFunction (LowerCase "sf")))) + , state = State_BlockStart + } + , Err + { error = Error_InvalidToken (Expecting_Sigil Assign) + , item = Just (Located { end = { col = 13, row = 13 }, start = { col = 7, row = 13 } } (Token (RecordAccessorFunction (LowerCase "sdfsd")))) + , state = State_BlockValueDeclaration (BlockValueDeclaration_Named { args = Stack [], name = Located { end = { col = 6, row = 13 }, start = { col = 1, row = 13 } } (LowerCase "sfsdf") }) + } + , Err + { error = Error_InvalidToken (Expecting_Sigil Assign) + , item = Just (Located { end = { col = 15, row = 15 }, start = { col = 7, row = 15 } } (Token (RecordAccessorLiteral (LowerCase "sdgsghj")))) + , state = State_BlockValueDeclaration (BlockValueDeclaration_Named { args = Stack [], name = Located { end = { col = 7, row = 15 }, start = { col = 1, row = 15 } } (LowerCase "asfasf") }) + } + , Err + { error = Error_InvalidToken Expecting_Block + , item = Just (Located { end = { col = 2, row = 17 }, start = { col = 1, row = 17 } } (Token (Sigil (Bracket Round Open)))) + , state = State_BlockStart + } + , Err + { error = Error_InvalidToken Expecting_Block + , item = Just (Located { end = { col = 2, row = 19 }, start = { col = 1, row = 19 } } (Token (Sigil (Bracket Round Open)))) + , state = State_BlockStart + } + , Err + { error = Error_InvalidToken (Expecting_Sigil Assign) + , item = Just (Located { end = { col = 8, row = 21 }, start = { col = 7, row = 21 } } (Token (Sigil (Bracket Round Open)))) + , state = State_BlockValueDeclaration (BlockValueDeclaration_Named { args = Stack [], name = Located { end = { col = 7, row = 21 }, start = { col = 1, row = 21 } } (LowerCase "sfhsdf") }) + } + , Err + { error = Error_MisplacedKeyword Case + , item = Just (Located { end = { col = 5, row = 23 }, start = { col = 1, row = 23 } } (Token (Keyword Case))) + , state = State_BlockStart + } + , Err + { error = + Error_BlockStartsWithQualifiedName + { name = TokenLowerCase (LowerCase "case") + , qualifiers = + [ UpperCase "Hi" + ] + } + , item = + Just + (Located { end = { col = 8, row = 25 }, start = { col = 1, row = 25 } } + (Token + (Identifier + { name = TokenLowerCase (LowerCase "case") + , qualifiers = + [ UpperCase "Hi" + ] + } + ) + ) + ) + , state = State_BlockStart + } + , Err + { error = Error_MisplacedKeyword Case + , item = Just (Located { end = { col = 5, row = 27 }, start = { col = 1, row = 27 } } (Token (Keyword Case))) + , state = State_BlockStart + } + , Err + { error = Error_InvalidToken Expecting_Unknown + , item = Just (Located { end = { col = 4, row = 29 }, start = { col = 1, row = 29 } } (Invalid (IdentifierWithTrailingDot { name = UpperCase "Hi", qualifiers = [] }))) + , state = State_BlockStart + } + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Invalid (IdentifierWithTrailingDot { name = UpperCase "Foo", qualifiers = [] })) + , Located { end = { col = 1, row = 3 }, start = { col = 5, row = 1 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 8, row = 3 }, start = { col = 1, row = 3 } } + (Token + (Identifier + { name = TokenUpperCase (UpperCase "Bar") + , qualifiers = + [ UpperCase "Foo" + ] + } + ) + ) + , Located { end = { col = 1, row = 5 }, start = { col = 8, row = 3 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 12, row = 5 }, start = { col = 1, row = 5 } } + (Token + (Identifier + { name = TokenLowerCase (LowerCase "baz") + , qualifiers = + [ UpperCase "Foo" + , UpperCase "Bar" + ] + } + ) + ) + , Located { end = { col = 1, row = 7 }, start = { col = 12, row = 5 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 11, row = 7 }, start = { col = 1, row = 7 } } + (Invalid + (IdentifierWithTrailingDot + { name = UpperCase "Bing" + , qualifiers = + [ UpperCase "Boor" + ] + } + ) + ) + , Located { end = { col = 1, row = 9 }, start = { col = 11, row = 7 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 5, row = 9 }, start = { col = 1, row = 9 } } (Invalid (IdentifierWithTrailingDot { name = UpperCase "Bor", qualifiers = [] })) + , Located { end = { col = 6, row = 9 }, start = { col = 5, row = 9 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 10, row = 9 }, start = { col = 6, row = 9 } } (Invalid (IdentifierWithTrailingDot { name = UpperCase "Big", qualifiers = [] })) + , Located { end = { col = 1, row = 11 }, start = { col = 10, row = 9 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 4, row = 11 }, start = { col = 1, row = 11 } } (Token (RecordAccessorFunction (LowerCase "sf"))) + , Located { end = { col = 1, row = 13 }, start = { col = 4, row = 11 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 6, row = 13 }, start = { col = 1, row = 13 } } (Token (Identifier { name = TokenLowerCase (LowerCase "sfsdf"), qualifiers = [] })) + , Located { end = { col = 7, row = 13 }, start = { col = 6, row = 13 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 13, row = 13 }, start = { col = 7, row = 13 } } (Token (RecordAccessorFunction (LowerCase "sdfsd"))) + , Located { end = { col = 1, row = 15 }, start = { col = 13, row = 13 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 7, row = 15 }, start = { col = 1, row = 15 } } (Token (Identifier { name = TokenLowerCase (LowerCase "asfasf"), qualifiers = [] })) + , Located { end = { col = 15, row = 15 }, start = { col = 7, row = 15 } } (Token (RecordAccessorLiteral (LowerCase "sdgsghj"))) + , Located { end = { col = 1, row = 17 }, start = { col = 15, row = 15 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 2, row = 17 }, start = { col = 1, row = 17 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 6, row = 17 }, start = { col = 2, row = 17 } } (Token (Identifier { name = TokenLowerCase (LowerCase "shdf"), qualifiers = [] })) + , Located { end = { col = 7, row = 17 }, start = { col = 6, row = 17 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 20, row = 17 }, start = { col = 7, row = 17 } } (Token (RecordAccessorLiteral (LowerCase "helloLiteral"))) + , Located { end = { col = 1, row = 19 }, start = { col = 20, row = 17 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 2, row = 19 }, start = { col = 1, row = 19 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 7, row = 19 }, start = { col = 2, row = 19 } } (Token (Identifier { name = TokenLowerCase (LowerCase "sjhsf"), qualifiers = [] })) + , Located { end = { col = 8, row = 19 }, start = { col = 7, row = 19 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 9, row = 19 }, start = { col = 8, row = 19 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 23, row = 19 }, start = { col = 9, row = 19 } } (Token (RecordAccessorFunction (LowerCase "helloFunction"))) + , Located { end = { col = 1, row = 21 }, start = { col = 23, row = 19 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 7, row = 21 }, start = { col = 1, row = 21 } } (Token (Identifier { name = TokenLowerCase (LowerCase "sfhsdf"), qualifiers = [] })) + , Located { end = { col = 8, row = 21 }, start = { col = 7, row = 21 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 22, row = 21 }, start = { col = 8, row = 21 } } (Token (RecordAccessorFunction (LowerCase "helloFunction"))) + , Located { end = { col = 23, row = 21 }, start = { col = 22, row = 21 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 1, row = 23 }, start = { col = 23, row = 21 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 5, row = 23 }, start = { col = 1, row = 23 } } (Token (Keyword Case)) + , Located { end = { col = 8, row = 23 }, start = { col = 5, row = 23 } } (Token (RecordAccessorFunction (LowerCase "hi"))) + , Located { end = { col = 1, row = 25 }, start = { col = 8, row = 23 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 8, row = 25 }, start = { col = 1, row = 25 } } + (Token + (Identifier + { name = TokenLowerCase (LowerCase "case") + , qualifiers = + [ UpperCase "Hi" + ] + } + ) + ) + , Located { end = { col = 1, row = 27 }, start = { col = 8, row = 25 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 5, row = 27 }, start = { col = 1, row = 27 } } (Token (Keyword Case)) + , Located { end = { col = 6, row = 27 }, start = { col = 5, row = 27 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 9, row = 27 }, start = { col = 6, row = 27 } } (Token (RecordAccessorFunction (LowerCase "hi"))) + , Located { end = { col = 1, row = 29 }, start = { col = 9, row = 27 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 4, row = 29 }, start = { col = 1, row = 29 } } (Invalid (IdentifierWithTrailingDot { name = UpperCase "Hi", qualifiers = [] })) + , Located { end = { col = 5, row = 29 }, start = { col = 4, row = 29 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 9, row = 29 }, start = { col = 5, row = 29 } } (Token (Keyword Case)) + ] + } + , { name = "type-alias-function-nested-missing-return" + , source = """type alias Function = (() -> ) + +type alias Function2 = { a: () -> } + +type alias Function3 = (() -> , ()) + +type alias Function3 = (Int, () ->, ()) +""" + , pretty = """ + ( ( Err, todo ) + , ( Err, todo ) + , ( Err, todo ) + , ( Err, todo ) + ) +""" + , contextualized = + Just + [ Err + { error = Error_MissingFunctionReturnType + , item = Just (Located { end = { col = 31, row = 1 }, start = { col = 30, row = 1 } } (Token (Sigil (Bracket Round Close)))) + , state = State_BlockTypeAlias (BlockTypeAlias_Completish (UpperCase "Function") [] (TypeExpressionNestingLeaf_Function { firstInput = TypeExpression_Unit, otherInputs = Stack [], output = Nothing, parent = Just (NestingParentType_Bracket { expressions = Stack [], parent = Nothing }) })) + } + , Err + { error = Error_MissingFunctionReturnType + , item = Just (Located { end = { col = 37, row = 3 }, start = { col = 36, row = 3 } } (Token (Sigil (Bracket Curly Close)))) + , state = State_BlockTypeAlias (BlockTypeAlias_Completish (UpperCase "Function2") [] (TypeExpressionNestingLeaf_Function { firstInput = TypeExpression_Unit, otherInputs = Stack [], output = Nothing, parent = Just (NestingParentType_PartialRecord { firstEntries = Stack [], lastEntryName = LowerCase "a", parent = Nothing }) })) + } + , Err + { error = Error_InvalidToken Expecting_Unknown + , item = Just (Located { end = { col = 32, row = 5 }, start = { col = 31, row = 5 } } (Token (Sigil Comma))) + , state = State_BlockTypeAlias (BlockTypeAlias_Completish (UpperCase "Function3") [] (TypeExpressionNestingLeaf_Function { firstInput = TypeExpression_Unit, otherInputs = Stack [], output = Nothing, parent = Just (NestingParentType_Bracket { expressions = Stack [], parent = Nothing }) })) + } + , Err + { error = Error_InvalidToken Expecting_Unknown + , item = Just (Located { end = { col = 36, row = 7 }, start = { col = 35, row = 7 } } (Token (Sigil Comma))) + , state = + State_BlockTypeAlias + (BlockTypeAlias_Completish (UpperCase "Function3") + [] + (TypeExpressionNestingLeaf_Function + { firstInput = TypeExpression_Unit + , otherInputs = Stack [] + , output = Nothing + , parent = + Just + (NestingParentType_Bracket + { expressions = + Stack + [ TypeExpression_NamedType { args = Stack [], name = UpperCase "Int", qualifiers = [] } + ] + , parent = Nothing + } + ) + } + ) + ) + } + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 20, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Function"), qualifiers = [] })) + , Located { end = { col = 21, row = 1 }, start = { col = 20, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 22, row = 1 }, start = { col = 21, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 23, row = 1 }, start = { col = 22, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 24, row = 1 }, start = { col = 23, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 25, row = 1 }, start = { col = 24, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 26, row = 1 }, start = { col = 25, row = 1 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 27, row = 1 }, start = { col = 26, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 29, row = 1 }, start = { col = 27, row = 1 } } (Token (Sigil ThinArrow)) + , Located { end = { col = 30, row = 1 }, start = { col = 29, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 31, row = 1 }, start = { col = 30, row = 1 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 1, row = 3 }, start = { col = 31, row = 1 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 5, row = 3 }, start = { col = 1, row = 3 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 3 }, start = { col = 5, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 3 }, start = { col = 6, row = 3 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 3 }, start = { col = 11, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 21, row = 3 }, start = { col = 12, row = 3 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Function2"), qualifiers = [] })) + , Located { end = { col = 22, row = 3 }, start = { col = 21, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 23, row = 3 }, start = { col = 22, row = 3 } } (Token (Sigil Assign)) + , Located { end = { col = 24, row = 3 }, start = { col = 23, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 25, row = 3 }, start = { col = 24, row = 3 } } (Token (Sigil (Bracket Curly Open))) + , Located { end = { col = 26, row = 3 }, start = { col = 25, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 27, row = 3 }, start = { col = 26, row = 3 } } (Token (Identifier { name = TokenLowerCase (LowerCase "a"), qualifiers = [] })) + , Located { end = { col = 28, row = 3 }, start = { col = 27, row = 3 } } (Token (Sigil Colon)) + , Located { end = { col = 29, row = 3 }, start = { col = 28, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 30, row = 3 }, start = { col = 29, row = 3 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 31, row = 3 }, start = { col = 30, row = 3 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 32, row = 3 }, start = { col = 31, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 34, row = 3 }, start = { col = 32, row = 3 } } (Token (Sigil ThinArrow)) + , Located { end = { col = 36, row = 3 }, start = { col = 34, row = 3 } } (Ignorable (Whitespace 2)) + , Located { end = { col = 37, row = 3 }, start = { col = 36, row = 3 } } (Token (Sigil (Bracket Curly Close))) + , Located { end = { col = 1, row = 5 }, start = { col = 37, row = 3 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 5, row = 5 }, start = { col = 1, row = 5 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 5 }, start = { col = 5, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 5 }, start = { col = 6, row = 5 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 5 }, start = { col = 11, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 21, row = 5 }, start = { col = 12, row = 5 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Function3"), qualifiers = [] })) + , Located { end = { col = 22, row = 5 }, start = { col = 21, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 23, row = 5 }, start = { col = 22, row = 5 } } (Token (Sigil Assign)) + , Located { end = { col = 24, row = 5 }, start = { col = 23, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 25, row = 5 }, start = { col = 24, row = 5 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 26, row = 5 }, start = { col = 25, row = 5 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 27, row = 5 }, start = { col = 26, row = 5 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 28, row = 5 }, start = { col = 27, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 30, row = 5 }, start = { col = 28, row = 5 } } (Token (Sigil ThinArrow)) + , Located { end = { col = 31, row = 5 }, start = { col = 30, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 32, row = 5 }, start = { col = 31, row = 5 } } (Token (Sigil Comma)) + , Located { end = { col = 33, row = 5 }, start = { col = 32, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 34, row = 5 }, start = { col = 33, row = 5 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 35, row = 5 }, start = { col = 34, row = 5 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 36, row = 5 }, start = { col = 35, row = 5 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 1, row = 7 }, start = { col = 36, row = 5 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 5, row = 7 }, start = { col = 1, row = 7 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 7 }, start = { col = 5, row = 7 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 7 }, start = { col = 6, row = 7 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 7 }, start = { col = 11, row = 7 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 21, row = 7 }, start = { col = 12, row = 7 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Function3"), qualifiers = [] })) + , Located { end = { col = 22, row = 7 }, start = { col = 21, row = 7 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 23, row = 7 }, start = { col = 22, row = 7 } } (Token (Sigil Assign)) + , Located { end = { col = 24, row = 7 }, start = { col = 23, row = 7 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 25, row = 7 }, start = { col = 24, row = 7 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 28, row = 7 }, start = { col = 25, row = 7 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 29, row = 7 }, start = { col = 28, row = 7 } } (Token (Sigil Comma)) + , Located { end = { col = 30, row = 7 }, start = { col = 29, row = 7 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 31, row = 7 }, start = { col = 30, row = 7 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 32, row = 7 }, start = { col = 31, row = 7 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 33, row = 7 }, start = { col = 32, row = 7 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 35, row = 7 }, start = { col = 33, row = 7 } } (Token (Sigil ThinArrow)) + , Located { end = { col = 36, row = 7 }, start = { col = 35, row = 7 } } (Token (Sigil Comma)) + , Located { end = { col = 37, row = 7 }, start = { col = 36, row = 7 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 38, row = 7 }, start = { col = 37, row = 7 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 39, row = 7 }, start = { col = 38, row = 7 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 40, row = 7 }, start = { col = 39, row = 7 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 1, row = 8 }, start = { col = 40, row = 7 } } (Newlines [] 0) + ] + } + , { name = "type-alias-invalid-multiple-brackets" + , source = """type alias Hi = (Int) () +""" + , pretty = """ + ( ( Err, todo ) ) +""" + , contextualized = + Just + [ Err + { error = Error_TypeDoesNotTakeArgs (TypeExpression_Bracketed (TypeExpression_NamedType { args = Stack [], name = UpperCase "Int", qualifiers = [] })) (TypeExpressionNestingLeaf_Bracket { firstExpressions = Stack [], parent = Nothing, trailingExpression = Nothing }) + , item = Just (Located { end = { col = 24, row = 1 }, start = { col = 23, row = 1 } } (Token (Sigil (Bracket Round Open)))) + , state = State_BlockTypeAlias (BlockTypeAlias_Completish (UpperCase "Hi") [] (TypeExpressionNestingLeaf_Expr () (TypeExpression_Bracketed (TypeExpression_NamedType { args = Stack [], name = UpperCase "Int", qualifiers = [] })))) + } + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Hi"), qualifiers = [] })) + , Located { end = { col = 15, row = 1 }, start = { col = 14, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 1 }, start = { col = 15, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 17, row = 1 }, start = { col = 16, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 1 }, start = { col = 17, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 21, row = 1 }, start = { col = 18, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 22, row = 1 }, start = { col = 21, row = 1 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 23, row = 1 }, start = { col = 22, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 24, row = 1 }, start = { col = 23, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 25, row = 1 }, start = { col = 24, row = 1 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 1, row = 2 }, start = { col = 25, row = 1 } } (Newlines [] 0) + ] + } + , { name = "type-alias-invalid-multiple-brackets-2" + , source = """type alias Hi = () () +""" + , pretty = """ + ( ( Err, todo ) ) +""" + , contextualized = + Just + [ Err + { error = Error_TypeDoesNotTakeArgs TypeExpression_Unit (TypeExpressionNestingLeaf_Bracket { firstExpressions = Stack [], parent = Nothing, trailingExpression = Nothing }) + , item = Just (Located { end = { col = 21, row = 1 }, start = { col = 20, row = 1 } } (Token (Sigil (Bracket Round Open)))) + , state = State_BlockTypeAlias (BlockTypeAlias_Completish (UpperCase "Hi") [] (TypeExpressionNestingLeaf_Expr () TypeExpression_Unit)) + } + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Hi"), qualifiers = [] })) + , Located { end = { col = 15, row = 1 }, start = { col = 14, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 1 }, start = { col = 15, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 17, row = 1 }, start = { col = 16, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 1 }, start = { col = 17, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 19, row = 1 }, start = { col = 18, row = 1 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 20, row = 1 }, start = { col = 19, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 21, row = 1 }, start = { col = 20, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 22, row = 1 }, start = { col = 21, row = 1 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 1, row = 2 }, start = { col = 22, row = 1 } } (Newlines [] 0) + ] + } + , { name = "type-alias-invalid-multiple-brackets-3" + , source = """type alias Hi = () (Int) +""" + , pretty = """ + ( ( Err, todo ) ) +""" + , contextualized = + Just + [ Err + { error = Error_TypeDoesNotTakeArgs TypeExpression_Unit (TypeExpressionNestingLeaf_Bracket { firstExpressions = Stack [], parent = Nothing, trailingExpression = Nothing }) + , item = Just (Located { end = { col = 21, row = 1 }, start = { col = 20, row = 1 } } (Token (Sigil (Bracket Round Open)))) + , state = State_BlockTypeAlias (BlockTypeAlias_Completish (UpperCase "Hi") [] (TypeExpressionNestingLeaf_Expr () TypeExpression_Unit)) + } + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Hi"), qualifiers = [] })) + , Located { end = { col = 15, row = 1 }, start = { col = 14, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 1 }, start = { col = 15, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 17, row = 1 }, start = { col = 16, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 1 }, start = { col = 17, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 19, row = 1 }, start = { col = 18, row = 1 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 20, row = 1 }, start = { col = 19, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 21, row = 1 }, start = { col = 20, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 24, row = 1 }, start = { col = 21, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 25, row = 1 }, start = { col = 24, row = 1 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 1, row = 2 }, start = { col = 25, row = 1 } } (Newlines [] 0) + ] + } + , { name = "type-alias-lower-case-types" + , source = """type alias A = B.C.d + +type alias B = List A.d + +type alias C = list A + +type alias D a = a -> B.c +type alias E a = B.c -> a""" + , pretty = """ + ( ( Err, todo ) + , ( Err, todo ) + , ( Err, todo ) + , ( Err, todo ) + , ( Err, todo ) + ) +""" + , contextualized = + Just + [ Err + { error = + Error_LowerCasedTypename + { name = LowerCase "d" + , qualifiers = + [ UpperCase "B" + , UpperCase "C" + ] + } + , item = + Just + (Located { end = { col = 21, row = 1 }, start = { col = 16, row = 1 } } + (Token + (Identifier + { name = TokenLowerCase (LowerCase "d") + , qualifiers = + [ UpperCase "B" + , UpperCase "C" + ] + } + ) + ) + ) + , state = State_BlockTypeAlias (BlockTypeAlias_NamedAssigns (UpperCase "A") []) + } + , Err + { error = + Error_LowerCasedTypename + { name = LowerCase "d" + , qualifiers = + [ UpperCase "A" + ] + } + , item = + Just + (Located { end = { col = 24, row = 3 }, start = { col = 21, row = 3 } } + (Token + (Identifier + { name = TokenLowerCase (LowerCase "d") + , qualifiers = + [ UpperCase "A" + ] + } + ) + ) + ) + , state = State_BlockTypeAlias (BlockTypeAlias_Completish (UpperCase "B") [] (TypeExpressionNestingLeaf_TypeWithArgs { args = Stack [], name = UpperCase "List", parent = Nothing, phantom = (), qualifiers = [] })) + } + , Err + { error = Error_TypeDoesNotTakeArgs (TypeExpression_GenericType (LowerCase "list")) (TypeExpressionNestingLeaf_TypeWithArgs { args = Stack [], name = UpperCase "A", parent = Nothing, phantom = (), qualifiers = [] }) + , item = Just (Located { end = { col = 22, row = 5 }, start = { col = 21, row = 5 } } (Token (Identifier { name = TokenUpperCase (UpperCase "A"), qualifiers = [] }))) + , state = State_BlockTypeAlias (BlockTypeAlias_Completish (UpperCase "C") [] (TypeExpressionNestingLeaf_Expr () (TypeExpression_GenericType (LowerCase "list")))) + } + , Err + { error = + Error_LowerCasedTypename + { name = LowerCase "c" + , qualifiers = + [ UpperCase "B" + ] + } + , item = + Just + (Located { end = { col = 26, row = 7 }, start = { col = 23, row = 7 } } + (Token + (Identifier + { name = TokenLowerCase (LowerCase "c") + , qualifiers = + [ UpperCase "B" + ] + } + ) + ) + ) + , state = + State_BlockTypeAlias + (BlockTypeAlias_Completish (UpperCase "D") + [ LowerCase "a" + ] + (TypeExpressionNestingLeaf_Function { firstInput = TypeExpression_GenericType (LowerCase "a"), otherInputs = Stack [], output = Nothing, parent = Nothing }) + ) + } + , Err + { error = + Error_LowerCasedTypename + { name = LowerCase "c" + , qualifiers = + [ UpperCase "B" + ] + } + , item = + Just + (Located { end = { col = 21, row = 8 }, start = { col = 18, row = 8 } } + (Token + (Identifier + { name = TokenLowerCase (LowerCase "c") + , qualifiers = + [ UpperCase "B" + ] + } + ) + ) + ) + , state = + State_BlockTypeAlias + (BlockTypeAlias_NamedAssigns (UpperCase "E") + [ LowerCase "a" + ] + ) + } + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 13, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "A"), qualifiers = [] })) + , Located { end = { col = 14, row = 1 }, start = { col = 13, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 15, row = 1 }, start = { col = 14, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 16, row = 1 }, start = { col = 15, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 21, row = 1 }, start = { col = 16, row = 1 } } + (Token + (Identifier + { name = TokenLowerCase (LowerCase "d") + , qualifiers = + [ UpperCase "B" + , UpperCase "C" + ] + } + ) + ) + , Located { end = { col = 1, row = 3 }, start = { col = 21, row = 1 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 5, row = 3 }, start = { col = 1, row = 3 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 3 }, start = { col = 5, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 3 }, start = { col = 6, row = 3 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 3 }, start = { col = 11, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 13, row = 3 }, start = { col = 12, row = 3 } } (Token (Identifier { name = TokenUpperCase (UpperCase "B"), qualifiers = [] })) + , Located { end = { col = 14, row = 3 }, start = { col = 13, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 15, row = 3 }, start = { col = 14, row = 3 } } (Token (Sigil Assign)) + , Located { end = { col = 16, row = 3 }, start = { col = 15, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 20, row = 3 }, start = { col = 16, row = 3 } } (Token (Identifier { name = TokenUpperCase (UpperCase "List"), qualifiers = [] })) + , Located { end = { col = 21, row = 3 }, start = { col = 20, row = 3 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 24, row = 3 }, start = { col = 21, row = 3 } } + (Token + (Identifier + { name = TokenLowerCase (LowerCase "d") + , qualifiers = + [ UpperCase "A" + ] + } + ) + ) + , Located { end = { col = 1, row = 5 }, start = { col = 24, row = 3 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 5, row = 5 }, start = { col = 1, row = 5 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 5 }, start = { col = 5, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 5 }, start = { col = 6, row = 5 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 5 }, start = { col = 11, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 13, row = 5 }, start = { col = 12, row = 5 } } (Token (Identifier { name = TokenUpperCase (UpperCase "C"), qualifiers = [] })) + , Located { end = { col = 14, row = 5 }, start = { col = 13, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 15, row = 5 }, start = { col = 14, row = 5 } } (Token (Sigil Assign)) + , Located { end = { col = 16, row = 5 }, start = { col = 15, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 20, row = 5 }, start = { col = 16, row = 5 } } (Token (Identifier { name = TokenLowerCase (LowerCase "list"), qualifiers = [] })) + , Located { end = { col = 21, row = 5 }, start = { col = 20, row = 5 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 22, row = 5 }, start = { col = 21, row = 5 } } (Token (Identifier { name = TokenUpperCase (UpperCase "A"), qualifiers = [] })) + , Located { end = { col = 1, row = 7 }, start = { col = 22, row = 5 } } + (Newlines + [ 0 + ] + 0 + ) + , Located { end = { col = 5, row = 7 }, start = { col = 1, row = 7 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 7 }, start = { col = 5, row = 7 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 7 }, start = { col = 6, row = 7 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 7 }, start = { col = 11, row = 7 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 13, row = 7 }, start = { col = 12, row = 7 } } (Token (Identifier { name = TokenUpperCase (UpperCase "D"), qualifiers = [] })) + , Located { end = { col = 14, row = 7 }, start = { col = 13, row = 7 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 15, row = 7 }, start = { col = 14, row = 7 } } (Token (Identifier { name = TokenLowerCase (LowerCase "a"), qualifiers = [] })) + , Located { end = { col = 16, row = 7 }, start = { col = 15, row = 7 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 17, row = 7 }, start = { col = 16, row = 7 } } (Token (Sigil Assign)) + , Located { end = { col = 18, row = 7 }, start = { col = 17, row = 7 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 19, row = 7 }, start = { col = 18, row = 7 } } (Token (Identifier { name = TokenLowerCase (LowerCase "a"), qualifiers = [] })) + , Located { end = { col = 20, row = 7 }, start = { col = 19, row = 7 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 22, row = 7 }, start = { col = 20, row = 7 } } (Token (Sigil ThinArrow)) + , Located { end = { col = 23, row = 7 }, start = { col = 22, row = 7 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 26, row = 7 }, start = { col = 23, row = 7 } } + (Token + (Identifier + { name = TokenLowerCase (LowerCase "c") + , qualifiers = + [ UpperCase "B" + ] + } + ) + ) + , Located { end = { col = 1, row = 8 }, start = { col = 26, row = 7 } } (Newlines [] 0) + , Located { end = { col = 5, row = 8 }, start = { col = 1, row = 8 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 8 }, start = { col = 5, row = 8 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 8 }, start = { col = 6, row = 8 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 8 }, start = { col = 11, row = 8 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 13, row = 8 }, start = { col = 12, row = 8 } } (Token (Identifier { name = TokenUpperCase (UpperCase "E"), qualifiers = [] })) + , Located { end = { col = 14, row = 8 }, start = { col = 13, row = 8 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 15, row = 8 }, start = { col = 14, row = 8 } } (Token (Identifier { name = TokenLowerCase (LowerCase "a"), qualifiers = [] })) + , Located { end = { col = 16, row = 8 }, start = { col = 15, row = 8 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 17, row = 8 }, start = { col = 16, row = 8 } } (Token (Sigil Assign)) + , Located { end = { col = 18, row = 8 }, start = { col = 17, row = 8 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 21, row = 8 }, start = { col = 18, row = 8 } } + (Token + (Identifier + { name = TokenLowerCase (LowerCase "c") + , qualifiers = + [ UpperCase "B" + ] + } + ) + ) + , Located { end = { col = 22, row = 8 }, start = { col = 21, row = 8 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 24, row = 8 }, start = { col = 22, row = 8 } } (Token (Sigil ThinArrow)) + , Located { end = { col = 25, row = 8 }, start = { col = 24, row = 8 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 26, row = 8 }, start = { col = 25, row = 8 } } (Token (Identifier { name = TokenLowerCase (LowerCase "a"), qualifiers = [] })) + ] + } + , { name = "type-alias-multiline-missing-indentation" + , source = """type alias Model = +List Int +""" + , pretty = """ + ( ( Err, todo ) + , ( Err, todo ) + ) +""" + , contextualized = + Just + [ Err + { error = Error_PartwayThroughBlock + , item = Just (Located { end = { col = 1, row = 2 }, start = { col = 19, row = 1 } } (Newlines [] 0)) + , state = State_BlockTypeAlias (BlockTypeAlias_NamedAssigns (UpperCase "Model") []) + } + , Err + { error = Error_BlockStartsWithUpperCase (UpperCase "List") + , item = Just (Located { end = { col = 5, row = 2 }, start = { col = 1, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "List"), qualifiers = [] }))) + , state = State_BlockStart + } + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 17, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Model"), qualifiers = [] })) + , Located { end = { col = 18, row = 1 }, start = { col = 17, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 19, row = 1 }, start = { col = 18, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 1, row = 2 }, start = { col = 19, row = 1 } } (Newlines [] 0) + , Located { end = { col = 5, row = 2 }, start = { col = 1, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "List"), qualifiers = [] })) + , Located { end = { col = 6, row = 2 }, start = { col = 5, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 9, row = 2 }, start = { col = 6, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 1, row = 3 }, start = { col = 9, row = 2 } } (Newlines [] 0) + ] + } + , { name = "type-alias-partial" + , source = """type alias +""" + , pretty = """ + ( ( Err, todo ) ) +""" + , contextualized = + Just + [ Err + { error = Error_PartwayThroughBlock + , item = Just (Located { end = { col = 1, row = 2 }, start = { col = 11, row = 1 } } (Newlines [] 0)) + , state = State_BlockTypeAlias BlockTypeAlias_Keywords + } + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 1, row = 2 }, start = { col = 11, row = 1 } } (Newlines [] 0) + ] + } + , { name = "type-alias-partial-2" + , source = """type alias Hi +""" + , pretty = """ + ( ( Err, todo ) ) +""" + , contextualized = + Just + [ Err + { error = Error_PartwayThroughBlock + , item = Just (Located { end = { col = 1, row = 2 }, start = { col = 14, row = 1 } } (Newlines [] 0)) + , state = State_BlockTypeAlias (BlockTypeAlias_Named (UpperCase "Hi") (Stack [])) + } + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Hi"), qualifiers = [] })) + , Located { end = { col = 1, row = 2 }, start = { col = 14, row = 1 } } (Newlines [] 0) + ] + } + , { name = "type-alias-partial-3" + , source = """type alias Hi = +""" + , pretty = """ + ( ( Err, todo ) ) +""" + , contextualized = + Just + [ Err + { error = Error_PartwayThroughBlock + , item = Just (Located { end = { col = 1, row = 2 }, start = { col = 16, row = 1 } } (Newlines [] 0)) + , state = State_BlockTypeAlias (BlockTypeAlias_NamedAssigns (UpperCase "Hi") []) + } + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Hi"), qualifiers = [] })) + , Located { end = { col = 15, row = 1 }, start = { col = 14, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 1 }, start = { col = 15, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 1, row = 2 }, start = { col = 16, row = 1 } } (Newlines [] 0) + ] + } + , { name = "type-alias-partial-with-bracket" + , source = """type alias Hi = ( +""" + , pretty = """ + ( ( Err, todo ) ) +""" + , contextualized = + Just + [ Err + { error = Error_PartwayThroughBlock + , item = Just (Located { end = { col = 1, row = 2 }, start = { col = 18, row = 1 } } (Newlines [] 0)) + , state = State_BlockTypeAlias (BlockTypeAlias_Completish (UpperCase "Hi") [] (TypeExpressionNestingLeaf_Bracket { firstExpressions = Stack [], parent = Nothing, trailingExpression = Nothing })) + } + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Hi"), qualifiers = [] })) + , Located { end = { col = 15, row = 1 }, start = { col = 14, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 1 }, start = { col = 15, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 17, row = 1 }, start = { col = 16, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 1 }, start = { col = 17, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 1, row = 2 }, start = { col = 18, row = 1 } } (Newlines [] 0) + ] + } + , { name = "type-alias-partial-with-bracket-2" + , source = """type alias Hi = ( + Int +""" + , pretty = """ + ( ( Err, todo ) ) +""" + , contextualized = + Just + [ Err + { error = Error_PartwayThroughBlock + , item = Just (Located { end = { col = 1, row = 3 }, start = { col = 12, row = 2 } } (Newlines [] 0)) + , state = State_BlockTypeAlias (BlockTypeAlias_Completish (UpperCase "Hi") [] (TypeExpressionNestingLeaf_TypeWithArgs { args = Stack [], name = UpperCase "Int", parent = Just (NestingParentType_Bracket { expressions = Stack [], parent = Nothing }), phantom = (), qualifiers = [] })) + } + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Hi"), qualifiers = [] })) + , Located { end = { col = 15, row = 1 }, start = { col = 14, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 1 }, start = { col = 15, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 17, row = 1 }, start = { col = 16, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 1 }, start = { col = 17, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 9, row = 2 }, start = { col = 18, row = 1 } } (Newlines [] 8) + , Located { end = { col = 12, row = 2 }, start = { col = 9, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 1, row = 3 }, start = { col = 12, row = 2 } } (Newlines [] 0) + ] + } + , { name = "type-alias-record-half-empty" + , source = """type alias Ty = { +""" + , pretty = """ + ( ( Err, todo ) ) +""" + , contextualized = + Just + [ Err + { error = Error_PartwayThroughBlock + , item = Just (Located { end = { col = 1, row = 2 }, start = { col = 18, row = 1 } } (Newlines [] 0)) + , state = State_BlockTypeAlias (BlockTypeAlias_Completish (UpperCase "Ty") [] (TypeExpressionNestingLeaf_PartialRecord { firstEntries = Stack [], lastEntry = LastEntryOfRecord_Empty, parent = Nothing })) + } + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Ty"), qualifiers = [] })) + , Located { end = { col = 15, row = 1 }, start = { col = 14, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 1 }, start = { col = 15, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 17, row = 1 }, start = { col = 16, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 1 }, start = { col = 17, row = 1 } } (Token (Sigil (Bracket Curly Open))) + , Located { end = { col = 1, row = 2 }, start = { col = 18, row = 1 } } (Newlines [] 0) + ] + } + , { name = "type-alias-record-missing-colon" + , source = """type alias Ty = { hi j7 } +""" + , pretty = """ + ( ( Err, todo ) ) +""" + , contextualized = + Just + [ Err + { error = Error_ExpectedColonWhilstParsingRecord + , item = Just (Located { end = { col = 24, row = 1 }, start = { col = 22, row = 1 } } (Token (Identifier { name = TokenLowerCase (LowerCase "j7"), qualifiers = [] }))) + , state = State_BlockTypeAlias (BlockTypeAlias_Completish (UpperCase "Ty") [] (TypeExpressionNestingLeaf_PartialRecord { firstEntries = Stack [], lastEntry = LastEntryOfRecord_Key (LowerCase "hi"), parent = Nothing })) + } + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Ty"), qualifiers = [] })) + , Located { end = { col = 15, row = 1 }, start = { col = 14, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 1 }, start = { col = 15, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 17, row = 1 }, start = { col = 16, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 1 }, start = { col = 17, row = 1 } } (Token (Sigil (Bracket Curly Open))) + , Located { end = { col = 19, row = 1 }, start = { col = 18, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 21, row = 1 }, start = { col = 19, row = 1 } } (Token (Identifier { name = TokenLowerCase (LowerCase "hi"), qualifiers = [] })) + , Located { end = { col = 22, row = 1 }, start = { col = 21, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 24, row = 1 }, start = { col = 22, row = 1 } } (Token (Identifier { name = TokenLowerCase (LowerCase "j7"), qualifiers = [] })) + , Located { end = { col = 25, row = 1 }, start = { col = 24, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 26, row = 1 }, start = { col = 25, row = 1 } } (Token (Sigil (Bracket Curly Close))) + , Located { end = { col = 1, row = 2 }, start = { col = 26, row = 1 } } (Newlines [] 0) + ] + } + , { name = "type-alias-with-quadruple" + , source = """type alias Hi = (Int, A, B, C, D) +type alias Hi = (A Int, C D E F, H I (J K), L M () O P) +""" + , pretty = """ + ( ( Err, todo ) + , ( Err, todo ) + ) +""" + , contextualized = + Just + [ Err + { error = + Error_TooManyTupleArgs + (UserDefinedType + { args = [] + , name = "Int" + , qualifiedness = PossiblyQualified Nothing + } + ) + (UserDefinedType + { args = [] + , name = "A" + , qualifiedness = PossiblyQualified Nothing + } + ) + (UserDefinedType + { args = [] + , name = "B" + , qualifiedness = PossiblyQualified Nothing + } + ) + (UserDefinedType + { args = [] + , name = "C" + , qualifiedness = PossiblyQualified Nothing + } + ) + [ UserDefinedType + { args = [] + , name = "D" + , qualifiedness = PossiblyQualified Nothing + } + ] + , item = Just (Located { end = { col = 1, row = 2 }, start = { col = 34, row = 1 } } (Newlines [] 0)) + , state = + State_BlockTypeAlias + (BlockTypeAlias_Completish (UpperCase "Hi") + [] + (TypeExpressionNestingLeaf_Expr () + (TypeExpression_Tuple (TypeExpression_NamedType { args = Stack [], name = UpperCase "Int", qualifiers = [] }) + (TypeExpression_NamedType { args = Stack [], name = UpperCase "A", qualifiers = [] }) + [ TypeExpression_NamedType { args = Stack [], name = UpperCase "B", qualifiers = [] } + , TypeExpression_NamedType { args = Stack [], name = UpperCase "C", qualifiers = [] } + , TypeExpression_NamedType { args = Stack [], name = UpperCase "D", qualifiers = [] } + ] + ) + ) + ) + } + , Err + { error = + Error_TooManyTupleArgs + (UserDefinedType + { args = + [ UserDefinedType + { args = [] + , name = "Int" + , qualifiedness = PossiblyQualified Nothing + } + ] + , name = "A" + , qualifiedness = PossiblyQualified Nothing + } + ) + (UserDefinedType + { args = + [ UserDefinedType + { args = [] + , name = "D" + , qualifiedness = PossiblyQualified Nothing + } + , UserDefinedType + { args = [] + , name = "E" + , qualifiedness = PossiblyQualified Nothing + } + , UserDefinedType + { args = [] + , name = "F" + , qualifiedness = PossiblyQualified Nothing + } + ] + , name = "C" + , qualifiedness = PossiblyQualified Nothing + } + ) + (UserDefinedType + { args = + [ UserDefinedType + { args = [] + , name = "I" + , qualifiedness = PossiblyQualified Nothing + } + , UserDefinedType + { args = + [ UserDefinedType + { args = [] + , name = "K" + , qualifiedness = PossiblyQualified Nothing + } + ] + , name = "J" + , qualifiedness = PossiblyQualified Nothing + } + ] + , name = "H" + , qualifiedness = PossiblyQualified Nothing + } + ) + (UserDefinedType + { args = + [ UserDefinedType + { args = [] + , name = "M" + , qualifiedness = PossiblyQualified Nothing + } + , Unit + , UserDefinedType + { args = [] + , name = "O" + , qualifiedness = PossiblyQualified Nothing + } + , UserDefinedType + { args = [] + , name = "P" + , qualifiedness = PossiblyQualified Nothing + } + ] + , name = "L" + , qualifiedness = PossiblyQualified Nothing + } + ) + [] + , item = Just (Located { end = { col = 1, row = 3 }, start = { col = 56, row = 2 } } (Newlines [] 0)) + , state = + State_BlockTypeAlias + (BlockTypeAlias_Completish (UpperCase "Hi") + [] + (TypeExpressionNestingLeaf_Expr () + (TypeExpression_Tuple + (TypeExpression_NamedType + { args = + Stack + [ TypeExpression_NamedType { args = Stack [], name = UpperCase "Int", qualifiers = [] } + ] + , name = UpperCase "A" + , qualifiers = [] + } + ) + (TypeExpression_NamedType + { args = + Stack + [ TypeExpression_NamedType { args = Stack [], name = UpperCase "F", qualifiers = [] } + , TypeExpression_NamedType { args = Stack [], name = UpperCase "E", qualifiers = [] } + , TypeExpression_NamedType { args = Stack [], name = UpperCase "D", qualifiers = [] } + ] + , name = UpperCase "C" + , qualifiers = [] + } + ) + [ TypeExpression_NamedType + { args = + Stack + [ TypeExpression_Bracketed + (TypeExpression_NamedType + { args = + Stack + [ TypeExpression_NamedType { args = Stack [], name = UpperCase "K", qualifiers = [] } + ] + , name = UpperCase "J" + , qualifiers = [] + } + ) + , TypeExpression_NamedType { args = Stack [], name = UpperCase "I", qualifiers = [] } + ] + , name = UpperCase "H" + , qualifiers = [] + } + , TypeExpression_NamedType + { args = + Stack + [ TypeExpression_NamedType { args = Stack [], name = UpperCase "P", qualifiers = [] } + , TypeExpression_NamedType { args = Stack [], name = UpperCase "O", qualifiers = [] } + , TypeExpression_Unit + , TypeExpression_NamedType { args = Stack [], name = UpperCase "M", qualifiers = [] } + ] + , name = UpperCase "L" + , qualifiers = [] + } + ] + ) + ) + ) + } + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Hi"), qualifiers = [] })) + , Located { end = { col = 15, row = 1 }, start = { col = 14, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 1 }, start = { col = 15, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 17, row = 1 }, start = { col = 16, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 1 }, start = { col = 17, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 21, row = 1 }, start = { col = 18, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 22, row = 1 }, start = { col = 21, row = 1 } } (Token (Sigil Comma)) + , Located { end = { col = 23, row = 1 }, start = { col = 22, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 24, row = 1 }, start = { col = 23, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "A"), qualifiers = [] })) + , Located { end = { col = 25, row = 1 }, start = { col = 24, row = 1 } } (Token (Sigil Comma)) + , Located { end = { col = 26, row = 1 }, start = { col = 25, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 27, row = 1 }, start = { col = 26, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "B"), qualifiers = [] })) + , Located { end = { col = 28, row = 1 }, start = { col = 27, row = 1 } } (Token (Sigil Comma)) + , Located { end = { col = 29, row = 1 }, start = { col = 28, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 30, row = 1 }, start = { col = 29, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "C"), qualifiers = [] })) + , Located { end = { col = 31, row = 1 }, start = { col = 30, row = 1 } } (Token (Sigil Comma)) + , Located { end = { col = 32, row = 1 }, start = { col = 31, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 33, row = 1 }, start = { col = 32, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "D"), qualifiers = [] })) + , Located { end = { col = 34, row = 1 }, start = { col = 33, row = 1 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 1, row = 2 }, start = { col = 34, row = 1 } } (Newlines [] 0) + , Located { end = { col = 5, row = 2 }, start = { col = 1, row = 2 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 2 }, start = { col = 5, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 2 }, start = { col = 6, row = 2 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 2 }, start = { col = 11, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 2 }, start = { col = 12, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Hi"), qualifiers = [] })) + , Located { end = { col = 15, row = 2 }, start = { col = 14, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 2 }, start = { col = 15, row = 2 } } (Token (Sigil Assign)) + , Located { end = { col = 17, row = 2 }, start = { col = 16, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 2 }, start = { col = 17, row = 2 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 19, row = 2 }, start = { col = 18, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "A"), qualifiers = [] })) + , Located { end = { col = 20, row = 2 }, start = { col = 19, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 23, row = 2 }, start = { col = 20, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 24, row = 2 }, start = { col = 23, row = 2 } } (Token (Sigil Comma)) + , Located { end = { col = 25, row = 2 }, start = { col = 24, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 26, row = 2 }, start = { col = 25, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "C"), qualifiers = [] })) + , Located { end = { col = 27, row = 2 }, start = { col = 26, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 28, row = 2 }, start = { col = 27, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "D"), qualifiers = [] })) + , Located { end = { col = 29, row = 2 }, start = { col = 28, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 30, row = 2 }, start = { col = 29, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "E"), qualifiers = [] })) + , Located { end = { col = 31, row = 2 }, start = { col = 30, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 32, row = 2 }, start = { col = 31, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "F"), qualifiers = [] })) + , Located { end = { col = 33, row = 2 }, start = { col = 32, row = 2 } } (Token (Sigil Comma)) + , Located { end = { col = 34, row = 2 }, start = { col = 33, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 35, row = 2 }, start = { col = 34, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "H"), qualifiers = [] })) + , Located { end = { col = 36, row = 2 }, start = { col = 35, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 37, row = 2 }, start = { col = 36, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "I"), qualifiers = [] })) + , Located { end = { col = 38, row = 2 }, start = { col = 37, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 39, row = 2 }, start = { col = 38, row = 2 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 40, row = 2 }, start = { col = 39, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "J"), qualifiers = [] })) + , Located { end = { col = 41, row = 2 }, start = { col = 40, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 42, row = 2 }, start = { col = 41, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "K"), qualifiers = [] })) + , Located { end = { col = 43, row = 2 }, start = { col = 42, row = 2 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 44, row = 2 }, start = { col = 43, row = 2 } } (Token (Sigil Comma)) + , Located { end = { col = 45, row = 2 }, start = { col = 44, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 46, row = 2 }, start = { col = 45, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "L"), qualifiers = [] })) + , Located { end = { col = 47, row = 2 }, start = { col = 46, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 48, row = 2 }, start = { col = 47, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "M"), qualifiers = [] })) + , Located { end = { col = 49, row = 2 }, start = { col = 48, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 50, row = 2 }, start = { col = 49, row = 2 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 51, row = 2 }, start = { col = 50, row = 2 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 52, row = 2 }, start = { col = 51, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 53, row = 2 }, start = { col = 52, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "O"), qualifiers = [] })) + , Located { end = { col = 54, row = 2 }, start = { col = 53, row = 2 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 55, row = 2 }, start = { col = 54, row = 2 } } (Token (Identifier { name = TokenUpperCase (UpperCase "P"), qualifiers = [] })) + , Located { end = { col = 56, row = 2 }, start = { col = 55, row = 2 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 1, row = 3 }, start = { col = 56, row = 2 } } (Newlines [] 0) + ] + } + , { name = "type-alias-with-tuple-double-comma" + , source = """type alias Hi = (Int, , A) +""" + , pretty = """ + ( ( Err, todo ) ) +""" + , contextualized = + Just + [ Err + { error = Error_InvalidToken Expecting_Unknown + , item = Just (Located { end = { col = 24, row = 1 }, start = { col = 23, row = 1 } } (Token (Sigil Comma))) + , state = + State_BlockTypeAlias + (BlockTypeAlias_Completish (UpperCase "Hi") + [] + (TypeExpressionNestingLeaf_Bracket + { firstExpressions = + Stack + [ TypeExpression_NamedType { args = Stack [], name = UpperCase "Int", qualifiers = [] } + ] + , parent = Nothing + , trailingExpression = Nothing + } + ) + ) + } + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Hi"), qualifiers = [] })) + , Located { end = { col = 15, row = 1 }, start = { col = 14, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 1 }, start = { col = 15, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 17, row = 1 }, start = { col = 16, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 1 }, start = { col = 17, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 21, row = 1 }, start = { col = 18, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 22, row = 1 }, start = { col = 21, row = 1 } } (Token (Sigil Comma)) + , Located { end = { col = 23, row = 1 }, start = { col = 22, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 24, row = 1 }, start = { col = 23, row = 1 } } (Token (Sigil Comma)) + , Located { end = { col = 25, row = 1 }, start = { col = 24, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 26, row = 1 }, start = { col = 25, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "A"), qualifiers = [] })) + , Located { end = { col = 27, row = 1 }, start = { col = 26, row = 1 } } (Token (Sigil (Bracket Round Close))) + , Located { end = { col = 1, row = 2 }, start = { col = 27, row = 1 } } (Newlines [] 0) + ] + } + , { name = "type-alias-with-tuple-not-closed" + , source = """type alias Hi = (Int, + + + +""" + , pretty = """ + ( ( Err, todo ) ) +""" + , contextualized = + Just + [ Err + { error = Error_PartwayThroughBlock + , item = + Just + (Located { end = { col = 1, row = 5 }, start = { col = 22, row = 1 } } + (Newlines + [ 0 + , 0 + , 0 + ] + 0 + ) + ) + , state = + State_BlockTypeAlias + (BlockTypeAlias_Completish (UpperCase "Hi") + [] + (TypeExpressionNestingLeaf_Bracket + { firstExpressions = + Stack + [ TypeExpression_NamedType { args = Stack [], name = UpperCase "Int", qualifiers = [] } + ] + , parent = Nothing + , trailingExpression = Nothing + } + ) + ) + } + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 6, row = 1 }, start = { col = 5, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 11, row = 1 }, start = { col = 6, row = 1 } } (Token (Keyword Alias)) + , Located { end = { col = 12, row = 1 }, start = { col = 11, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 14, row = 1 }, start = { col = 12, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Hi"), qualifiers = [] })) + , Located { end = { col = 15, row = 1 }, start = { col = 14, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 16, row = 1 }, start = { col = 15, row = 1 } } (Token (Sigil Assign)) + , Located { end = { col = 17, row = 1 }, start = { col = 16, row = 1 } } (Ignorable (Whitespace 1)) + , Located { end = { col = 18, row = 1 }, start = { col = 17, row = 1 } } (Token (Sigil (Bracket Round Open))) + , Located { end = { col = 21, row = 1 }, start = { col = 18, row = 1 } } (Token (Identifier { name = TokenUpperCase (UpperCase "Int"), qualifiers = [] })) + , Located { end = { col = 22, row = 1 }, start = { col = 21, row = 1 } } (Token (Sigil Comma)) + , Located { end = { col = 1, row = 5 }, start = { col = 22, row = 1 } } + (Newlines + [ 0 + , 0 + , 0 + ] + 0 + ) + ] + } + , { name = "type-partial" + , source = """type +""" + , pretty = """ + ( ( Err, todo ) ) +""" + , contextualized = + Just + [ Err + { error = Error_PartwayThroughBlock + , item = Just (Located { end = { col = 1, row = 2 }, start = { col = 5, row = 1 } } (Newlines [] 0)) + , state = State_BlockFirstItem BlockFirstItem_Type + } + ] + , lexed = + Ok + [ Located { end = { col = 5, row = 1 }, start = { col = 1, row = 1 } } (Token (Keyword Type)) + , Located { end = { col = 1, row = 2 }, start = { col = 5, row = 1 } } (Newlines [] 0) + ] + } + ] diff --git a/tests/ParserTest.elm b/tests/ParserTest.elm index b8a0d4d3..3001f51d 100644 --- a/tests/ParserTest.elm +++ b/tests/ParserTest.elm @@ -18,6 +18,7 @@ import Elm.Compiler.Error exposing (ParseContext, ParseProblem) import Elm.Data.Declaration as Declaration exposing (DeclarationBody) import Elm.Data.Exposing exposing (ExposedItem(..), Exposing(..)) import Elm.Data.Module exposing (ModuleType(..)) +import Elm.Data.Operator as Operator import Elm.Data.Qualifiedness exposing (PossiblyQualified(..)) import Elm.Data.Type.Concrete as ConcreteType exposing (ConcreteType) import Elm.Data.TypeAnnotation exposing (TypeAnnotation) @@ -489,7 +490,8 @@ expr = (Lambda { arguments = [ "x" ] , body = - Plus + Operator + Operator.Add (Argument "x") (Int 1) } @@ -506,7 +508,8 @@ expr = (Lambda { arguments = [ "x" ] , body = - Plus + Operator + Operator.Add (Argument "x") (Int 1) } @@ -518,7 +521,8 @@ expr = (Lambda { arguments = [ "x", "y" ] , body = - Plus + Operator + Operator.Add (Argument "x") (Argument "y") } @@ -1049,7 +1053,8 @@ expr = } ] , body = - Plus + Operator + Operator.Add (Int 1) (Argument "x") } @@ -1073,7 +1078,8 @@ expr = } , { name = "y" , body = - Plus + Operator + Operator.Add (Argument "x") (Int 1) } @@ -1123,7 +1129,7 @@ expr = ) , ( "list concat" , "[] ++ []" - , Just (ListConcat (List []) (List [])) + , Just (Operator Operator.Append (List []) (List [])) ) , ( "multiline" , """ @@ -1205,7 +1211,7 @@ expr = , [ ( "simple case" , "1 :: []" , Just - (Cons + (Operator Operator.Cons (Int 1) (List []) ) @@ -1213,9 +1219,9 @@ expr = , ( "multiple values case" , "1 :: 2 :: []" , Just - (Cons + (Operator Operator.Cons (Int 1) - (Cons + (Operator Operator.Cons (Int 2) (List []) ) @@ -1224,7 +1230,7 @@ expr = , ( "no spaces" , "1::[]" , Just - (Cons + (Operator Operator.Cons (Int 1) (List []) ) @@ -1232,7 +1238,7 @@ expr = , ( "multiple spaces" , "1 :: []" , Just - (Cons + (Operator Operator.Cons (Int 1) (List []) ) @@ -1268,7 +1274,7 @@ expr = , ( "multiline" , """ { a = 42 - , b = "hello" + , b = "hello" } """ , Just @@ -1545,7 +1551,7 @@ type_ = , ( "multiline record" , """ { x : Int - , y : String + , y : String } """ |> String.unindent diff --git a/tests/TestHelpers.elm b/tests/TestHelpers.elm index c6a0f029..3d4ac57d 100644 --- a/tests/TestHelpers.elm +++ b/tests/TestHelpers.elm @@ -12,6 +12,7 @@ module TestHelpers exposing import Elm.AST.Typed as Typed exposing (Expr_(..)) import Elm.Data.Located as Located exposing (Located) +import Elm.Data.Operator as Operator import Elm.Data.Qualifiedness exposing (Qualified) import Elm.Data.Type as Type exposing (Type, TypeOrId(..)) import Elm.Data.Type.Concrete as ConcreteType exposing (ConcreteType)