It seems to me one ought to be able to process binary data with DCGs on a list of bytes. To make it work generally, though, one has to use bitwise operations which means is/2
is involved, which means instantiation order is an issue, which may confound using DCGs to both parse and generate. The idea here is to serialize/deserialize binary data but I think this example is simple enough to illustrate the problem.
Let me illustrate with some code. Suppose I have a binary protocol. I want to read two 4-bit integers from a byte. My naive self tries this:
two_four_bit_ints(High, Low) -->
[B],
{
High is B >> 4,
Low is B /\ 0xF
}.
This seems to work for parsing:
?- phrase(two_four_bit_ints(H,L), [255]).
H = L, L = 15.
?- phrase(two_four_bit_ints(H,L), [0]).
H = L, L = 0.
?- phrase(two_four_bit_ints(H,L), [15]).
H = 0,
L = 15.
?- phrase(two_four_bit_ints(H,L), [240]).
H = 15,
L = 0.
But this is not going to generate:
?- phrase(two_four_bit_ints(15,15), [X]).
ERROR: is/2: Arguments are not sufficiently instantiated
?- phrase(two_four_bit_ints(15,15), X).
ERROR: is/2: Arguments are not sufficiently instantiated
Not sure what to do. I'm bracing for someone to shout "Use clpfd
" but it does not appear to support bit shift operations, and I'd be concerned about the performance effect of invoking such a powerful system in the middle of low-level code.
Since I don't see a lot of helpers for binary around, is there some other more preferred way of doing binary extraction/encoding in Prolog? I'm only using SWI for now so I'm happy to accept suggestions that are not portable to ISO, but if it is portable that's nice too. I was rather hoping to find someone had ported something like Erlang's bit syntax but didn't have any luck searching.