Are the authors opposed to preprocessing?

1,204 views
Skip to first unread message

clark....@gmail.com

unread,
Mar 17, 2012, 12:41:40 PM3/17/12
to golan...@googlegroups.com
While fixing an error in misc/cgo/gmp/gmp.go (my Ubuntu 10.04 system has version 4.3.2 of libgmp, which doesn't have the mp_bitcnt_t type), I was thinking of putting in a conditional test on libgmp version and found that there is no conditional compilation (or macros either). Somebody in this forum asked about this earlier and was told to do "makefile magic".

I'm probably overlooking something, but even makefile magic will require some kind of text substitution on the sources or have N versions of the source where N is the product of the number of variants. That doesn't seem very programmer friendly to me, especially for a system language.

Are the authors opposed to pre-processing on principle, or is this just something nobody has gotten around to yet?

If the Go community rejects pre-processing, why and what does it offer to prevent the explosion of variant sources?

In particular, how could the following be offered as a patch to misc/cgo/gmp/gmp.go ?

// Lsh sets z = x << s and returns z.
func (z *Int) Lsh(x *Int, s uint) *Int {
x.doinit()
z.doinit()
// The version of gmp we have (4.3.2) doesn't have mp_bitcnt_t
// C.mpz_mul_2exp(&z.i[0], &x.i[0], C.mp_bitcnt_t(s))
C.mpz_mul_2exp(&z.i[0], &x.i[0], C.ulong(s))
return z
}

// Rsh sets z = x >> s and returns z.
func (z *Int) Rsh(x *Int, s uint) *Int {
x.doinit()
z.doinit()
// The version of gmp we have (4.3.2) doesn't have mp_bitcnt_t
// C.mpz_div_2exp(&z.i[0], &x.i[0], C.mp_bitcnt_t(s))
C.mpz_div_2exp(&z.i[0], &x.i[0], C.ulong(s))
return z
}

Ian Lance Taylor

unread,
Mar 18, 2012, 12:59:36 AM3/18/12
to clark....@gmail.com, golan...@googlegroups.com
clark....@gmail.com writes:

> Are the authors opposed to pre-processing on principle, or is this just
> something nobody has gotten around to yet?

Go is not going to acquire a preprocessing phase like C. This is a
matter of principle.


> If the Go community rejects pre-processing, why and what does it offer to
> prevent the explosion of variant sources?

Note that this is only an issue when working with the syscall package or
cgo. For the syscall package, variant sources, controlled by build
tags, are the supported mechanism. For a case like your using cgo, I
would recommend handling the type in the C source code if possible, in
order to present a uniform interface to the Go code.

Ian

Albert Strasheim

unread,
Mar 18, 2012, 3:09:32 AM3/18/12
to golan...@googlegroups.com
Hello


On Saturday, March 17, 2012 6:41:40 PM UTC+2, clark....@gmail.com wrote:
If the Go community rejects pre-processing, why and what does it offer to prevent the explosion of variant sources?

Maybe not strictly related to your problem, but I would also suggest that you could write any kind preprocessor or code generator your heart desires based on comment contents, struct tags or other struct/function/interface conventions using go/parser. It really works well.

Regards

Albert

minux

unread,
Mar 18, 2012, 1:22:50 PM3/18/12
to clark....@gmail.com, golan...@googlegroups.com
I'm also troubled by this particular problem when testing cgo, so I think this patch
could be merged. You can follow the instructions detailed on http://tip.golang.org/doc/contribute.html

On Sun, Mar 18, 2012 at 12:41 AM, <clark....@gmail.com> wrote:
In particular, how could the following be offered as a patch to misc/cgo/gmp/gmp.go ?

// Lsh sets z = x << s and returns z.
func (z *Int) Lsh(x *Int, s uint) *Int {
x.doinit()
z.doinit()
// The version of gmp we have (4.3.2) doesn't have mp_bitcnt_t
I suggest the comment changed to "// older version of gmp doesn't provide mp_bitcnt_t, so use ulong instead" 
// C.mpz_mul_2exp(&z.i[0], &x.i[0], C.mp_bitcnt_t(s))
delete this line of comment. 
C.mpz_mul_2exp(&z.i[0], &x.i[0], C.ulong(s))
return z
}

// Rsh sets z = x >> s and returns z.
func (z *Int) Rsh(x *Int, s uint) *Int {
x.doinit()
z.doinit()
// The version of gmp we have (4.3.2) doesn't have mp_bitcnt_t
// C.mpz_div_2exp(&z.i[0], &x.i[0], C.mp_bitcnt_t(s))
ditto 

minux

unread,
Mar 18, 2012, 2:04:22 PM3/18/12
to clark....@gmail.com, golan...@googlegroups.com
Oh, sorry, my fault. If we use ulong it will break build for newer gmp. I suggest we wrap both of the
function. As the code needs some further updates, I will submit a CL for this.
Thanks for this report.

clark....@gmail.com

unread,
Mar 18, 2012, 3:02:45 PM3/18/12
to golan...@googlegroups.com
Ian Lance Taylor write:

 > Go is not going to acquire a preprocessing phase like C.  This is a
 > matter of principle.

Please, what is the principle? Why do you reject pre-processors?

 > Note that this is only an issue when working with the syscall package or
 > cgo.  

I don't think so. Conditional compilation is not just about dealing with C header file cruft. It solves the problem of variant features that may be configured in or out at compile time.  Are you saying that the go authors take the position that all variant features should be dealt with at run-time ? Take for instance almost any  .[ch] file in the Linux kernel. How would you write a kernel in go without conditional compilation? 

Frithjof Schulze

unread,
Mar 18, 2012, 3:40:07 PM3/18/12
to golang-nuts
On Sat, Mar 17, 2012 at 09:41:40AM -0700, clark....@gmail.com wrote:
> In particular, how could the following be offered as a patch to
> misc/cgo/gmp/gmp.go ?
>
> // Lsh sets z = x << s and returns z.
> func (z *Int) Lsh(x *Int, s uint) *Int {
> x.doinit()
> z.doinit()
> // The version of gmp we have (4.3.2) doesn't have mp_bitcnt_t
> // C.mpz_mul_2exp(&z.i[0], &x.i[0], C.mp_bitcnt_t(s))
> C.mpz_mul_2exp(&z.i[0], &x.i[0], C.ulong(s))
> return z
> }
>
> // Rsh sets z = x >> s and returns z.
> func (z *Int) Rsh(x *Int, s uint) *Int {
> x.doinit()
> z.doinit()
> // The version of gmp we have (4.3.2) doesn't have mp_bitcnt_t
> // C.mpz_div_2exp(&z.i[0], &x.i[0], C.mp_bitcnt_t(s))
> C.mpz_div_2exp(&z.i[0], &x.i[0], C.ulong(s))
> return z
> }

I originally asked for usage of the mp_bitcnt_t type

http://code.google.com/p/go/issues/detail?id=2007

because newer versions of GMP do use this type. Instead of reverting this
change I really would like to see an exemplary way to handle such problems.

Best,
Frithjof

minux

unread,
Mar 18, 2012, 4:00:23 PM3/18/12
to golang-nuts
On Mon, Mar 19, 2012 at 3:40 AM, Frithjof Schulze <sch...@math.uni-hannover.de> wrote:
I originally asked for usage of the mp_bitcnt_t type

http://code.google.com/p/go/issues/detail?id=2007

because newer versions of GMP do use this type.  Instead of reverting this
change I really would like to see an exemplary way to handle such problems.

Paulo Pinto

unread,
Mar 18, 2012, 5:44:23 PM3/18/12
to golang-nuts
This is actually one area where I agree 100% with the Go authors.

Separating operating systems across files is a best practice I have
when coding C or C++, instead of filling the code with tons of
unreadable #ifdefs.

They tend to grow to a point, where sometimes it is required to
run cpp just to understand what is actually happening.

Enterprise code experience. :\

--
Paulo

On Mar 18, 5:59 am, Ian Lance Taylor <i...@google.com> wrote:

John Barham

unread,
Mar 18, 2012, 6:57:53 PM3/18/12
to clark....@gmail.com, golan...@googlegroups.com
> How would you write a kernel in go without conditional compilation?

Here's how it's done in C: http://plan9.bell-labs.com/sources/plan9/sys/src/9/

Andrew Gerrand

unread,
Mar 18, 2012, 9:52:51 PM3/18/12
to clark....@gmail.com, golan...@googlegroups.com
Pre-processor macros in C have made most "portable" C code very difficult to read. Readability is one of Go's key design criteria.

Instead, the "go" command supports conditional compilation of entire files. This seems to be a simple, comprehensible approach that scales well.

See the "Build Constraints" section of the go/build package docs for details:

Andrew

Hans Stimer

unread,
Mar 18, 2012, 10:22:59 PM3/18/12
to clark....@gmail.com, golan...@googlegroups.com
I like how D solves this by just having static if statements that
disappear at compile time. i.e. if (processor == ARM) { .... } else if
(processor == X86) {...}.

The compiler just predefines these values.

http://dlang.org/version.html

ron minnich

unread,
Mar 19, 2012, 12:51:02 AM3/19/12
to Hans Stimer, clark....@gmail.com, golan...@googlegroups.com
On Sun, Mar 18, 2012 at 10:22 PM, Hans Stimer <hans....@gmail.com> wrote:
> I like how D solves this by just having static if statements that
> disappear at compile time. i.e. if (processor == ARM) { .... } else if
> (processor == X86) {...}.

What's special about this? Any reasonable optimizing compiler will do
the same. Or in the case of the Go toolchain, one of ?l can do it too
IIRC.

I tried but failed to find the article that we used to call 'if (0)'
back at LANL. The argument explained why
if (0)

made a lot more sense than
#if 0

(more or less)

ron

Hans Stimer

unread,
Mar 19, 2012, 2:21:18 AM3/19/12
to ron minnich, clark....@gmail.com, golan...@googlegroups.com
On Sun, Mar 18, 2012 at 9:51 PM, ron minnich <rmin...@gmail.com> wrote:
> On Sun, Mar 18, 2012 at 10:22 PM, Hans Stimer <hans....@gmail.com> wrote:
>> I like how D solves this by just having static if statements that
>> disappear at compile time. i.e. if (processor == ARM) { .... } else if
>> (processor == X86) {...}.
>
> What's special about this? Any reasonable optimizing compiler will do
> the same.

There is nothing special required of the compiler, that is why it is
such an elegant solution.

楚杰

unread,
Mar 19, 2012, 2:30:18 AM3/19/12
to golan...@googlegroups.com
How golang to support optional compile-time features?
Reply all
Reply to author
Forward
0 new messages