Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend language with do notation #257

Open
TravisCardwell opened this issue Nov 7, 2024 · 0 comments
Open

Extend language with do notation #257

TravisCardwell opened this issue Nov 7, 2024 · 0 comments
Labels
enhancement New feature or request

Comments

@TravisCardwell
Copy link
Collaborator

We could generate code that is easier to read if we use do notation.

This topic came up during implementation of the preprocessor backend, as an alternative to long infix operator chains that resulted in extremely long lines. We ended up implementing special-case formatting for these, however, so that particular issue is resolved.

>> Example

Using a do block would produce code that is more like what users would write by hand.

Current
instance F.Storable CPrimitive where

  ...

  poke =
    \x0 ->
      \x1 ->
        case x1 of
          MkCPrimitive
            cPrimitive_c2
            cPrimitive_sc3
            cPrimitive_uc4
            cPrimitive_s5
            cPrimitive_si6
            cPrimitive_ss7
            cPrimitive_ssi8
            cPrimitive_us9
            cPrimitive_usi10
            cPrimitive_i11
            cPrimitive_s212
            cPrimitive_si213
            cPrimitive_u14
            cPrimitive_ui15
            cPrimitive_l16
            cPrimitive_li17
            cPrimitive_sl18
            cPrimitive_sli19
            cPrimitive_ul20
            cPrimitive_uli21
            cPrimitive_ll22
            cPrimitive_lli23
            cPrimitive_sll24
            cPrimitive_slli25
            cPrimitive_ull26
            cPrimitive_ulli27
            cPrimitive_f28
            cPrimitive_d29
            cPrimitive_ld30 ->
                 F.pokeByteOff x0 0 cPrimitive_c2
              >> F.pokeByteOff x0 8 cPrimitive_sc3
              >> F.pokeByteOff x0 16 cPrimitive_uc4
              >> F.pokeByteOff x0 32 cPrimitive_s5
              >> F.pokeByteOff x0 48 cPrimitive_si6
              >> F.pokeByteOff x0 64 cPrimitive_ss7
              >> F.pokeByteOff x0 80 cPrimitive_ssi8
              >> F.pokeByteOff x0 96 cPrimitive_us9
              >> F.pokeByteOff x0 112 cPrimitive_usi10
              >> F.pokeByteOff x0 128 cPrimitive_i11
              >> F.pokeByteOff x0 160 cPrimitive_s212
              >> F.pokeByteOff x0 192 cPrimitive_si213
              >> F.pokeByteOff x0 224 cPrimitive_u14
              >> F.pokeByteOff x0 256 cPrimitive_ui15
              >> F.pokeByteOff x0 320 cPrimitive_l16
              >> F.pokeByteOff x0 384 cPrimitive_li17
              >> F.pokeByteOff x0 448 cPrimitive_sl18
              >> F.pokeByteOff x0 512 cPrimitive_sli19
              >> F.pokeByteOff x0 576 cPrimitive_ul20
              >> F.pokeByteOff x0 640 cPrimitive_uli21
              >> F.pokeByteOff x0 704 cPrimitive_ll22
              >> F.pokeByteOff x0 768 cPrimitive_lli23
              >> F.pokeByteOff x0 832 cPrimitive_sll24
              >> F.pokeByteOff x0 896 cPrimitive_slli25
              >> F.pokeByteOff x0 960 cPrimitive_ull26
              >> F.pokeByteOff x0 1024 cPrimitive_ulli27
              >> F.pokeByteOff x0 1088 cPrimitive_f28
              >> F.pokeByteOff x0 1152 cPrimitive_d29
              >> F.pokeByteOff x0 1280 cPrimitive_ld30
Suggestion
instance F.Storable CPrimitive where

  ...

  poke =
    \x0 ->
      \x1 ->
        case x1 of
          MkCPrimitive
            cPrimitive_c2
            cPrimitive_sc3
            cPrimitive_uc4
            cPrimitive_s5
            cPrimitive_si6
            cPrimitive_ss7
            cPrimitive_ssi8
            cPrimitive_us9
            cPrimitive_usi10
            cPrimitive_i11
            cPrimitive_s212
            cPrimitive_si213
            cPrimitive_u14
            cPrimitive_ui15
            cPrimitive_l16
            cPrimitive_li17
            cPrimitive_sl18
            cPrimitive_sli19
            cPrimitive_ul20
            cPrimitive_uli21
            cPrimitive_ll22
            cPrimitive_lli23
            cPrimitive_sll24
            cPrimitive_slli25
            cPrimitive_ull26
            cPrimitive_ulli27
            cPrimitive_f28
            cPrimitive_d29
            cPrimitive_ld30 -> do
              F.pokeByteOff x0 0 cPrimitive_c2
              F.pokeByteOff x0 8 cPrimitive_sc3
              F.pokeByteOff x0 16 cPrimitive_uc4
              F.pokeByteOff x0 32 cPrimitive_s5
              F.pokeByteOff x0 48 cPrimitive_si6
              F.pokeByteOff x0 64 cPrimitive_ss7
              F.pokeByteOff x0 80 cPrimitive_ssi8
              F.pokeByteOff x0 96 cPrimitive_us9
              F.pokeByteOff x0 112 cPrimitive_usi10
              F.pokeByteOff x0 128 cPrimitive_i11
              F.pokeByteOff x0 160 cPrimitive_s212
              F.pokeByteOff x0 192 cPrimitive_si213
              F.pokeByteOff x0 224 cPrimitive_u14
              F.pokeByteOff x0 256 cPrimitive_ui15
              F.pokeByteOff x0 320 cPrimitive_l16
              F.pokeByteOff x0 384 cPrimitive_li17
              F.pokeByteOff x0 448 cPrimitive_sl18
              F.pokeByteOff x0 512 cPrimitive_sli19
              F.pokeByteOff x0 576 cPrimitive_ul20
              F.pokeByteOff x0 640 cPrimitive_uli21
              F.pokeByteOff x0 704 cPrimitive_ll22
              F.pokeByteOff x0 768 cPrimitive_lli23
              F.pokeByteOff x0 832 cPrimitive_sll24
              F.pokeByteOff x0 896 cPrimitive_slli25
              F.pokeByteOff x0 960 cPrimitive_ull26
              F.pokeByteOff x0 1024 cPrimitive_ulli27
              F.pokeByteOff x0 1088 cPrimitive_f28
              F.pokeByteOff x0 1152 cPrimitive_d29
              F.pokeByteOff x0 1280 cPrimitive_ld30

<*> Example

Applicative construction (pure MkCFoo <*> peekByteOff x0 0 <*> ...) is generally not good for maintenance because the constructor arguments are specified by order. When arguments are added/changed/deleted, it can be easy to make mistakes that lead to bugs. I generally write do blocks where each argument is bound to the field name, and RecordWildCards is used to return the constructed value. In our case, use of applicative construction is not an issue because the code is generated and such changes/maintenance is therefore automated. Binding to field names, however, makes it very easy for users to confirm offsets in the example below.

Current
instance F.Storable CPrimitive where

  ...

  peek =
    \x0 ->
          pure MkCPrimitive
      <*> F.peekByteOff x0 0
      <*> F.peekByteOff x0 8
      <*> F.peekByteOff x0 16
      <*> F.peekByteOff x0 32
      <*> F.peekByteOff x0 48
      <*> F.peekByteOff x0 64
      <*> F.peekByteOff x0 80
      <*> F.peekByteOff x0 96
      <*> F.peekByteOff x0 112
      <*> F.peekByteOff x0 128
      <*> F.peekByteOff x0 160
      <*> F.peekByteOff x0 192
      <*> F.peekByteOff x0 224
      <*> F.peekByteOff x0 256
      <*> F.peekByteOff x0 320
      <*> F.peekByteOff x0 384
      <*> F.peekByteOff x0 448
      <*> F.peekByteOff x0 512
      <*> F.peekByteOff x0 576
      <*> F.peekByteOff x0 640
      <*> F.peekByteOff x0 704
      <*> F.peekByteOff x0 768
      <*> F.peekByteOff x0 832
      <*> F.peekByteOff x0 896
      <*> F.peekByteOff x0 960
      <*> F.peekByteOff x0 1024
      <*> F.peekByteOff x0 1088
      <*> F.peekByteOff x0 1152
      <*> F.peekByteOff x0 1280

  ...
Suggestion
instance F.Storable CPrimitive where

  ...

  peek =
    \x0 -> do
      cPrimitive_c2 <- F.peekByteOff x0 0
      cPrimitive_sc3 <- F.peekByteOff x0 8
      cPrimitive_uc4 <- F.peekByteOff x0 16
      cPrimitive_s5 <- F.peekByteOff x0 32
      cPrimitive_si6 <- F.peekByteOff x0 48
      cPrimitive_ss7 <- F.peekByteOff x0 64
      cPrimitive_ssi8 <- F.peekByteOff x0 80
      cPrimitive_us9 <- F.peekByteOff x0 96
      cPrimitive_usi10 <- F.peekByteOff x0 112
      cPrimitive_i11 <- F.peekByteOff x0 128
      cPrimitive_s212 <- F.peekByteOff x0 160
      cPrimitive_si213 <- F.peekByteOff x0 192
      cPrimitive_u14 <- F.peekByteOff x0 224
      cPrimitive_ui15 <- F.peekByteOff x0 256
      cPrimitive_l16 <- F.peekByteOff x0 320
      cPrimitive_li17 <- F.peekByteOff x0 384
      cPrimitive_sl18 <- F.peekByteOff x0 448
      cPrimitive_sli19 <- F.peekByteOff x0 512
      cPrimitive_ul20 <- F.peekByteOff x0 576
      cPrimitive_uli21 <- F.peekByteOff x0 640
      cPrimitive_ll22 <- F.peekByteOff x0 704
      cPrimitive_lli23 <- F.peekByteOff x0 768
      cPrimitive_sll24 <- F.peekByteOff x0 832
      cPrimitive_slli25 <- F.peekByteOff x0 896
      cPrimitive_ull26 <- F.peekByteOff x0 960
      cPrimitive_ulli27 <- F.peekByteOff x0 1024
      cPrimitive_f28 <- F.peekByteOff x0 1088
      cPrimitive_d29 <- F.peekByteOff x0 1152
      cPrimitive_ld30 <- F.peekByteOff x0 1280
      pure MkCPrimitive{..}

  ...
@TravisCardwell TravisCardwell added the enhancement New feature or request label Nov 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant