Play

Check-in [40164ce609]
Login
Overview
Comment:CLI now injects path to stdlib as a package path.
Timelines: family | ancestors | descendants | both | cli
Files: files | file ages | folders
SHA3-256: 40164ce6099d53e688acda15a7a75ea4564dfc6df0c642594bafaf539701d861
User & Date: robin.hansen on 2021-04-07 13:38:24
Other Links: branch diff | manifest | tags
Context
2021-04-07
13:39
Add cli program to compile projects, run functions and initiate new projects. Leaf check-in: 9318fc4c3b user: robin.hansen tags: trunk
13:38
CLI now injects path to stdlib as a package path. Closed-Leaf check-in: 40164ce609 user: robin.hansen tags: cli
13:01
Detect errors in CLI.elm, and forward those errors to the terminal. check-in: 3b0a88175e user: robin.hansen tags: cli
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Modified src/CLI.elm from [82a859cde1] to [2a2a2f3219].

10
11
12
13
14
15
16

17
18
19
20
21
22
23
..
31
32
33
34
35
36
37
38
39
40
41




42
43
44
45
46
47
48
import Play.TypeChecker.Problem as TypeCheckerProblem
import Wasm


type alias Flags =
    { projectDir : String
    , entryPoint : Maybe String

    }


type alias Model =
    PackageLoader.Model


................................................................................
        { init = init
        , update = update
        , subscriptions = subscriptions
        }


init : Flags -> ( Model, Cmd Msg )
init { projectDir, entryPoint } =
    let
        initialModel =
            PackageLoader.init projectDir entryPoint




    in
    ( initialModel
    , sendSideEffectFromModel initialModel
    )


sendSideEffectFromModel : PackageLoader.Model -> Cmd Msg







>







 







|


|
>
>
>
>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import Play.TypeChecker.Problem as TypeCheckerProblem
import Wasm


type alias Flags =
    { projectDir : String
    , entryPoint : Maybe String
    , stdLibPath : String
    }


type alias Model =
    PackageLoader.Model


................................................................................
        { init = init
        , update = update
        , subscriptions = subscriptions
        }


init : Flags -> ( Model, Cmd Msg )
init { projectDir, entryPoint, stdLibPath } =
    let
        initialModel =
            PackageLoader.init
                { projectDirPath = projectDir
                , possibleEntryPoint = entryPoint
                , stdLibPath = stdLibPath
                }
    in
    ( initialModel
    , sendSideEffectFromModel initialModel
    )


sendSideEffectFromModel : PackageLoader.Model -> Cmd Msg

Modified src/Play/Data/PackagePath.elm from [b58e74fd1c] to [1e9585ddbd].

36
37
38
39
40
41
42




43
44
45




46
    ctor <| String.dropRight charsToDrop str


prefix : String -> PackagePath -> PackagePath
prefix pathToPrefix packagePath =
    case packagePath of
        Directory dir ->




            Directory <| pathToPrefix ++ "/" ++ dir

        AllDirectoriesInDirectory dir ->




            AllDirectoriesInDirectory <| pathToPrefix ++ "/" ++ dir







>
>
>
>
|


>
>
>
>
|
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
    ctor <| String.dropRight charsToDrop str


prefix : String -> PackagePath -> PackagePath
prefix pathToPrefix packagePath =
    case packagePath of
        Directory dir ->
            if String.startsWith "/" dir then
                packagePath

            else
                Directory <| pathToPrefix ++ "/" ++ dir

        AllDirectoriesInDirectory dir ->
            if String.startsWith "/" dir then
                packagePath

            else
                AllDirectoriesInDirectory <| pathToPrefix ++ "/" ++ dir

Modified src/Play/PackageLoader.elm from [a38a7dc958] to [41ef8f9010].

26
27
28
29
30
31
32
33







34
35
36
37
38
39
40
41
42
..
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
...
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125






126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
type Problem
    = InvalidPackageMetadata String String
    | UnknownMessageForState String
    | NoExposedModulesInRootProject
    | ModuleNotFound String
    | InternalError String









type Model
    = Initializing (Maybe String) SideEffect
    | LoadingMetadata State (List PackagePath) SideEffect
    | ResolvingModulePaths State (List PackageInfo) SideEffect
    | Compiling State (List ( PackageInfo, ModuleName )) SideEffect
    | Done Qualifier.ExposedAST
    | Failed Problem


................................................................................
type alias PackageInfo =
    { path : String
    , metadata : PackageMetadata
    , modules : List ModuleName
    }


emptyState : Maybe String -> PackageInfo -> State
emptyState possibleEntryPoint rootPackage =
    { possibleEntryPoint = possibleEntryPoint
    , rootPackage = rootPackage
    , dependencies = rootPackage.metadata.dependencies
    , dependentPackages = Dict.empty
    , filePathToModule = Dict.empty
    , moduleNameToPackageName = Dict.empty
    , absoluteModuleNameToDetails = Dict.empty
    , inProgressAst = Nothing
................................................................................
        ResolvingModulePaths _ _ sf ->
            Just sf

        Compiling _ _ sf ->
            Just sf


init : String -> Maybe String -> Model
init projectDirPath possibleEntryPoint =
    Initializing possibleEntryPoint <|
        ReadFile projectDirPath "play.json"


update : Msg -> Model -> Model
update msg model =
    case model of
        Initializing possibleEntryPoint _ ->
            case msg of
                FileContents path _ content ->
                    case Json.decodeString PackageMetadata.decoder content of
                        Ok metadata ->
                            let






                                state =
                                    emptyState possibleEntryPoint
                                        { path = path
                                        , metadata = metadata
                                        , modules = []
                                        }

                                pathsToLoad =
                                    List.map (PackagePath.prefix path) metadata.packagePaths
                            in
                            case pathsToLoad of
                                [] ->
                                    ResolvingModulePaths state [] <|
                                        ResolvePackageModules (PackageName.toString metadata.name) path

                                (PackagePath.Directory nextPathDir) :: _ ->








>
>
>
>
>
>
>

|







 







|
|
|







 







|
|
|
|





|





>
>
>
>
>
>

|

|




|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
..
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
...
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
type Problem
    = InvalidPackageMetadata String String
    | UnknownMessageForState String
    | NoExposedModulesInRootProject
    | ModuleNotFound String
    | InternalError String


type alias InitOptions =
    { projectDirPath : String
    , stdLibPath : String
    , possibleEntryPoint : Maybe String
    }


type Model
    = Initializing InitOptions SideEffect
    | LoadingMetadata State (List PackagePath) SideEffect
    | ResolvingModulePaths State (List PackageInfo) SideEffect
    | Compiling State (List ( PackageInfo, ModuleName )) SideEffect
    | Done Qualifier.ExposedAST
    | Failed Problem


................................................................................
type alias PackageInfo =
    { path : String
    , metadata : PackageMetadata
    , modules : List ModuleName
    }


emptyState : InitOptions -> PackageInfo -> State
emptyState initOptions rootPackage =
    { possibleEntryPoint = initOptions.possibleEntryPoint
    , rootPackage = rootPackage
    , dependencies = rootPackage.metadata.dependencies
    , dependentPackages = Dict.empty
    , filePathToModule = Dict.empty
    , moduleNameToPackageName = Dict.empty
    , absoluteModuleNameToDetails = Dict.empty
    , inProgressAst = Nothing
................................................................................
        ResolvingModulePaths _ _ sf ->
            Just sf

        Compiling _ _ sf ->
            Just sf


init : InitOptions -> Model
init initOptions =
    Initializing initOptions <|
        ReadFile initOptions.projectDirPath "play.json"


update : Msg -> Model -> Model
update msg model =
    case model of
        Initializing initOpts _ ->
            case msg of
                FileContents path _ content ->
                    case Json.decodeString PackageMetadata.decoder content of
                        Ok metadata ->
                            let
                                metadataWithStdLib =
                                    { metadata
                                        | packagePaths =
                                            metadata.packagePaths ++ [ PackagePath.fromString initOpts.stdLibPath ]
                                    }

                                state =
                                    emptyState initOpts
                                        { path = path
                                        , metadata = metadataWithStdLib
                                        , modules = []
                                        }

                                pathsToLoad =
                                    List.map (PackagePath.prefix path) metadataWithStdLib.packagePaths
                            in
                            case pathsToLoad of
                                [] ->
                                    ResolvingModulePaths state [] <|
                                        ResolvePackageModules (PackageName.toString metadata.name) path

                                (PackagePath.Directory nextPathDir) :: _ ->

Modified tests/Test/PackageLoader.elm from [16ac885c95] to [da9199a4ec].

12
13
14
15
16
17
18







19
20
21
22
23
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
..
74
75
76
77
78
79
80


81


82
83
84
85
86
87
88
...
122
123
124
125
126
127
128



129
130
131
132
133
134
135
136
137
...
232
233
234
235
236
237
238

239
240
241
242
243
244
245
246
...
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
import Play.Qualifier as Qualifier
import Test exposing (Test, describe, test)
import Test.Qualifier.Util as Util


suite : Test
suite =







    describe "PackageLoader"
        [ test "Passes the load package metadata step" <|
            \_ ->
                PackageLoader.init "/project" Nothing
                    |> Expect.equal (PackageLoader.Initializing Nothing <| PackageLoader.ReadFile "/project" "play.json")
        , test "Retrieves necessary files" <|
            \_ ->
                PackageLoader.init "/project" Nothing
                    |> expectSideEffects testFiles
                        [ PackageLoader.ReadFile "/project" "play.json"
                        , PackageLoader.ResolveDirectories "/project/lib"
                        , PackageLoader.ReadFile "/project/lib/template_strings" "play.json"

                        , PackageLoader.ReadFile "/project/lib/template_strings/lib/version" "play.json"
                        , PackageLoader.ReadFile "/project/lib/unused" "play.json"
                        , PackageLoader.ReadFile "/project/lib/version" "play.json"
                        , PackageLoader.ResolvePackageModules "robheghan/fnv" "/project"
                        , PackageLoader.ResolvePackageModules "jarvis/template_strings" "/project/lib/template_strings"
                        , PackageLoader.ResolvePackageModules "play/version" "/project/lib/template_strings/lib/version"
                        , PackageLoader.ReadFile "/project/src" "mod1.play"
                        , PackageLoader.ReadFile "/project/lib/template_strings/lib/version/src/version" "data.play"
                        ]
        , test "Compiles to qualified AST" <|
            \_ ->
                let
                    loaderResult =
                        PackageLoader.init "/project" Nothing
                            |> resolveSideEffects testFiles []
                            |> Result.map Tuple.second
                in
                case loaderResult of
                    Err msg ->
                        Expect.fail msg

................................................................................
                                    ]
                            }
                            (Util.stripLocations ast)
        , test "Specified entry point is marked as such" <|
            \_ ->
                let
                    loaderResult =


                        PackageLoader.init "/project" (Just "/play/version/version/data/number")


                            |> resolveSideEffects testFiles []
                            |> Result.map Tuple.second
                in
                case loaderResult of
                    Err msg ->
                        Expect.fail msg

................................................................................
        Err msg ->
            Expect.fail msg

        Ok ( seenSfs, _ ) ->
            let
                sfDiff =
                    List.filter (\sf -> not <| List.member sf expectedSFs) seenSfs



            in
            Expect.equalLists [] sfDiff


resolveSideEffects :
    Dict String String
    -> List PackageLoader.SideEffect
    -> PackageLoader.Model
    -> Result String ( List PackageLoader.SideEffect, Qualifier.ExposedAST )
................................................................................
                    "mod1"
                ],
                "dependencies": {
                    "jarvis/template_strings": "1.2.0",
                    "play/version": "1.0.0"
                },
                "package-paths": [

                    "lib/*"
                ]
            }
            """
          )
        , ( "/project/src/mod1.play"
          , """
            def: next-version
................................................................................
                "exposed-modules": [
                    "template_strings/mod"
                ],
                "dependencies": {
                    "play/version": "1.1.0"
                },
                "package-paths": [
                    "lib/version"
                ]
            }
          """
          )
        , ( "/project/lib/template_strings/src/template_strings/mod.play"
          , """
            def: dec







>
>
>
>
>
>
>



|
|


|


<

>













|







 







>
>
|
>
>







 







>
>
>

|







 







>
|







 







|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
..
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
...
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
...
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
...
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
import Play.Qualifier as Qualifier
import Test exposing (Test, describe, test)
import Test.Qualifier.Util as Util


suite : Test
suite =
    let
        initOpts =
            { projectDirPath = "/project"
            , possibleEntryPoint = Nothing
            , stdLibPath = "/project/lib/unused"
            }
    in
    describe "PackageLoader"
        [ test "Passes the load package metadata step" <|
            \_ ->
                PackageLoader.init initOpts
                    |> Expect.equal (PackageLoader.Initializing initOpts <| PackageLoader.ReadFile "/project" "play.json")
        , test "Retrieves necessary files" <|
            \_ ->
                PackageLoader.init initOpts
                    |> expectSideEffects testFiles
                        [ PackageLoader.ReadFile "/project" "play.json"

                        , PackageLoader.ReadFile "/project/lib/template_strings" "play.json"
                        , PackageLoader.ResolveDirectories "/project/lib/template_strings/lib"
                        , PackageLoader.ReadFile "/project/lib/template_strings/lib/version" "play.json"
                        , PackageLoader.ReadFile "/project/lib/unused" "play.json"
                        , PackageLoader.ReadFile "/project/lib/version" "play.json"
                        , PackageLoader.ResolvePackageModules "robheghan/fnv" "/project"
                        , PackageLoader.ResolvePackageModules "jarvis/template_strings" "/project/lib/template_strings"
                        , PackageLoader.ResolvePackageModules "play/version" "/project/lib/template_strings/lib/version"
                        , PackageLoader.ReadFile "/project/src" "mod1.play"
                        , PackageLoader.ReadFile "/project/lib/template_strings/lib/version/src/version" "data.play"
                        ]
        , test "Compiles to qualified AST" <|
            \_ ->
                let
                    loaderResult =
                        PackageLoader.init initOpts
                            |> resolveSideEffects testFiles []
                            |> Result.map Tuple.second
                in
                case loaderResult of
                    Err msg ->
                        Expect.fail msg

................................................................................
                                    ]
                            }
                            (Util.stripLocations ast)
        , test "Specified entry point is marked as such" <|
            \_ ->
                let
                    loaderResult =
                        PackageLoader.init
                            { projectDirPath = "/project"
                            , possibleEntryPoint = Just "/play/version/version/data/number"
                            , stdLibPath = initOpts.stdLibPath
                            }
                            |> resolveSideEffects testFiles []
                            |> Result.map Tuple.second
                in
                case loaderResult of
                    Err msg ->
                        Expect.fail msg

................................................................................
        Err msg ->
            Expect.fail msg

        Ok ( seenSfs, _ ) ->
            let
                sfDiff =
                    List.filter (\sf -> not <| List.member sf expectedSFs) seenSfs

                sfDiffRev =
                    List.filter (\sf -> not <| List.member sf seenSfs) expectedSFs
            in
            Expect.equalLists [] (sfDiff ++ sfDiffRev)


resolveSideEffects :
    Dict String String
    -> List PackageLoader.SideEffect
    -> PackageLoader.Model
    -> Result String ( List PackageLoader.SideEffect, Qualifier.ExposedAST )
................................................................................
                    "mod1"
                ],
                "dependencies": {
                    "jarvis/template_strings": "1.2.0",
                    "play/version": "1.0.0"
                },
                "package-paths": [
                    "lib/template_strings",
                    "lib/version"
                ]
            }
            """
          )
        , ( "/project/src/mod1.play"
          , """
            def: next-version
................................................................................
                "exposed-modules": [
                    "template_strings/mod"
                ],
                "dependencies": {
                    "play/version": "1.1.0"
                },
                "package-paths": [
                    "lib/*"
                ]
            }
          """
          )
        , ( "/project/lib/template_strings/src/template_strings/mod.play"
          , """
            def: dec