From 7ab96e730de9e7bf7da3646ab920636df4f02345 Mon Sep 17 00:00:00 2001 From: Jeroen Engels Date: Sun, 4 Aug 2024 00:40:01 +0200 Subject: [PATCH] Rework the Module type to grant access to common fields more easily --- CHANGELOG.md | 6 + src/Elm/Parser/Modules.elm | 31 ++--- src/Elm/Syntax/Module.elm | 94 +++------------ tests/Elm/Parser/FileTests.elm | 80 ++++++------- tests/Elm/Parser/ModuleTests.elm | 200 +++++++++++++++---------------- 5 files changed, 170 insertions(+), 241 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d33f78490..a7fe5b90e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,6 +67,12 @@ - Changed `Elm.Syntax.Exposing.Exposing`: - `Explicit (List (Node TopLevelExpose))` -> `Explicit (Node TopLevelExpose) (List (Node TopLevelExpose))` (takes a non-empty list of elements) +- Changed `Elm.Syntax.Module`: + - `Module` is now a record type alias for `{ moduleName : Node ModuleName, kind : ModuleKind, exposingList : Node Exposing }` + - Added `type ModuleKind = NormalModule | PortModule | EffectModule EffectModuleData` + - Removed fields `moduleName` and `exposingList` from `EffectModuleData` + - Removed helper functions `exposingList`, `moduleName`, `isPortModule`, `isEffectModule` + - Added module `Elm.Syntax.StringLiteralType` containing `type StringLiteralType = TripleQuote | SingleQuote` - Removed deprecated `Elm.Syntax.Range.emptyRange`, use `Elm.Syntax.Range.empty` instead. diff --git a/src/Elm/Parser/Modules.elm b/src/Elm/Parser/Modules.elm index 63f35474f..51aa2f5f3 100644 --- a/src/Elm/Parser/Modules.elm +++ b/src/Elm/Parser/Modules.elm @@ -4,7 +4,7 @@ import Elm.Parser.Base exposing (moduleName) import Elm.Parser.Expose exposing (exposeDefinition) import Elm.Parser.Layout as Layout import Elm.Parser.Tokens as Tokens -import Elm.Syntax.Module exposing (Module(..)) +import Elm.Syntax.Module exposing (Module, ModuleKind(..)) import Elm.Syntax.Node exposing (Node(..)) import List.Extra import ParserFast exposing (Parser) @@ -96,13 +96,14 @@ effectModuleDefinition = |> Rope.prependTo exp.comments , syntax = Node range - (EffectModule - { moduleName = name - , exposingList = exp.syntax - , command = whereClauses.syntax.command - , subscription = whereClauses.syntax.subscription - } - ) + { moduleName = name + , kind = + EffectModule + { command = whereClauses.syntax.command + , subscription = whereClauses.syntax.subscription + } + , exposingList = exp.syntax + } } ) (ParserFast.keywordFollowedBy "effect" Layout.maybeLayout) @@ -124,11 +125,10 @@ normalModuleDefinition = |> Rope.prependTo exposingList.comments , syntax = Node range - (NormalModule - { moduleName = moduleName - , exposingList = exposingList.syntax - } - ) + { moduleName = moduleName + , kind = NormalModule + , exposingList = exposingList.syntax + } } ) (ParserFast.keywordFollowedBy "module" Layout.maybeLayout) @@ -148,7 +148,10 @@ portModuleDefinition = |> Rope.prependTo exposingList.comments , syntax = Node range - (PortModule { moduleName = moduleName, exposingList = exposingList.syntax }) + { moduleName = moduleName + , kind = PortModule + , exposingList = exposingList.syntax + } } ) (ParserFast.keywordFollowedBy "port" Layout.maybeLayout) diff --git a/src/Elm/Syntax/Module.elm b/src/Elm/Syntax/Module.elm index e64858211..e0dc21cd9 100644 --- a/src/Elm/Syntax/Module.elm +++ b/src/Elm/Syntax/Module.elm @@ -1,7 +1,4 @@ -module Elm.Syntax.Module exposing - ( Module(..), DefaultModuleData, EffectModuleData - , exposingList, moduleName, isPortModule, isEffectModule - ) +module Elm.Syntax.Module exposing (Module, ModuleKind(..), EffectModuleData) {-| This syntax represents module definitions in Elm. For example: @@ -11,96 +8,35 @@ For example: ## Module -@docs Module, DefaultModuleData, EffectModuleData - -@docs exposingList, moduleName, isPortModule, isEffectModule +@docs Module, ModuleKind, EffectModuleData -} import Elm.Syntax.Exposing exposing (Exposing) import Elm.Syntax.ModuleName exposing (ModuleName) -import Elm.Syntax.Node as Node exposing (Node) +import Elm.Syntax.Node exposing (Node) -{-| Union type for different kind of modules +{-| Type alias representing a Module. -} -type Module - = NormalModule DefaultModuleData - | PortModule DefaultModuleData - | EffectModule EffectModuleData - - -{-| Data for a default default --} -type alias DefaultModuleData = +type alias Module = { moduleName : Node ModuleName + , kind : ModuleKind , exposingList : Node Exposing } +{-| Union type for different kind of modules +-} +type ModuleKind + = NormalModule + | PortModule + | EffectModule EffectModuleData + + {-| Data for an effect module -} type alias EffectModuleData = - { moduleName : Node ModuleName - , exposingList : Node Exposing - , command : Maybe (Node String) + { command : Maybe (Node String) , subscription : Maybe (Node String) } - - -{-| Get the name for a module. For older modules this may not be present. --} -moduleName : Module -> ModuleName -moduleName m = - case m of - NormalModule x -> - Node.value x.moduleName - - PortModule x -> - Node.value x.moduleName - - EffectModule x -> - Node.value x.moduleName - - -{-| Get the exposing list for a module. --} -exposingList : Module -> Exposing -exposingList m = - case m of - NormalModule x -> - Node.value x.exposingList - - PortModule x -> - Node.value x.exposingList - - EffectModule x -> - Node.value x.exposingList - - -{-| Check whether a module is defined as a port-module --} -isPortModule : Module -> Bool -isPortModule m = - case m of - PortModule _ -> - True - - _ -> - False - - -{-| Check whether a module is defined as an effect-module --} -isEffectModule : Module -> Bool -isEffectModule m = - case m of - EffectModule _ -> - True - - _ -> - False - - - --- diff --git a/tests/Elm/Parser/FileTests.elm b/tests/Elm/Parser/FileTests.elm index 412b39c54..e3fad93da 100644 --- a/tests/Elm/Parser/FileTests.elm +++ b/tests/Elm/Parser/FileTests.elm @@ -7,7 +7,7 @@ import Elm.Syntax.Declaration exposing (Declaration(..)) import Elm.Syntax.DestructurePattern exposing (DestructurePattern(..)) import Elm.Syntax.Exposing exposing (Exposing(..)) import Elm.Syntax.Expression exposing (Expression(..), LetDeclaration(..)) -import Elm.Syntax.Module exposing (Module(..)) +import Elm.Syntax.Module exposing (ModuleKind(..)) import Elm.Syntax.Node exposing (Node(..)) import Elm.Syntax.Pattern exposing (Pattern(..)) import Elm.Syntax.TypeAnnotation exposing (TypeAnnotation(..)) @@ -139,13 +139,12 @@ caseWhitespace f = case f of (Ok { moduleDefinition = Node { start = { row = 2, column = 1 }, end = { row = 2, column = 41 } } - (NormalModule - { moduleName = Node { start = { row = 2, column = 8 }, end = { row = 2, column = 27 } } [ "Trailing", "Whitespace" ] - , exposingList = - Node { start = { row = 2, column = 28 }, end = { row = 2, column = 41 } } - (All { start = { row = 2, column = 38 }, end = { row = 2, column = 40 } }) - } - ) + { moduleName = Node { start = { row = 2, column = 8 }, end = { row = 2, column = 27 } } [ "Trailing", "Whitespace" ] + , kind = NormalModule + , exposingList = + Node { start = { row = 2, column = 28 }, end = { row = 2, column = 41 } } + (All { start = { row = 2, column = 38 }, end = { row = 2, column = 40 } }) + } , imports = [] , declarations = [ Node { start = { row = 4, column = 1 }, end = { row = 11, column = 11 } } @@ -198,13 +197,12 @@ lambdaWhitespace = \\ a b -> a (Ok { moduleDefinition = Node { start = { row = 2, column = 1 }, end = { row = 2, column = 41 } } - (NormalModule - { moduleName = Node { start = { row = 2, column = 8 }, end = { row = 2, column = 27 } } [ "Trailing", "Whitespace" ] - , exposingList = - Node { start = { row = 2, column = 28 }, end = { row = 2, column = 41 } } - (All { start = { row = 2, column = 38 }, end = { row = 2, column = 40 } }) - } - ) + { moduleName = Node { start = { row = 2, column = 8 }, end = { row = 2, column = 27 } } [ "Trailing", "Whitespace" ] + , kind = NormalModule + , exposingList = + Node { start = { row = 2, column = 28 }, end = { row = 2, column = 41 } } + (All { start = { row = 2, column = 38 }, end = { row = 2, column = 40 } }) + } , imports = [] , declarations = [ Node { start = { row = 4, column = 1 }, end = { row = 8, column = 6 } } @@ -256,13 +254,12 @@ letWhitespace = let (Ok { moduleDefinition = Node { start = { row = 2, column = 1 }, end = { row = 2, column = 41 } } - (NormalModule - { moduleName = Node { start = { row = 2, column = 8 }, end = { row = 2, column = 27 } } [ "Trailing", "Whitespace" ] - , exposingList = - Node { start = { row = 2, column = 28 }, end = { row = 2, column = 41 } } - (All { start = { row = 2, column = 38 }, end = { row = 2, column = 40 } }) - } - ) + { moduleName = Node { start = { row = 2, column = 8 }, end = { row = 2, column = 27 } } [ "Trailing", "Whitespace" ] + , kind = NormalModule + , exposingList = + Node { start = { row = 2, column = 28 }, end = { row = 2, column = 41 } } + (All { start = { row = 2, column = 38 }, end = { row = 2, column = 40 } }) + } , imports = [] , declarations = [ Node { start = { row = 4, column = 1 }, end = { row = 8, column = 3 } } @@ -317,13 +314,12 @@ type Configuration (Ok { moduleDefinition = Node { start = { row = 2, column = 1 }, end = { row = 2, column = 25 } } - (NormalModule - { moduleName = Node { start = { row = 2, column = 8 }, end = { row = 2, column = 11 } } [ "Foo" ] - , exposingList = - Node { start = { row = 2, column = 12 }, end = { row = 2, column = 25 } } - (All { start = { row = 2, column = 22 }, end = { row = 2, column = 24 } }) - } - ) + { moduleName = Node { start = { row = 2, column = 8 }, end = { row = 2, column = 11 } } [ "Foo" ] + , kind = NormalModule + , exposingList = + Node { start = { row = 2, column = 12 }, end = { row = 2, column = 25 } } + (All { start = { row = 2, column = 22 }, end = { row = 2, column = 24 } }) + } , imports = [ Node { start = { row = 4, column = 1 }, end = { row = 4, column = 12 } } { moduleName = Node { start = { row = 4, column = 8 }, end = { row = 4, column = 12 } } [ "Dict" ] @@ -364,13 +360,12 @@ type Configuration (Ok { moduleDefinition = Node { start = { row = 2, column = 1 }, end = { row = 2, column = 25 } } - (NormalModule - { moduleName = Node { start = { row = 2, column = 8 }, end = { row = 2, column = 11 } } [ "Foo" ] - , exposingList = - Node { start = { row = 2, column = 12 }, end = { row = 2, column = 25 } } - (All { start = { row = 2, column = 22 }, end = { row = 2, column = 24 } }) - } - ) + { moduleName = Node { start = { row = 2, column = 8 }, end = { row = 2, column = 11 } } [ "Foo" ] + , kind = NormalModule + , exposingList = + Node { start = { row = 2, column = 12 }, end = { row = 2, column = 25 } } + (All { start = { row = 2, column = 22 }, end = { row = 2, column = 24 } }) + } , imports = [] , declarations = [ Node { start = { row = 6, column = 1 }, end = { row = 7, column = 20 } } @@ -406,13 +401,12 @@ port sendResponse : String -> Cmd msg (Ok { moduleDefinition = Node { start = { row = 2, column = 1 }, end = { row = 2, column = 30 } } - (PortModule - { moduleName = Node { start = { row = 2, column = 13 }, end = { row = 2, column = 16 } } [ "Foo" ] - , exposingList = - Node { start = { row = 2, column = 17 }, end = { row = 2, column = 30 } } - (All { start = { row = 2, column = 27 }, end = { row = 2, column = 29 } }) - } - ) + { moduleName = Node { start = { row = 2, column = 13 }, end = { row = 2, column = 16 } } [ "Foo" ] + , kind = PortModule + , exposingList = + Node { start = { row = 2, column = 17 }, end = { row = 2, column = 30 } } + (All { start = { row = 2, column = 27 }, end = { row = 2, column = 29 } }) + } , imports = [ Node { start = { row = 4, column = 1 }, end = { row = 4, column = 14 } } { moduleName = Node { start = { row = 4, column = 8 }, end = { row = 4, column = 14 } } [ "String" ] diff --git a/tests/Elm/Parser/ModuleTests.elm b/tests/Elm/Parser/ModuleTests.elm index ec030b090..82fb55e02 100644 --- a/tests/Elm/Parser/ModuleTests.elm +++ b/tests/Elm/Parser/ModuleTests.elm @@ -23,62 +23,59 @@ all = \() -> "module Foo exposing (Bar)" |> expectAst - (NormalModule - { moduleName = Node { start = { row = 1, column = 8 }, end = { row = 1, column = 11 } } [ "Foo" ] - , exposingList = - Node { start = { row = 1, column = 12 }, end = { row = 1, column = 26 } } - (Explicit - (Node { start = { row = 1, column = 22 }, end = { row = 1, column = 25 } } (TypeOrAliasExpose "Bar")) - [] - ) - } - ) + { moduleName = Node { start = { row = 1, column = 8 }, end = { row = 1, column = 11 } } [ "Foo" ] + , kind = NormalModule + , exposingList = + Node { start = { row = 1, column = 12 }, end = { row = 1, column = 26 } } + (Explicit + (Node { start = { row = 1, column = 22 }, end = { row = 1, column = 25 } } (TypeOrAliasExpose "Bar")) + [] + ) + } , test "port moduleDefinition" <| \() -> "port module Foo exposing (Bar)" |> expectAst - (PortModule - { moduleName = Node { start = { row = 1, column = 13 }, end = { row = 1, column = 16 } } [ "Foo" ] - , exposingList = - Node { start = { row = 1, column = 17 }, end = { row = 1, column = 31 } } - (Explicit (Node { start = { row = 1, column = 27 }, end = { row = 1, column = 30 } } (TypeOrAliasExpose "Bar")) []) - } - ) + { moduleName = Node { start = { row = 1, column = 13 }, end = { row = 1, column = 16 } } [ "Foo" ] + , kind = PortModule + , exposingList = + Node { start = { row = 1, column = 17 }, end = { row = 1, column = 31 } } + (Explicit (Node { start = { row = 1, column = 27 }, end = { row = 1, column = 30 } } (TypeOrAliasExpose "Bar")) []) + } , test "port moduleDefinition with spacing" <| \() -> "port module Foo exposing ( Bar )" |> expectAst - (PortModule - { moduleName = Node { start = { row = 1, column = 13 }, end = { row = 1, column = 16 } } [ "Foo" ] - , exposingList = - Node { start = { row = 1, column = 17 }, end = { row = 1, column = 33 } } - (Explicit (Node { start = { row = 1, column = 28 }, end = { row = 1, column = 31 } } (TypeOrAliasExpose "Bar")) []) - } - ) + { moduleName = Node { start = { row = 1, column = 13 }, end = { row = 1, column = 16 } } [ "Foo" ] + , kind = PortModule + , exposingList = + Node { start = { row = 1, column = 17 }, end = { row = 1, column = 33 } } + (Explicit (Node { start = { row = 1, column = 28 }, end = { row = 1, column = 31 } } (TypeOrAliasExpose "Bar")) []) + } , test "effect moduleDefinition" <| \() -> "effect module Foo where {command = MyCmd, subscription = MySub } exposing (Bar)" |> expectAst - (EffectModule - { moduleName = Node { start = { row = 1, column = 15 }, end = { row = 1, column = 18 } } [ "Foo" ] - , exposingList = - Node { start = { row = 1, column = 66 }, end = { row = 1, column = 80 } } - (Explicit (Node { start = { row = 1, column = 76 }, end = { row = 1, column = 79 } } (TypeOrAliasExpose "Bar")) []) - , command = Just (Node { start = { row = 1, column = 36 }, end = { row = 1, column = 41 } } "MyCmd") - , subscription = Just (Node { start = { row = 1, column = 58 }, end = { row = 1, column = 63 } } "MySub") - } - ) + { moduleName = Node { start = { row = 1, column = 15 }, end = { row = 1, column = 18 } } [ "Foo" ] + , kind = + EffectModule + { command = Just (Node { start = { row = 1, column = 36 }, end = { row = 1, column = 41 } } "MyCmd") + , subscription = Just (Node { start = { row = 1, column = 58 }, end = { row = 1, column = 63 } } "MySub") + } + , exposingList = + Node { start = { row = 1, column = 66 }, end = { row = 1, column = 80 } } + (Explicit (Node { start = { row = 1, column = 76 }, end = { row = 1, column = 79 } } (TypeOrAliasExpose "Bar")) []) + } , test "unformatted" <| \() -> "module \n Foo \n exposing (..)" |> expectAst - (NormalModule - { moduleName = Node { start = { row = 2, column = 2 }, end = { row = 2, column = 5 } } [ "Foo" ] - , exposingList = - Node { start = { row = 3, column = 2 }, end = { row = 3, column = 16 } } - (All { start = { row = 3, column = 13 }, end = { row = 3, column = 15 } }) - } - ) + { moduleName = Node { start = { row = 2, column = 2 }, end = { row = 2, column = 5 } } [ "Foo" ] + , kind = NormalModule + , exposingList = + Node { start = { row = 3, column = 2 }, end = { row = 3, column = 16 } } + (All { start = { row = 3, column = 13 }, end = { row = 3, column = 15 } }) + } , test "unformatted wrong" <| \() -> parse "module \nFoo \n exposing (..)" Parser.moduleDefinition @@ -87,24 +84,22 @@ all = \() -> "module Foo exposing (..)" |> expectAst - (NormalModule - { moduleName = Node { start = { row = 1, column = 8 }, end = { row = 1, column = 11 } } [ "Foo" ] - , exposingList = - Node { start = { row = 1, column = 12 }, end = { row = 1, column = 25 } } - (All { start = { row = 1, column = 22 }, end = { row = 1, column = 24 } }) - } - ) + { moduleName = Node { start = { row = 1, column = 8 }, end = { row = 1, column = 11 } } [ "Foo" ] + , kind = NormalModule + , exposingList = + Node { start = { row = 1, column = 12 }, end = { row = 1, column = 25 } } + (All { start = { row = 1, column = 22 }, end = { row = 1, column = 24 } }) + } , test "module name with _" <| \() -> "module I_en_gb exposing (..)" |> expectAst - (NormalModule - { moduleName = Node { start = { row = 1, column = 8 }, end = { row = 1, column = 15 } } [ "I_en_gb" ] - , exposingList = - Node { start = { row = 1, column = 16 }, end = { row = 1, column = 29 } } - (All { start = { row = 1, column = 26 }, end = { row = 1, column = 28 } }) - } - ) + { moduleName = Node { start = { row = 1, column = 8 }, end = { row = 1, column = 15 } } [ "I_en_gb" ] + , kind = NormalModule + , exposingList = + Node { start = { row = 1, column = 16 }, end = { row = 1, column = 29 } } + (All { start = { row = 1, column = 26 }, end = { row = 1, column = 28 } }) + } , test "Regression test for Incorrect range in if expression" <| \() -> parseCore @@ -127,24 +122,23 @@ b = 3 (Ok { moduleDefinition = Node { start = { row = 1, column = 1 }, end = { row = 1, column = 32 } } - (NormalModule - { moduleName = - Node - { start = { row = 1, column = 8 } - , end = { row = 1, column = 18 } - } - [ "TestModule" ] - , exposingList = - Node - { start = { row = 1, column = 19 } - , end = - { row = 1 - , column = 32 - } + { moduleName = + Node + { start = { row = 1, column = 8 } + , end = { row = 1, column = 18 } + } + [ "TestModule" ] + , kind = NormalModule + , exposingList = + Node + { start = { row = 1, column = 19 } + , end = + { row = 1 + , column = 32 } - (All { start = { row = 1, column = 29 }, end = { row = 1, column = 31 } }) - } - ) + } + (All { start = { row = 1, column = 29 }, end = { row = 1, column = 31 } }) + } , imports = [] , declarations = [ Node { start = { row = 3, column = 1 }, end = { row = 7, column = 10 } } @@ -216,17 +210,16 @@ b = 3 (Ok { moduleDefinition = Node { start = { row = 1, column = 1 }, end = { row = 1, column = 32 } } - (NormalModule - { moduleName = Node { start = { row = 1, column = 8 }, end = { row = 1, column = 18 } } [ "TestModule" ] - , exposingList = - Node { start = { row = 1, column = 19 }, end = { row = 1, column = 32 } } - (All - { start = { row = 1, column = 29 } - , end = { row = 1, column = 31 } - } - ) - } - ) + { moduleName = Node { start = { row = 1, column = 8 }, end = { row = 1, column = 18 } } [ "TestModule" ] + , kind = NormalModule + , exposingList = + Node { start = { row = 1, column = 19 }, end = { row = 1, column = 32 } } + (All + { start = { row = 1, column = 29 } + , end = { row = 1, column = 31 } + } + ) + } , imports = [] , declarations = [ Node @@ -287,13 +280,12 @@ a = 1 (Ok { moduleDefinition = Node { start = { row = 1, column = 1 }, end = { row = 1, column = 32 } } - (NormalModule - { moduleName = Node { start = { row = 1, column = 8 }, end = { row = 1, column = 18 } } [ "TestModule" ] - , exposingList = - Node { start = { row = 1, column = 19 }, end = { row = 1, column = 32 } } - (All { start = { row = 1, column = 29 }, end = { row = 1, column = 31 } }) - } - ) + { moduleName = Node { start = { row = 1, column = 8 }, end = { row = 1, column = 18 } } [ "TestModule" ] + , kind = NormalModule + , exposingList = + Node { start = { row = 1, column = 19 }, end = { row = 1, column = 32 } } + (All { start = { row = 1, column = 29 }, end = { row = 1, column = 31 } }) + } , imports = [ Node { start = { row = 2, column = 1 }, end = { row = 2, column = 9 } } { moduleName = Node { start = { row = 2, column = 8 }, end = { row = 2, column = 9 } } [ "A" ] @@ -338,11 +330,10 @@ b = 2 (Ok { moduleDefinition = Node { start = { row = 1, column = 1 }, end = { row = 1, column = 32 } } - (NormalModule - { moduleName = Node { start = { row = 1, column = 8 }, end = { row = 1, column = 18 } } [ "TestModule" ] - , exposingList = Node { start = { row = 1, column = 19 }, end = { row = 1, column = 32 } } (All { start = { row = 1, column = 29 }, end = { row = 1, column = 31 } }) - } - ) + { moduleName = Node { start = { row = 1, column = 8 }, end = { row = 1, column = 18 } } [ "TestModule" ] + , kind = NormalModule + , exposingList = Node { start = { row = 1, column = 19 }, end = { row = 1, column = 32 } } (All { start = { row = 1, column = 29 }, end = { row = 1, column = 31 } }) + } , imports = [] , declarations = [ Node { start = { row = 2, column = 1 }, end = { row = 2, column = 15 } } @@ -438,17 +429,16 @@ fun2 n = (Ok { moduleDefinition = Node { start = { row = 1, column = 1 }, end = { row = 1, column = 31 } } - (NormalModule - { moduleName = Node { start = { row = 1, column = 8 }, end = { row = 1, column = 9 } } [ "A" ] - , exposingList = - Node { start = { row = 1, column = 10 }, end = { row = 1, column = 31 } } - (Explicit - (Node { start = { row = 1, column = 20 }, end = { row = 1, column = 24 } } (FunctionExpose "fun1")) - [ Node { start = { row = 1, column = 26 }, end = { row = 1, column = 30 } } (FunctionExpose "fun2") - ] - ) - } - ) + { moduleName = Node { start = { row = 1, column = 8 }, end = { row = 1, column = 9 } } [ "A" ] + , kind = NormalModule + , exposingList = + Node { start = { row = 1, column = 10 }, end = { row = 1, column = 31 } } + (Explicit + (Node { start = { row = 1, column = 20 }, end = { row = 1, column = 24 } } (FunctionExpose "fun1")) + [ Node { start = { row = 1, column = 26 }, end = { row = 1, column = 30 } } (FunctionExpose "fun2") + ] + ) + } , imports = [] , declarations = [ Node { start = { row = 3, column = 1 }, end = { row = 5, column = 11 } }