Stabel

Check-in [9c25d24e88]
Login
Overview
Comment:First attempt at array-get. Has a bug.
Timelines: family | ancestors | descendants | both | arrays
Files: files | file ages | folders
SHA3-256: 9c25d24e885a1d3728cdd4aaa01c492c4860b5158b57c4e1769227aceefe5040
User & Date: robin.hansen on 2021-08-27 08:26:06
Other Links: branch diff | manifest | tags
Context
2021-08-28
07:34
Update test_expression.js, with instructions on how to use it. check-in: 8f6b7a467b user: robin.hansen tags: arrays
2021-08-27
08:26
First attempt at array-get. Has a bug. check-in: 9c25d24e88 user: robin.hansen tags: arrays
2021-08-24
17:21
Implement array-push. check-in: 72850142b1 user: robin.hansen tags: arrays
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Modified src/Stabel/Codegen.elm from [f568b54ec2] to [a7ce3dc66b].

841
842
843
844
845
846
847



848
849
850
851
852
853

                Builtin.ArrayLength ->
                    BaseModule.callArrayLengthFn

                Builtin.ArrayPush ->
                    BaseModule.callArrayPushFn




        Box stackPos id ->
            Wasm.Batch
                [ Wasm.I32_Const stackPos
                , Wasm.I32_Const id
                , BaseModule.callBoxFn
                ]







>
>
>






841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856

                Builtin.ArrayLength ->
                    BaseModule.callArrayLengthFn

                Builtin.ArrayPush ->
                    BaseModule.callArrayPushFn

                Builtin.ArrayGet ->
                    BaseModule.callArrayGetFn

        Box stackPos id ->
            Wasm.Batch
                [ Wasm.I32_Const stackPos
                , Wasm.I32_Const id
                , BaseModule.callBoxFn
                ]

Modified src/Stabel/Codegen/BaseModule.elm from [e2ab26f5c1] to [bbdc76af52].

257
258
259
260
261
262
263










264
265
266
267
268
269
270
...
682
683
684
685
686
687
688
689










690












































callArrayPushFn : Wasm.Instruction
callArrayPushFn =
    Wasm.Call 22 arrayPushFn













-- Base module


baseModule : Wasm.Module
baseModule =
    let
................................................................................
            , Wasm.Local_Get 3
            , Wasm.I32_Store

            -- Return
            , Wasm.Local_Get 2
            , callStackPushFn
            ]
      }










    ]

















































>
>
>
>
>
>
>
>
>
>







 








>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
...
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752


callArrayPushFn : Wasm.Instruction
callArrayPushFn =
    Wasm.Call 22 arrayPushFn


arrayGetFn : String
arrayGetFn =
    "__array_get"


callArrayGetFn : Wasm.Instruction
callArrayGetFn =
    Wasm.Call 23 arrayGetFn



-- Base module


baseModule : Wasm.Module
baseModule =
    let
................................................................................
            , Wasm.Local_Get 3
            , Wasm.I32_Store

            -- Return
            , Wasm.Local_Get 2
            , callStackPushFn
            ]
      }
    , { id = 23
      , name = arrayGetFn
      , args = []
      , results = []
      , locals = [ Wasm.Int32, Wasm.Int32 ]
      , instructions =
            [ callStackPopFn
            , Wasm.Local_Set 0 -- index to get
            , callStackPopFn
            , Wasm.Local_Set 1 -- array

            -- check for negative index
            , Wasm.Local_Get 0
            , Wasm.I32_Const 0
            , Wasm.I32_LT
            , Wasm.If
                [ Wasm.I32_Const 0
                , Wasm.I32_Const 0
                , callStackPushFn
                , callStackPushFn
                , Wasm.Return
                ]
                []

            -- Check for index too large
            , Wasm.Local_Get 0
            , Wasm.Local_Get 1
            , Wasm.I32_Load -- length of index
            , Wasm.I32_LT
            , Wasm.If
                [ Wasm.I32_Const 0
                , Wasm.I32_Const 0
                , callStackPushFn
                , callStackPushFn
                , Wasm.Return
                ]
                []

            -- Get element at index
            , Wasm.Local_Get 1
            , Wasm.I32_Const wasmPtrSize
            , Wasm.I32_Add -- move pointer beyond length
            , Wasm.Local_Get 0
            , Wasm.I32_Const wasmPtrSize
            , Wasm.I32_Mul -- offset
            , Wasm.I32_Add -- starting position + offset = ptr to element
            , Wasm.I32_Load -- element to return
            , Wasm.I32_Const 1 -- success flag
            , callStackPushFn
            , callStackPushFn
            ]
      }
    ]

Modified src/Stabel/Data/Builtin.elm from [272a506fbc] to [8788cd1d69].

17
18
19
20
21
22
23

24
25
26
27
28
29
30
..
97
98
99
100
101
102
103





    | StackSwap
    | StackRightRotate
    | StackLeftRotate
    | Apply
    | ArrayEmpty
    | ArrayLength
    | ArrayPush



functionType : Builtin -> FunctionType
functionType builtin =
    case builtin of
        Plus ->
            { input = [ Type.Int, Type.Int ]
................................................................................
            , output = [ Type.Int ]
            }

        ArrayPush ->
            { input = [ Type.Array (Type.Generic "a"), Type.Generic "a" ]
            , output = [ Type.Array (Type.Generic "a") ]
            }












>







 







>
>
>
>
>
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
..
98
99
100
101
102
103
104
105
106
107
108
109
    | StackSwap
    | StackRightRotate
    | StackLeftRotate
    | Apply
    | ArrayEmpty
    | ArrayLength
    | ArrayPush
    | ArrayGet


functionType : Builtin -> FunctionType
functionType builtin =
    case builtin of
        Plus ->
            { input = [ Type.Int, Type.Int ]
................................................................................
            , output = [ Type.Int ]
            }

        ArrayPush ->
            { input = [ Type.Array (Type.Generic "a"), Type.Generic "a" ]
            , output = [ Type.Array (Type.Generic "a") ]
            }

        ArrayGet ->
            { input = [ Type.Array (Type.Generic "a"), Type.Int ]
            , output = [ Type.Int, Type.Generic "a" ]
            }

Modified src/Stabel/Qualifier.elm from [dfb6e3993b] to [7624a204a9].

118
119
120
121
122
123
124

125
126
127
128
129
130
131
        , ( "dup", Builtin.StackDuplicate )
        , ( "drop", Builtin.StackDrop )
        , ( "rotate", Builtin.StackRightRotate )
        , ( "-rotate", Builtin.StackLeftRotate )
        , ( "!", Builtin.Apply )
        , ( "array-length", Builtin.ArrayLength )
        , ( "array-push", Builtin.ArrayPush )

        ]


type alias RunConfig =
    { packageName : String
    , modulePath : String
    , ast : Parser.AST







>







118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
        , ( "dup", Builtin.StackDuplicate )
        , ( "drop", Builtin.StackDrop )
        , ( "rotate", Builtin.StackRightRotate )
        , ( "-rotate", Builtin.StackLeftRotate )
        , ( "!", Builtin.Apply )
        , ( "array-length", Builtin.ArrayLength )
        , ( "array-push", Builtin.ArrayPush )
        , ( "array-get", Builtin.ArrayGet )
        ]


type alias RunConfig =
    { packageName : String
    , modulePath : String
    , ast : Parser.AST

Modified src/Stabel/Wasm.elm from [9d9b871b9d] to [0c24fd4e9e].

75
76
77
78
79
80
81

82
83
84
85
86
87
88
..
91
92
93
94
95
96
97

98
99
100
101
102
103
104
...
351
352
353
354
355
356
357


















358
359
360
361
362
363
364
...
399
400
401
402
403
404
405



406
407
408
409
410
411
412

type Instruction
    = Batch (List Instruction)
    | Block (List Instruction)
    | Loop (List Instruction)
    | Break Int
    | BreakIf Int

    | Return
    | Call Int String
    | CallIndirect
    | Local_Get Int
    | Local_Set Int
    | Local_Tee Int
    | I32_Const Int
................................................................................
    | I32_Mul
    | I32_Div
    | I32_Eq
    | I32_NotEq
    | I32_EqZero
    | I32_Store
    | I32_Load

    | Drop
    | Unreachable
    | Commented String Instruction
    | Memory_Copy


maximumLocalIndex : Instruction -> Maybe Int
................................................................................

        Break num ->
            Str <| "(br " ++ String.fromInt num ++ ")"

        BreakIf num ->
            Str <| "(br_if " ++ String.fromInt num ++ ")"



















        Return ->
            Str "return"

        Call id fnName ->
            Str <| "(call " ++ String.fromInt id ++ ") ;; $" ++ fnName

        CallIndirect ->
................................................................................

        I32_Store ->
            Str "i32.store"

        I32_Load ->
            Str "i32.load"




        Drop ->
            Str "drop"

        Unreachable ->
            Str "unreachable"

        Commented comment inst ->







>







 







>







 







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







 







>
>
>







75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
..
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
...
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
...
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435

type Instruction
    = Batch (List Instruction)
    | Block (List Instruction)
    | Loop (List Instruction)
    | Break Int
    | BreakIf Int
    | If (List Instruction) (List Instruction)
    | Return
    | Call Int String
    | CallIndirect
    | Local_Get Int
    | Local_Set Int
    | Local_Tee Int
    | I32_Const Int
................................................................................
    | I32_Mul
    | I32_Div
    | I32_Eq
    | I32_NotEq
    | I32_EqZero
    | I32_Store
    | I32_Load
    | I32_LT
    | Drop
    | Unreachable
    | Commented String Instruction
    | Memory_Copy


maximumLocalIndex : Instruction -> Maybe Int
................................................................................

        Break num ->
            Str <| "(br " ++ String.fromInt num ++ ")"

        BreakIf num ->
            Str <| "(br_if " ++ String.fromInt num ++ ")"

        If thenIns elseIns ->
            if List.isEmpty elseIns then
                BatchFormat
                    [ Str "(if (then"
                    , Indent <| List.map formatInstruction thenIns
                    , Str "))"
                    ]

            else
                BatchFormat
                    [ Str "(if (then"
                    , Indent <| List.map formatInstruction thenIns
                    , Str ")"
                    , Str "(else"
                    , Indent <| List.map formatInstruction elseIns
                    , Str "))"
                    ]

        Return ->
            Str "return"

        Call id fnName ->
            Str <| "(call " ++ String.fromInt id ++ ") ;; $" ++ fnName

        CallIndirect ->
................................................................................

        I32_Store ->
            Str "i32.store"

        I32_Load ->
            Str "i32.load"

        I32_LT ->
            Str "i32.lt_s"

        Drop ->
            Str "drop"

        Unreachable ->
            Str "unreachable"

        Commented comment inst ->

Modified wasm_tests/array.test.js from [481f95590d] to [0708b0e372].

32
33
34
35
36
37
38















































































    `);

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

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























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
    `);

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

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

test('Get first', async () => {
    const wat = await compiler.toWat('main', `
        def: main
        : { 5 6 7 }
          0 array-get
          swap drop
    `);

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

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

test('Get second', async () => {
    const wat = await compiler.toWat('main', `
        def: main
        : { 5 6 7 }
          1 array-get
          swap drop
    `);

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

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

test('Get last', async () => {
    const wat = await compiler.toWat('main', `
        def: main
        : { 5 6 7 }
          2 array-get
          swap drop
    `);

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

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

test('Get succeess', async () => {
    const wat = await compiler.toWat('main', `
        def: main
        : { 5 6 7 }
          2 array-get
          drop
    `);

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

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

test('Get out of lower bound', async () => {
    const wat = await compiler.toWat('main', `
        def: main
        : { 5 6 7 }
          0 1 -
          array-get
          drop
    `);

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

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

test('Get out of lower bound', async () => {
    const wat = await compiler.toWat('main', `
        def: main
        : { 5 6 7 }
          5 array-get
          drop
    `);

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

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