Stabel

Check-in [e91945bdeb]
Login
Overview
Comment:Fixed bug where internal modules wasn't necesarily compiled in correct order.
Timelines: family | ancestors | descendants | both | module-definition
Files: files | file ages | folders
SHA3-256: e91945bdeb543932b68a62f701583d966b2cebcab1fab4977dc7a5d0c46c5cc7
User & Date: robin.hansen on 2021-05-29 16:14:20
Other Links: branch diff | manifest | tags
Context
2021-05-31
10:36
Add module definitions to all standard library modules. check-in: cfb0ec9059 user: robin.hansen tags: module-definition
2021-05-29
16:14
Fixed bug where internal modules wasn't necesarily compiled in correct order. check-in: e91945bdeb user: robin.hansen tags: module-definition
2021-05-28
09:34
Fixed parser bug for type signatures with multiple in/out arguments. check-in: 562f019b23 user: robin.hansen tags: module-definition
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Modified src/Play/PackageLoader.elm from [c6047bc95a] to [cfb8a0b60d].

67
68
69
70
71
72
73

74
75
76
77
78
79
80
...
447
448
449
450
451
452
453







454
455
456
457
458
459
460
461

462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
...
499
500
501
502
503
504
505



506
507
508
509
510
511
512
513
514
...
556
557
558
559
560
561
562


























    }


type alias ParsedModuleInfo =
    { packageName : PackageName
    , modulePath : ModuleName
    , ast : Parser.AST

    }


emptyState : InitOptions -> PackageInfo -> State
emptyState initOptions rootPackage =
    { possibleEntryPoint = initOptions.possibleEntryPoint
    , rootPackage = rootPackage
................................................................................
                ( Just ( packageName, moduleName ), Ok parserAst ) ->
                    let
                        fullModuleName =
                            absoluteModuleName packageName moduleName

                        updatedParsedModules =
                            Set.insert fullModuleName state.parsedModuleNames








                        updatedState =
                            { state
                                | parsedModuleNames = updatedParsedModules
                                , parsedModules =
                                    { packageName = packageName
                                    , modulePath = moduleName
                                    , ast = parserAst

                                    }
                                        :: state.parsedModules
                            }

                        requiredModules =
                            Qualifier.requiredModules
                                { packageName = PackageName.toString packageName
                                , ast = parserAst
                                , externalModules = state.moduleNameToPackageName
                                }

                        modulesQueuedForOrAlreadyParsed =
                            remainingModules
                                |> List.map (\( pInfo, mName ) -> absoluteModuleName pInfo.metadata.name mName)
                                |> Set.fromList
                                |> Set.union updatedParsedModules

                        missingModulesInParseQueue =
................................................................................


nextCompileStep : List ( PackageInfo, ModuleName ) -> State -> Model
nextCompileStep remainingModules state =
    case remainingModules of
        [] ->
            let



                ( qualifiedAst, errs ) =
                    state.parsedModules
                        |> List.foldl qualifyAst ( { types = Dict.empty, words = Dict.empty }, [] )

                qualifyAst parsedModInfo ( qast, es ) =
                    let
                        qualifierResult =
                            Qualifier.run
                                { packageName = PackageName.toString parsedModInfo.packageName
................................................................................

        ( packageInfo, moduleName ) :: otherModules ->
            let
                ( path, fileName ) =
                    readModuleFromDisk packageInfo.path moduleName
            in
            Parsing state otherModules (ReadFile path fileName)

































>







 







>
>
>
>
>
>
>








>




<
<
<
<
<
<
<







 







>
>
>

|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
...
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474







475
476
477
478
479
480
481
...
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
...
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
    }


type alias ParsedModuleInfo =
    { packageName : PackageName
    , modulePath : ModuleName
    , ast : Parser.AST
    , requiredModules : Set String
    }


emptyState : InitOptions -> PackageInfo -> State
emptyState initOptions rootPackage =
    { possibleEntryPoint = initOptions.possibleEntryPoint
    , rootPackage = rootPackage
................................................................................
                ( Just ( packageName, moduleName ), Ok parserAst ) ->
                    let
                        fullModuleName =
                            absoluteModuleName packageName moduleName

                        updatedParsedModules =
                            Set.insert fullModuleName state.parsedModuleNames

                        requiredModules =
                            Qualifier.requiredModules
                                { packageName = PackageName.toString packageName
                                , ast = parserAst
                                , externalModules = state.moduleNameToPackageName
                                }

                        updatedState =
                            { state
                                | parsedModuleNames = updatedParsedModules
                                , parsedModules =
                                    { packageName = packageName
                                    , modulePath = moduleName
                                    , ast = parserAst
                                    , requiredModules = requiredModules
                                    }
                                        :: state.parsedModules
                            }








                        modulesQueuedForOrAlreadyParsed =
                            remainingModules
                                |> List.map (\( pInfo, mName ) -> absoluteModuleName pInfo.metadata.name mName)
                                |> Set.fromList
                                |> Set.union updatedParsedModules

                        missingModulesInParseQueue =
................................................................................


nextCompileStep : List ( PackageInfo, ModuleName ) -> State -> Model
nextCompileStep remainingModules state =
    case remainingModules of
        [] ->
            let
                sortedParsedModules =
                    List.sortWith sortByRequiredModules state.parsedModules

                ( qualifiedAst, errs ) =
                    sortedParsedModules
                        |> List.foldl qualifyAst ( { types = Dict.empty, words = Dict.empty }, [] )

                qualifyAst parsedModInfo ( qast, es ) =
                    let
                        qualifierResult =
                            Qualifier.run
                                { packageName = PackageName.toString parsedModInfo.packageName
................................................................................

        ( packageInfo, moduleName ) :: otherModules ->
            let
                ( path, fileName ) =
                    readModuleFromDisk packageInfo.path moduleName
            in
            Parsing state otherModules (ReadFile path fileName)


sortByRequiredModules : ParsedModuleInfo -> ParsedModuleInfo -> Order
sortByRequiredModules a b =
    let
        aQualifiedName =
            absoluteModuleName a.packageName a.modulePath

        bQualifiedName =
            absoluteModuleName b.packageName b.modulePath

        aRequiredByB =
            Set.member aQualifiedName b.requiredModules

        bRequiredByA =
            Set.member bQualifiedName a.requiredModules
    in
    case ( aRequiredByB, bRequiredByA ) of
        ( True, False ) ->
            LT

        ( False, True ) ->
            GT

        otherwise ->
            EQ

Modified src/Play/Qualifier.elm from [44d7d10703] to [b1f6a34b92].

963
964
965
966
967
968
969



970
971
972
973
974
975
976
            else
                let
                    qualifiedPath =
                        qualifyPackageModule config.packageName normalizedPath

                    qualifiedName =
                        String.join "/" [ qualifiedPath, value ]



                in
                case Dict.get qualifiedName config.inProgressAST.words of
                    Nothing ->
                        { acc | qualifiedNodes = Err (UnknownWordRef loc qualifiedName) :: acc.qualifiedNodes }

                    Just word ->
                        if word.metadata.isExposed then







>
>
>







963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
            else
                let
                    qualifiedPath =
                        qualifyPackageModule config.packageName normalizedPath

                    qualifiedName =
                        String.join "/" [ qualifiedPath, value ]

                    _ =
                        Dict.keys config.inProgressAST.words
                in
                case Dict.get qualifiedName config.inProgressAST.words of
                    Nothing ->
                        { acc | qualifiedNodes = Err (UnknownWordRef loc qualifiedName) :: acc.qualifiedNodes }

                    Just word ->
                        if word.metadata.isExposed then

Modified tests/Test/PackageLoader.elm from [6a7e40be54] to [670203e2f4].

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
..
75
76
77
78
79
80
81












































82
83
84
85
86
87
88
...
228
229
230
231
232
233
234




























235
236
237
238
239
240
241
...
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
...
349
350
351
352
353
354
355










































                        , 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
................................................................................
                                      , metadata = Metadata.default
                                      , implementation =
                                            Qualifier.SoloImpl
                                                [ Qualifier.Integer emptyRange 2
                                                ]
                                      }
                                    ]












































                            }
                            (Util.stripLocations ast)
        , test "Specified entry point is marked as such" <|
            \_ ->
                let
                    loaderResult =
                        PackageLoader.init
................................................................................
        case pathParts of
            [ _, "play.json" ] ->
                True

            _ ->
                False






























testFiles : Dict String String
testFiles =
    Dict.fromList
        [ ( "/project/play.json"
          , """
            {
................................................................................
          )
        , ( "/project/lib/template_strings/src/template_strings/mod.play"
          , """
            def: dec
            : 1 =
            """
          )
        , ( "/project/lib/unused/play.json"
          , """
            {
                "name": "some/useless",
                "version": "1.7.0",
                "language-version": "0.2.0",
                "exposed-modules": [
                    "useless/mod"
                ],
                "dependencies": {
                },
                "package-paths": [
                ]
            }
          """
          )
        , ( "/project/lib/unused/src/useless/mod.play"
          , """
            def: square
            : dup *
            """
          )
        , ( "/project/lib/version/play.json"
          , """
            {
                "name": "play/version",
                "version": "1.0.0",
                "language-version": "0.2.0",
                "exposed-modules": [
................................................................................
        , ( "/project/lib/template_strings/lib/version/src/version/data.play"
          , """
            def: number
            : 2
            """
          )
        ]

















































|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
..
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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
...
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
...
354
355
356
357
358
359
360






















361
362
363
364
365
366
367
...
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
                        , 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 project with external dependencies to qualified AST" <|
            \_ ->
                let
                    loaderResult =
                        PackageLoader.init initOpts
                            |> resolveSideEffects testFiles []
                            |> Result.map Tuple.second
                in
................................................................................
                                      , metadata = Metadata.default
                                      , implementation =
                                            Qualifier.SoloImpl
                                                [ Qualifier.Integer emptyRange 2
                                                ]
                                      }
                                    ]
                            }
                            (Util.stripLocations ast)
        , test "Compiles project with multiple dependant modules to qualified AST" <|
            \_ ->
                let
                    loaderResult =
                        PackageLoader.init initOpts
                            |> resolveSideEffects testFilesInternalConsistency []
                            |> Result.map Tuple.second
                in
                case loaderResult of
                    Err msg ->
                        Expect.fail msg

                    Ok ast ->
                        Expect.equal
                            { types =
                                Dict.fromListBy Qualifier.typeDefinitionName []
                            , words =
                                Dict.fromListBy .name
                                    [ { name = "/robheghan/dummy/mod1/bump-version"
                                      , metadata = Metadata.default
                                      , implementation =
                                            Qualifier.SoloImpl
                                                [ Qualifier.Integer emptyRange 1
                                                , Qualifier.Builtin emptyRange Builtin.Plus
                                                ]
                                      }
                                    , { name = "/robheghan/dummy/mod2/version"
                                      , metadata = Metadata.default
                                      , implementation =
                                            Qualifier.SoloImpl
                                                [ Qualifier.Integer emptyRange 5
                                                ]
                                      }
                                    , { name = "/robheghan/dummy/mod3/next-version"
                                      , metadata = Metadata.default
                                      , implementation =
                                            Qualifier.SoloImpl
                                                [ Qualifier.Word emptyRange "/robheghan/dummy/mod2/version"
                                                , Qualifier.Word emptyRange "/robheghan/dummy/mod1/bump-version"
                                                ]
                                      }
                                    ]
                            }
                            (Util.stripLocations ast)
        , test "Specified entry point is marked as such" <|
            \_ ->
                let
                    loaderResult =
                        PackageLoader.init
................................................................................
        case pathParts of
            [ _, "play.json" ] ->
                True

            _ ->
                False


stdLibFiles : Dict String String
stdLibFiles =
    Dict.fromList
        [ ( "/project/lib/unused/play.json"
          , """
            {
                "name": "some/useless",
                "version": "1.7.0",
                "language-version": "0.2.0",
                "exposed-modules": [
                    "useless/mod"
                ],
                "dependencies": {
                },
                "package-paths": [
                ]
            }
          """
          )
        , ( "/project/lib/unused/src/useless/mod.play"
          , """
            def: square
            : dup *
            """
          )
        ]


testFiles : Dict String String
testFiles =
    Dict.fromList
        [ ( "/project/play.json"
          , """
            {
................................................................................
          )
        , ( "/project/lib/template_strings/src/template_strings/mod.play"
          , """
            def: dec
            : 1 =
            """
          )






















        , ( "/project/lib/version/play.json"
          , """
            {
                "name": "play/version",
                "version": "1.0.0",
                "language-version": "0.2.0",
                "exposed-modules": [
................................................................................
        , ( "/project/lib/template_strings/lib/version/src/version/data.play"
          , """
            def: number
            : 2
            """
          )
        ]
        |> Dict.union stdLibFiles


testFilesInternalConsistency : Dict String String
testFilesInternalConsistency =
    Dict.fromList
        [ ( "/project/play.json"
          , """
            {
                "name": "robheghan/dummy",
                "version": "1.0.0",
                "language-version": "0.2.0",
                "exposed-modules": [
                    "mod1",
                    "mod2",
                    "mod3"
                ],
                "dependencies": {},
                "package-paths": []
            }
            """
          )
        , ( "/project/src/mod1.play"
          , """
            def: bump-version
            : 1 +
            """
          )
        , ( "/project/src/mod2.play"
          , """
            def: version
            : 5
            """
          )
        , ( "/project/src/mod3.play"
          , """
            def: next-version
            : mod2/version mod1/bump-version
            """
          )
        ]
        |> Dict.union stdLibFiles