[mercury-users] Bit-fields in Mercury

Peter Moulder Peter.Moulder at infotech.monash.edu.au
Sun Jul 9 14:22:24 AEST 2006


You can have one or two opaque types to represent bits, with:

  :- interface.
  :- type my_bitfield.
  :- type my_option == my_bitfield.
  % Or can keep my_option as another opaque type, especially
  % if using list notation instead of ‘\/’ (see below).
  :- func opt1 = my_option.
  ...
  :- func my_bitfield `\/` my_bitfield = my_bitfield.

  :- pred fold(pred(my_option, A, A), my_bitfield, A, A).
  :- mode fold(pred(in, in, out) is det, in, in, out) is det
  % or whatever modes you need.

  :- pred my_option `member` my_bitmap.
  :- mode in `member` in is semidet.

  :- implementation.
  :- type my_bitfield == int.

  X `\/` Y = X `'int.\/'` Y.

  Opt `member` Field :-
  	Opt /\ Field \= 0.

  fold(Pred, Opts, !Acc):-
  	( if Opts = 0 then
		true
	 else
	 	Rest_opts = Opts /\ (Opts - 1),
		Low_opt = Opts - Rest_opts,
		Pred(Low_opt, !Acc),
		fold(Pred, Rest_opts, !Acc)
	).

(All code untested, but you get the idea.)

If you want the ‘out `member` out is nondet’ mode too,
then *see (mercury_ref)Different clauses for different modes.
Suggested code:

  :- pragma promise_pure(member/2).
  % Mercury 0.13 has a more specific pragma (see aforementioned
  % section of the documentation), though I think promise_pure is
  % good enough for our purposes.

  Opt::in `member` Opts::in :-
  	Opt /\ Field \= 0.
  	
  Opt::out `member` Opts::in :-
  	( if Opts = 0 then
		false
	 else
	 	Rest_opts = Opts /\ (Opts - 1),
		(
			Opt = Opts - Rest_opts
		 ;
		 	Opt `member` Rest_opts
		)
	).

An interesting alternative to using ‘\/’ (Mercury's bitwise-or operator)
is to use list notation:

  :- func [] = my_bitfield.
  :- func [my_option | my_bitfield] = my_bitfield.

  ...

  [] = 0.
  [Opt | Rest] = Opt \/ Rest.

This allows constructing option sets with [opt1, opt2, opt5].  Note that
you probably still want to use the fold predicate (or function) rather
than adding a ‘[out | out] = in’ mode, assuming you want [opt1, opt2] to
be equivalent to [opt2, opt1, opt1] but want to iterate in a det
fashion.

pjrm.
--------------------------------------------------------------------------
mercury-users mailing list
post:  mercury-users at cs.mu.oz.au
administrative address: owner-mercury-users at cs.mu.oz.au
unsubscribe: Address: mercury-users-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-users-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the users mailing list