[m-dev.] Tool for generating DU types in C

Paul Bone pbone at csse.unimelb.edu.au
Mon Mar 22 15:29:59 AEDT 2010


On Sun, Mar 21, 2010 at 10:58:09PM +1100, Ralph Becket wrote:
> Is there a sensible place to put this?
> 
> Following a conversation with Andrew last week, I've spent some time
> this weekend putting the attached awk script together to generate all
> the boilerplate for discriminated union types in C.

Perhaps on your website.

> This is the sort of thing I find myself churning out all too often
> when hacking C.

I don't know if you want review comments or not.  But I'll happy provide a few
comments.  I scanned quickly through the awk script, I was more interested in
the generated code.  I found two problems in the generated code but otherwise
this is excelent and has more features than I imagined.  Good work.


> As an example, the following file, 'a_b_tree.du':
> 
>     @ type a_b_tree
>     @ constructor a
>     @ constructor b
>     @ constructor branch
>     l : a_b_tree
>     r : a_b_tree
>     @{
>         if (l == NULL || r == NULL) {
>         fprintf(stderr, "a_b_tree: branch cannot have NULL arguments.\n");
>         }
>     }@
>     @ end
> 
> will, when run through 'gen-du-type a_b_tree.du', produce 'a_b_tree.h':
> 
>     /* Automatically generated from a_b_tree.du. */
> 
>     #if !defined(__a_b_tree_h__)
>     #define __a_b_tree_h__
> 
>     typedef struct _a_b_tree *a_b_tree;

Don't hide pointers in typedefs.  In C pointers are so important that they
should be explicit.

> and 'a_b_tree.c':
> 
>     /* Automatically generated from a_b_tree.du. */
> 
>     #include <stdio.h>
>     #include <stdlib.h>
>     #include "a_b_tree.h"
> 
>     struct _a_b_tree {};
> 
>     #define _a_b_tree_a_tag 0
>     #define _a_b_tree_b_tag 1
>     #define _a_b_tree_branch_tag 2
> 
>     struct a_b_tree_a _a_b_tree_a_sentinel =
>         { _a_b_tree_a_tag };
> 
>     a_b_tree
>     a()
>     {
>         return (a_b_tree)&_a_b_tree_a_sentinel;
>     }

So a constructor with no arguments actually returns a reference to a globally
allocated cell, while below a constructor with arguments allocates a new cell
and returns it.  This could be confusing, and should perhaps be made more clear
to the programmer.

You should also make the sentinel object above const so that it is allocated in
read-only memory at runtime.  The constructor should also return a const
object, use cdecl(1) for help with the const keyword, I never remember the
order of these keywards for declarations.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 489 bytes
Desc: Digital signature
URL: <http://lists.mercurylang.org/archives/developers/attachments/20100322/c9e2d3f2/attachment.sig>


More information about the developers mailing list