Stabel

Check-in [d9f4e595b8]
Login
Overview
Comment:Happy path implementaton of fully qualified references. Still needs error handling and an integration test.
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: d9f4e595b8c81eafd576e490ef1f258846ad97b1f8be87e29e34700e7505b8c8
User & Date: robin.hansen on 2021-09-25 09:48:42
Other Links: manifest | tags
Context
2021-09-25
12:16
Integration test for fully qualified functions. check-in: 7403f0755f user: robin.hansen tags: trunk
09:48
Happy path implementaton of fully qualified references. Still needs error handling and an integratio... check-in: d9f4e595b8 user: robin.hansen tags: trunk
09:22
Added fully qualified refs as possible outcomes of parsing. Qualifier now handles them correctly. No... check-in: b8ab950864 user: robin.hansen tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Modified src/Stabel/Parser.elm from [6a1081c128] to [cd560c0df7].

581
582
583
584
585
586
587



588
589
590
591
592
593
594
...
602
603
604
605
606
607
608





609
610
611
612
613
614
615
...
629
630
631
632
633
634
635



636
637
638
639
640
641
642
....
1427
1428
1429
1430
1431
1432
1433



















1434
1435
1436
1437
1438
1439
1440
....
1462
1463
1464
1465
1466
1467
1468





1469
1470
1471
1472
1473
1474


typeSignatureRefParser : Parser PossiblyQualifiedType
typeSignatureRefParser =
    Parser.oneOf
        [ Parser.succeed (\name -> LocalRef name [])
            |= typeNameParser



        , Parser.succeed (\( path, name ) -> ExternalRef path name [])
            |. Parser.symbol (Token "/" ExpectedForwardSlash)
            |= Parser.loop [] modularizedTypeRefParser
        , Parser.succeed (\( path, name ) -> InternalRef path name [])
            |= Parser.loop [] modularizedTypeRefParser
        , Parser.succeed Generic
            |= genericParser
................................................................................

typeRefParser : Parser PossiblyQualifiedType
typeRefParser =
    Parser.oneOf
        [ Parser.succeed LocalRef
            |= typeNameParser
            |. noiseParser





            |= Parser.loop [] typeOrGenericParser
        , Parser.succeed (\( path, name ) binds -> ExternalRef path name binds)
            |. Parser.symbol (Token "/" ExpectedForwardSlash)
            |= Parser.loop [] modularizedTypeRefParser
            |. noiseParser
            |= Parser.loop [] typeOrGenericParser
        , Parser.succeed (\( path, name ) binds -> InternalRef path name binds)
................................................................................


typeMatchTypeParser : Parser PossiblyQualifiedType
typeMatchTypeParser =
    Parser.oneOf
        [ Parser.succeed (\name -> LocalRef name [])
            |= typeNameParser



        , Parser.succeed (\( path, name ) -> ExternalRef path name [])
            |. Parser.symbol (Token "/" ExpectedForwardSlash)
            |= Parser.loop [] modularizedTypeRefParser
        , Parser.succeed (\( path, name ) -> InternalRef path name [])
            |= Parser.loop [] modularizedTypeRefParser
        , Parser.succeed Generic
            |= genericParser
................................................................................
            |= sourceLocationParser
        ]


qualifiedSymbolImplParser : Parser (SourceLocationRange -> AstNode)
qualifiedSymbolImplParser =
    let



















        externalBuilder ( path, reference ) =
            if checkForUpperCaseLetterInPath path then
                Parser.problem <| InvalidModulePath <| "/" ++ String.join "/" path

            else if List.length path == 0 then
                Parser.problem <| InvalidModulePath <| "/" ++ String.join "/" path ++ "/" ++ reference

................................................................................

        checkForUpperCaseLetterInPath path =
            List.any (String.any Char.isUpper) path
    in
    Parser.oneOf
        [ Parser.succeed internalBuilder
            |= symbolImplParser





            |= Parser.loop [] modulePathParser
            |> Parser.andThen identity
        , Parser.succeed identity
            |= Parser.loop [] modulePathParser
            |> Parser.andThen externalBuilder
        ]







>
>
>







 







>
>
>
>
>







 







>
>
>







 







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







 







>
>
>
>
>






581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
...
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
...
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
....
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
....
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509


typeSignatureRefParser : Parser PossiblyQualifiedType
typeSignatureRefParser =
    Parser.oneOf
        [ Parser.succeed (\name -> LocalRef name [])
            |= typeNameParser
        , Parser.succeed (\( path, name ) -> FullyQualifiedRef ("/" ++ String.join "/" path ++ "/" ++ name) [])
            |. Parser.symbol (Token "//" ExpectedForwardSlash)
            |= Parser.loop [] modularizedTypeRefParser
        , Parser.succeed (\( path, name ) -> ExternalRef path name [])
            |. Parser.symbol (Token "/" ExpectedForwardSlash)
            |= Parser.loop [] modularizedTypeRefParser
        , Parser.succeed (\( path, name ) -> InternalRef path name [])
            |= Parser.loop [] modularizedTypeRefParser
        , Parser.succeed Generic
            |= genericParser
................................................................................

typeRefParser : Parser PossiblyQualifiedType
typeRefParser =
    Parser.oneOf
        [ Parser.succeed LocalRef
            |= typeNameParser
            |. noiseParser
            |= Parser.loop [] typeOrGenericParser
        , Parser.succeed (\( path, name ) binds -> FullyQualifiedRef ("/" ++ String.join "/" path ++ "/" ++ name) binds)
            |. Parser.symbol (Token "//" ExpectedForwardSlash)
            |= Parser.loop [] modularizedTypeRefParser
            |. noiseParser
            |= Parser.loop [] typeOrGenericParser
        , Parser.succeed (\( path, name ) binds -> ExternalRef path name binds)
            |. Parser.symbol (Token "/" ExpectedForwardSlash)
            |= Parser.loop [] modularizedTypeRefParser
            |. noiseParser
            |= Parser.loop [] typeOrGenericParser
        , Parser.succeed (\( path, name ) binds -> InternalRef path name binds)
................................................................................


typeMatchTypeParser : Parser PossiblyQualifiedType
typeMatchTypeParser =
    Parser.oneOf
        [ Parser.succeed (\name -> LocalRef name [])
            |= typeNameParser
        , Parser.succeed (\( path, name ) -> FullyQualifiedRef ("/" ++ String.join "/" path ++ "/" ++ name) [])
            |. Parser.symbol (Token "//" ExpectedForwardSlash)
            |= Parser.loop [] modularizedTypeRefParser
        , Parser.succeed (\( path, name ) -> ExternalRef path name [])
            |. Parser.symbol (Token "/" ExpectedForwardSlash)
            |= Parser.loop [] modularizedTypeRefParser
        , Parser.succeed (\( path, name ) -> InternalRef path name [])
            |= Parser.loop [] modularizedTypeRefParser
        , Parser.succeed Generic
            |= genericParser
................................................................................
            |= sourceLocationParser
        ]


qualifiedSymbolImplParser : Parser (SourceLocationRange -> AstNode)
qualifiedSymbolImplParser =
    let
        fullyQualifiedBuilder firstPath ( restPath, functionName ) =
            let
                path =
                    firstPath :: restPath

                ref =
                    "/" ++ String.join "/" path ++ "/" ++ functionName
            in
            if checkForUpperCaseLetterInPath path then
                Parser.problem <| InvalidModulePath <| "/" ++ String.join "/" path

            else if List.length path == 0 then
                Parser.problem <| InvalidModulePath <| ref

            else
                Parser.succeed <|
                    \loc ->
                        FullyQualifiedFunction loc ref

        externalBuilder ( path, reference ) =
            if checkForUpperCaseLetterInPath path then
                Parser.problem <| InvalidModulePath <| "/" ++ String.join "/" path

            else if List.length path == 0 then
                Parser.problem <| InvalidModulePath <| "/" ++ String.join "/" path ++ "/" ++ reference

................................................................................

        checkForUpperCaseLetterInPath path =
            List.any (String.any Char.isUpper) path
    in
    Parser.oneOf
        [ Parser.succeed internalBuilder
            |= symbolImplParser
            |= Parser.loop [] modulePathParser
            |> Parser.andThen identity
        , Parser.succeed fullyQualifiedBuilder
            |. Parser.token (Token "//" ExpectedForwardSlash)
            |= symbolImplParser
            |= Parser.loop [] modulePathParser
            |> Parser.andThen identity
        , Parser.succeed identity
            |= Parser.loop [] modulePathParser
            |> Parser.andThen externalBuilder
        ]

Modified tests/Test/Parser.elm from [e6646f0f1b] to [dff1888a3a].

1
2
3
4
5
6
7
8
module Test.Parser exposing (..)

import Dict
import Dict.Extra as Dict
import Expect
import Fuzz exposing (Fuzzer)
import Random
import Stabel.Parser as AST exposing (..)
|







1
2
3
4
5
6
7
8
module Test.Parser exposing (suite)

import Dict
import Dict.Extra as Dict
import Expect
import Fuzz exposing (Fuzzer)
import Random
import Stabel.Parser as AST exposing (..)

Modified tests/Test/Parser/QualifiedRefs.elm from [b5b2da8cf8] to [23a84b652b].

1
2
3
4
5
6
7
8
...
169
170
171
172
173
174
175





























176
177
178
179
180
181
182
...
252
253
254
255
256
257
258













































259
260
261
262
263
264
265
266
267
268
module Test.Parser.QualifiedRefs exposing (..)

import Dict
import Dict.Extra as Dict
import Stabel.Parser as AST exposing (..)
import Stabel.Parser.AssociatedFunctionSignature as AssociatedFunctionSignature
import Stabel.Parser.ModuleDefinition as ModuleDefinition
import Stabel.Parser.SourceLocation exposing (emptyRange)
................................................................................
                                        SoloImpl
                                            [ AST.Function emptyRange "drop"
                                            , AST.Integer emptyRange 1
                                            ]
                                  }
                                ]
                        }





























                in
                expectAst source expectedAst
        , test "External type in multifn" <|
            \_ ->
                let
                    source =
                        """
................................................................................
                                  , implementation =
                                        MultiImpl
                                            [ ( TypeMatchType emptyRange (InternalRef [ "internal" ] "Tipe" []) [ ( "value", TypeMatchInt emptyRange 1 ) ]
                                              , [ AST.Function emptyRange "drop"
                                                , AST.Integer emptyRange 1
                                                ]
                                              )













































                                            ]
                                            [ AST.Function emptyRange "drop"
                                            , AST.Integer emptyRange 0
                                            ]
                                  }
                                ]
                        }
                in
                expectAst source expectedAst
        ]
|







 







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







 







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










1
2
3
4
5
6
7
8
...
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
...
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
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
module Test.Parser.QualifiedRefs exposing (suite)

import Dict
import Dict.Extra as Dict
import Stabel.Parser as AST exposing (..)
import Stabel.Parser.AssociatedFunctionSignature as AssociatedFunctionSignature
import Stabel.Parser.ModuleDefinition as ModuleDefinition
import Stabel.Parser.SourceLocation exposing (emptyRange)
................................................................................
                                        SoloImpl
                                            [ AST.Function emptyRange "drop"
                                            , AST.Integer emptyRange 1
                                            ]
                                  }
                                ]
                        }
                in
                expectAst source expectedAst
        , test "Fully qualified function reference" <|
            \_ ->
                let
                    source =
                        """
                        def: test
                        : //author/package/some/module/sample
                        """

                    expectedAst =
                        { sourceReference = ""
                        , moduleDefinition = ModuleDefinition.Undefined
                        , types = Dict.empty
                        , functions =
                            Dict.fromListBy .name
                                [ { name = "test"
                                  , typeSignature = AssociatedFunctionSignature.NotProvided
                                  , sourceLocationRange = Nothing
                                  , documentation = ""
                                  , aliases = Dict.empty
                                  , imports = Dict.empty
                                  , implementation =
                                        SoloImpl
                                            [ AST.FullyQualifiedFunction emptyRange "/author/package/some/module/sample" ]
                                  }
                                ]
                        }
                in
                expectAst source expectedAst
        , test "External type in multifn" <|
            \_ ->
                let
                    source =
                        """
................................................................................
                                  , implementation =
                                        MultiImpl
                                            [ ( TypeMatchType emptyRange (InternalRef [ "internal" ] "Tipe" []) [ ( "value", TypeMatchInt emptyRange 1 ) ]
                                              , [ AST.Function emptyRange "drop"
                                                , AST.Integer emptyRange 1
                                                ]
                                              )
                                            ]
                                            [ AST.Function emptyRange "drop"
                                            , AST.Integer emptyRange 0
                                            ]
                                  }
                                ]
                        }
                in
                expectAst source expectedAst
        , test "Fully qualified type in multifn" <|
            \_ ->
                let
                    source =
                        """
                        defmulti: test
                        type: //author/package/internal/Tipe -- Int
                        : //author/package/internal/Tipe( value 1 )
                          drop 1
                        else:
                          drop 0
                        """

                    expectedAst =
                        { sourceReference = ""
                        , moduleDefinition = ModuleDefinition.Undefined
                        , types = Dict.empty
                        , functions =
                            Dict.fromListBy .name
                                [ { name = "test"
                                  , typeSignature =
                                        AssociatedFunctionSignature.UserProvided
                                            { input = [ NotStackRange <| FullyQualifiedRef "/author/package/internal/Tipe" [] ]
                                            , output = [ NotStackRange <| LocalRef "Int" [] ]
                                            }
                                  , sourceLocationRange = Nothing
                                  , documentation = ""
                                  , aliases = Dict.empty
                                  , imports = Dict.empty
                                  , implementation =
                                        MultiImpl
                                            [ ( TypeMatchType emptyRange (FullyQualifiedRef "/author/package/internal/Tipe" []) [ ( "value", TypeMatchInt emptyRange 1 ) ]
                                              , [ AST.Function emptyRange "drop"
                                                , AST.Integer emptyRange 1
                                                ]
                                              )
                                            ]
                                            [ AST.Function emptyRange "drop"
                                            , AST.Integer emptyRange 0
                                            ]
                                  }
                                ]
                        }
                in
                expectAst source expectedAst
        ]

Modified tests/Test/Parser/Util.elm from [d2ff50d105] to [f297e9d987].

75
76
77
78
79
80
81



82
83
84
85
86
87
88

        AST.PackageFunction _ path val ->
            AST.PackageFunction emptyRange path val

        AST.ExternalFunction _ path val ->
            AST.ExternalFunction emptyRange path val




        AST.InlineFunction _ val ->
            AST.InlineFunction emptyRange (List.map stripNodeLocation val)

        AST.ArrayLiteral _ val ->
            AST.ArrayLiteral emptyRange (List.map stripNodeLocation val)

        AST.StringLiteral _ val ->







>
>
>







75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

        AST.PackageFunction _ path val ->
            AST.PackageFunction emptyRange path val

        AST.ExternalFunction _ path val ->
            AST.ExternalFunction emptyRange path val

        AST.FullyQualifiedFunction _ ref ->
            AST.FullyQualifiedFunction emptyRange ref

        AST.InlineFunction _ val ->
            AST.InlineFunction emptyRange (List.map stripNodeLocation val)

        AST.ArrayLiteral _ val ->
            AST.ArrayLiteral emptyRange (List.map stripNodeLocation val)

        AST.StringLiteral _ val ->