Play

Check-in [7e7304568b]
Login
Overview
Comment:Codegen now compiles multiwords with a default branch.
Timelines: family | ancestors | descendants | both | unions
Files: files | file ages | folders
SHA3-256: 7e7304568b5f33325e2ef355c5e8a7269763b9a45d7198b88e700ba28f9c071a
User & Date: robin.hansen on 2020-04-25 13:31:18
Other Links: branch diff | manifest | tags
Context
2020-04-29
15:56
Type checker now correctly infers output values of a multi word. check-in: 4f532ab8e0 user: robin.hansen tags: unions
2020-04-25
13:31
Codegen now compiles multiwords with a default branch. check-in: 7e7304568b user: robin.hansen tags: unions
12:08
Type check default implentation of a multiword. check-in: 84f06fbbd8 user: robin.hansen tags: unions
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Modified src/Play/Codegen.elm from [ad20f97718] to [e4283e3851].

432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
...
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
...
489
490
491
492
493
494
495

496
497
498
499
500
501
502

toWasmFuncDef : Dict String TypeInformation -> AST.WordDefinition -> Wasm.FunctionDef
toWasmFuncDef typeInfo def =
    let
        wasmImplementation =
            case def.implementation of
                AST.MultiImpl whens defaultImpl ->
                    [ multiFnToInstructions typeInfo whens ]

                AST.SoloImpl impl ->
                    List.map (nodeToInstruction typeInfo) impl

        numberOfLocals =
            List.filterMap Wasm.maximumLocalIndex wasmImplementation
                |> List.maximum
................................................................................
    , args = []
    , results = []
    , locals = List.repeat numberOfLocals Wasm.Int32
    , instructions = wasmImplementation
    }


multiFnToInstructions : Dict String TypeInformation -> List ( Type, List AST.AstNode ) -> Wasm.Instruction
multiFnToInstructions typeInfo whens =
    let
        branches =
            List.foldl buildBranch (Wasm.Batch []) whens

        buildBranch ( type_, nodes ) ins =
            let
                typeId =
................................................................................
        [ Wasm.Call stackPopFn -- TODO: This only works for arity 0 words.
        , Wasm.Local_Tee 0
        , Wasm.Local_Get 0
        , Wasm.Call stackPushFn -- TODO: should probably have a way of _just_ reading values from stack
        , Wasm.I32_Load
        , Wasm.Local_Set 0 -- store instance id in local
        , branches

        ]


nodeToInstruction : Dict String TypeInformation -> AST.AstNode -> Wasm.Instruction
nodeToInstruction typeInfo node =
    case node of
        AST.IntLiteral value ->







|







 







|
|







 







>







432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
...
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
...
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503

toWasmFuncDef : Dict String TypeInformation -> AST.WordDefinition -> Wasm.FunctionDef
toWasmFuncDef typeInfo def =
    let
        wasmImplementation =
            case def.implementation of
                AST.MultiImpl whens defaultImpl ->
                    [ multiFnToInstructions typeInfo whens defaultImpl ]

                AST.SoloImpl impl ->
                    List.map (nodeToInstruction typeInfo) impl

        numberOfLocals =
            List.filterMap Wasm.maximumLocalIndex wasmImplementation
                |> List.maximum
................................................................................
    , args = []
    , results = []
    , locals = List.repeat numberOfLocals Wasm.Int32
    , instructions = wasmImplementation
    }


multiFnToInstructions : Dict String TypeInformation -> List ( Type, List AST.AstNode ) -> List AST.AstNode -> Wasm.Instruction
multiFnToInstructions typeInfo whens defaultImpl =
    let
        branches =
            List.foldl buildBranch (Wasm.Batch []) whens

        buildBranch ( type_, nodes ) ins =
            let
                typeId =
................................................................................
        [ Wasm.Call stackPopFn -- TODO: This only works for arity 0 words.
        , Wasm.Local_Tee 0
        , Wasm.Local_Get 0
        , Wasm.Call stackPushFn -- TODO: should probably have a way of _just_ reading values from stack
        , Wasm.I32_Load
        , Wasm.Local_Set 0 -- store instance id in local
        , branches
        , Wasm.Batch (List.map (nodeToInstruction typeInfo) defaultImpl)
        ]


nodeToInstruction : Dict String TypeInformation -> AST.AstNode -> Wasm.Instruction
nodeToInstruction typeInfo node =
    case node of
        AST.IntLiteral value ->

Modified src/Play/TypeChecker.elm from [55b1315c90] to [5f19850904].

545
546
547
548
549
550
551
552
553
554
555
556
557
558
559

560







561
562
563





564



565
566
567
568
569
570
571

        -- Both types are either a resolved type or bound generic
        ( Just boundA, Just boundB ) ->
            if boundA == boundB then
                ( context, True )

            else
                let
                    stillCompatible =
                        case ( boundA, boundB ) of
                            ( Type.Union unionTypes, _ ) ->
                                List.member boundB unionTypes

                            ( _, Type.Union unionTypes ) ->
                                List.member boundA unionTypes









                            _ ->
                                False
                in





                ( context, stillCompatible )





getGenericBinding : Context -> Type -> Maybe Type
getGenericBinding context type_ =
    case type_ of
        Type.Generic genericId ->
            case Dict.get genericId context.boundGenerics of







<
<
|
|
|

|
|
>

>
>
>
>
>
>
>
|
|
|
>
>
>
>
>
|
>
>
>







545
546
547
548
549
550
551


552
553
554
555
556
557
558
559
560
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

        -- Both types are either a resolved type or bound generic
        ( Just boundA, Just boundB ) ->
            if boundA == boundB then
                ( context, True )

            else


                case ( boundA, boundB ) of
                    ( Type.Union unionTypes, _ ) ->
                        ( context, List.member boundB unionTypes )

                    ( _, Type.Union unionTypes ) ->
                        if List.member boundA unionTypes then
                            ( context, True )

                        else
                            let
                                isGeneric t =
                                    case t of
                                        Type.Generic _ ->
                                            True

                                        _ ->
                                            False
                            in
                            case List.find isGeneric unionTypes of
                                Just generic ->
                                    compatibleTypes context typeA generic

                                Nothing ->
                                    ( context, False )

                    _ ->
                        ( context, False )


getGenericBinding : Context -> Type -> Maybe Type
getGenericBinding context type_ =
    case type_ of
        Type.Generic genericId ->
            case Dict.get genericId context.boundGenerics of

Modified tests/Test/TypeChecker.elm from [04381ef340] to [b992e9b684].

438
439
440
441
442
443
444


























445
446
447
448
449
450
451
                        input =
                            template
                                { name = "to-int"
                                , metadata =
                                    Metadata.default
                                        |> Metadata.withType [ Type.Custom "Bool" ] [ Type.Int ]
                                , implementation =


























                                    QAST.MultiImpl
                                        [ ( Type.Custom "False"
                                          , [ QAST.Builtin Builtin.StackDrop
                                            , QAST.Integer 0
                                            ]
                                          )
                                        ]







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







438
439
440
441
442
443
444
445
446
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
                        input =
                            template
                                { name = "to-int"
                                , metadata =
                                    Metadata.default
                                        |> Metadata.withType [ Type.Custom "Bool" ] [ Type.Int ]
                                , implementation =
                                    QAST.MultiImpl
                                        [ ( Type.Custom "False"
                                          , [ QAST.Builtin Builtin.StackDrop
                                            , QAST.Integer 0
                                            ]
                                          )
                                        ]
                                        [ QAST.Builtin Builtin.StackDrop
                                        , QAST.Integer 1
                                        ]
                                }
                    in
                    case typeCheck input of
                        Err () ->
                            Expect.fail "Did not expect type check to fail."

                        Ok _ ->
                            Expect.pass
            , test "With default branch (no type meta)" <|
                \_ ->
                    let
                        input =
                            template
                                { name = "to-int"
                                , metadata = Metadata.default
                                , implementation =
                                    QAST.MultiImpl
                                        [ ( Type.Custom "False"
                                          , [ QAST.Builtin Builtin.StackDrop
                                            , QAST.Integer 0
                                            ]
                                          )
                                        ]

Modified wasm_tests/multifn.test.js from [8f8c9b0cfd] to [562aebf87c].

36
37
38
39
40
41
42
43


44
45
46
47
48
49
50
        defmulti: to-int
        when: True
            drop 100
        : drop 75

        def: main
        entry: true
        : >True to-int >False to-int -


    `);

    const result = await compiler.run(wat, 'main');

    expect(result.stackElement()).toBe(25);
});








|
>
>







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
        defmulti: to-int
        when: True
            drop 100
        : drop 75

        def: main
        entry: true
        : >True to-int 
          >False to-int 
          -
    `);

    const result = await compiler.run(wat, 'main');

    expect(result.stackElement()).toBe(25);
});