[Template-haskell] TH question
Tim Newsham
newsham at lava.net
Wed Jan 18 20:27:50 EST 2006
Hi, I have yet to write anything in TH, although I've been toying with
it a little bit and asking some questions on IRC. I have come across
a problem that doesn't seem to have a good solution without using
some sort of preprocessor. I want to take a simple spec and generate
some marshalling code using a straighforward transformation.
The spec should look something like:
> $(declPkt "ip" [
> ("Word8", "v_hl", "0x45"),
> ("Word8", "tos", "0"),
> ("Word16", "len", "0"),
> ("Word16", "id", "0"),
> ("Word16", "off", "0"),
> ("Word8", "ttl", "64"),
> ("Word8", "p", "6"),
> ("Word16", "sum", "0"),
> ("Word32", "src", "0"),
> ("Word32", "dst", "0")])
and should generate something like:
> data IP = IP {
> ip_v_hl :: Word8,
> ip_tos :: Word8,
> ip_len :: Word16,
> ip_id :: Word16,
> ip_off :: Word16,
> ip_ttl :: Word8,
> ip_p :: Word8,
> ip_sum :: Word16,
> ip_src :: Word32,
> ip_dst :: Word32
> } deriving Show
> newIP = IP 0x45 0 20 0 0 64 6 0 0 0
>
> instance ByteContainer IP where
> getByteAt b 0 = getByteAt (ip_v_hl b) 0
> getByteAt b 1 = getByteAt (ip_tos b) 0
> getByteAt b 2 = getByteAt (ip_len b) 0
> getByteAt b 3 = getByteAt (ip_len b) 1
> getByteAt b 4 = getByteAt (ip_id b) 0
> getByteAt b 5 = getByteAt (ip_id b) 1
> getByteAt b 6 = getByteAt (ip_off b) 0
> getByteAt b 7 = getByteAt (ip_off b) 1
> getByteAt b 8 = getByteAt (ip_ttl b) 0
> getByteAt b 9 = getByteAt (ip_p b) 0
> getByteAt b 10 = getByteAt (ip_sum b) 0
> getByteAt b 11 = getByteAt (ip_sum b) 1
> getByteAt b 12 = getByteAt (ip_src b) 0
> getByteAt b 13 = getByteAt (ip_src b) 1
> getByteAt b 14 = getByteAt (ip_src b) 2
> getByteAt b 15 = getByteAt (ip_src b) 3
> getByteAt b 16 = getByteAt (ip_dst b) 0
> getByteAt b 17 = getByteAt (ip_dst b) 1
> getByteAt b 18 = getByteAt (ip_dst b) 2
> getByteAt b 19 = getByteAt (ip_dst b) 3
>
> containerLength b = 20
>
> makeContainer b = IP {
> ip_v_hl = makeContainer (Slice b 0),
> ip_tos = makeContainer (Slice b 1),
> ip_len = makeContainer (Slice b 2),
> ip_id = makeContainer (Slice b 4),
> ip_off = makeContainer (Slice b 6),
> ip_ttl = makeContainer (Slice b 8),
> ip_p = makeContainer (Slice b 9),
> ip_sum = makeContainer (Slice b 10),
> ip_src = makeContainer (Slice b 12),
> ip_dst = makeContainer (Slice b 16)
> }
This definitely looks feasible using TH. However, it looks like I
might have to mess with ASTs manually.
My questions is -- is there an easy way to perform this transformation
making use of quasi-quotes for much of the code, or will it be necessary
to construct all of the ASTs manually?
This seems like something that should have a fairly simple solution but
so far I haven't been able to come up with one :(.
Tim Newsham
http://www.lava.net/~newsham/
More information about the template-haskell
mailing list