xguerin / bitstring

OCaml Bitstring - bitstring matching for OCaml
GNU General Public License v2.0
67 stars 8 forks source link

Error matching literal single bits #31

Closed devesascampos closed 1 year ago

devesascampos commented 1 year ago

(Apols in advance if I'm doing something really dumb)

Have (ppx_)bitstring version 4.1.0 on ocaml 4.11.2

<><> bitstring: information on all versions <><><><><><><><><><><><><><><><>  🐫 
name                   bitstring
all-installed-versions 4.1.0 [default]

Trying to match a bitstring bs with a pattern containing/consisting of a single literal bit fails:

# let bs = Bitstring.bitstring_of_string "a";;
val bs : Bitstring.bitstring = (Bytes.of_string "a", 0, 8)
# match%bitstring bs with | {| 0:1 |} -> "working";;
Error: This pattern matches values of type int
       but a pattern was expected which matches values of type bool

(the {| appears underlined)

In fact, something like the pattern_matcher example in documentation.md also fails

# let pattern_matcher = function%bitstring
  | {| 1 : 1
     ; a : 2
     ; b : 16 : bigendian
  |} -> true
  | {| _ |} -> false
  ;;
Error: This pattern matches values of type int
       but a pattern was expected which matches values of type bool

(the {| appears underlined)

Replacing the literal with a variable works

# match%bitstring bs with | {| x:1 |} -> "working";;
- : string = "working"

And then adding a check serves as a workaround to get the original intent

# match%bitstring bs with | {| x:1:check(x = false) |} -> "working";;
- : string = "working"

but is clunky.

devesascampos commented 1 year ago

I understand if this is expected behaviour (and the example is wrong) and I should just use bools

# match%bitstring bs with | {| false:1: |} -> "working";;
- : string = "working"
# match%bitstring bs with | {| true:1: |} -> "working";;
Exception: Match_failure ("//toplevel//", 1, 0).

but to me it strikes me as weird to be able to match 0b01 but not 0b0 particularly when matching longer patterns that contain longer sections of literal bits.

xguerin commented 1 year ago

~Looks like an oversight, thanks for reporting. I'll look into it.~ The documentation is inaccurate. Since the migration to PPX, single-bit values are interpreted as bool. The following does work:

let match_bits_with_expected_values _ =
    (*
     * Create a string of bits.
     *)
    let bits = Bitstring.bitstring_of_string "a" in 
    (*
     * Match expected bits.
     *)
    let actual = match%bitstring bits with
     | {| false:1 ; true:1 ; _ : -1 : bitstring |} -> true
     | {| _ |} -> false
    in
    assert actual
devesascampos commented 1 year ago

Thx for the clarification.