Re: math expressions (was: Re: Tail call elimination)

2020-05-29 Thread Edward Welbourne
Tim Murphy (29 May 2020 01:02) wrote:
> Integer maths is important at the language level - it will enable
> algorithms that weren't possible before e.g. dividing a list into
> equal halves or a for-loop for which we also need a function that
> generates a range).

Indeed.  The only case I can think of where I wished I had the ability
to do arithmetic in make-files was when building large .a files out of
many many .o files, enough to hit line-length limits.  Doing it one .o
at a time hit quadratic behaviour in ar, so doing it in batches, as
large as would fit on the command-line, was our best option; being able
to do arithmetic would have let us automate that cleanly, rather than
kludge it by trial and error.

Eddy.



Re: math expressions (was: Re: Tail call elimination)

2020-05-28 Thread Paul Smith
On Thu, 2020-05-28 at 17:07 -0500, Pete Dietl wrote:
> Thoughts?

I'm fine with these choices, insofar as I can tell.  I reserve the
right to change my mind after seeing the full scope of the proposal :).




Re: math expressions (was: Re: Tail call elimination)

2020-05-28 Thread Tim Murphy
On Thu, 28 May 2020 at 22:07, Pete Dietl  wrote:

> Upon taking a look at gnulib, I found that they have arithmetic wrap
> functions which guarantee wrapping.
> We can use these functions to guarantee that overflow will just wrap
> around.
>
> Let's leave the shift operators out for now.
>
> comp is for complement. ~
>
> In most scheme implementations, providing only one operand to the
> arithmetic functions
> just returns that argument, aside from subtraction, which negates the
> argument.
>
> Once again I am aiming for the single argument syntax of $(math ...)
>
> Interestingly, in Guile, (+) and (*) return 1, but (/) and (-) return
> errors about invalid number of arguments.
> Personally, I think no operands should result in an error.
>

I think that would save people from horrible bugs that would otherwise be
hidden, so yes.

Integer maths is important at the language level - it will enable
algorithms that weren't possible before e.g. dividing a list into equal
halves or a for-loop for which we also need a function that generates a
range).  To me this seems to be on a higher level of importance compared to
bit manipulation.

Tim


Re: math expressions (was: Re: Tail call elimination)

2020-05-28 Thread Pete Dietl
Upon taking a look at gnulib, I found that they have arithmetic wrap
functions which guarantee wrapping.
We can use these functions to guarantee that overflow will just wrap around.

Let's leave the shift operators out for now.

comp is for complement. ~

In most scheme implementations, providing only one operand to the
arithmetic functions
just returns that argument, aside from subtraction, which negates the argument.

Once again I am aiming for the single argument syntax of $(math ...)

Interestingly, in Guile, (+) and (*) return 1, but (/) and (-) return
errors about invalid number of arguments.
Personally, I think no operands should result in an error.

Thoughts?



Re: math expressions (was: Re: Tail call elimination)

2020-05-28 Thread Paul Smith
On Thu, 2020-05-28 at 22:07 +0200, Jouke Witteveen wrote:
> Here is a thought: The current support for numeric variables is
> limited to unsigned numbers. We could choose to stick with that!

I'm not sure how this would work... it works today because we have no
subtraction and all numbers make can generate are always positive, but
if you allow subtraction then you have to decide what to do with
negative numbers.  I guess we could throw a fatal error.

Seems pretty harsh! :)

> Note that when LIST is empty, addition and subtraction should yield
> "0", while multiplication and division should yield "1".

I think this needs to be defined but there are two ways to do it.  And
in addition to the empty list, you need to decide what to do about a
unary list (list with only one value).

In one of my earliest messages on this list I suggested as you do here,
that we use the identity function for the operator.  This boils down to
saying that the initial value of the accumulator for the math function
is 0 for addition/subtraction and 1 for multiplication/division.

Then I had another thought, that always using 0 might be useful in some
situations... but I was thinking specifically of multiplication:
obviously that won't work for division.

So, I think the identity function is the right choice.




Re: math expressions (was: Re: Tail call elimination)

2020-05-28 Thread Paul Smith
On Wed, 2020-05-27 at 13:47 -0500, Pete Dietl wrote:
> Technically, the C standard allows for machines which don't use 2's
> complement.  So should we consider our LONG_MIN to be -2^63 + 1?
> 
> Also, signed arithmetic overflow is undefined behavior, so should we
> also indicate that we have undefined behavior or should we use some
> function that reliably detects and wraps signed arithmetic?
> 
> Bit shifting to the right with signed integers is undefined behavior
> too. Usually this is an arithmetic shift, but it's not guaranteed.
> Should we try to guarantee this with some function or should we leave
> this as undefined behavior?

It seems to me we have these choices:

Just perform the math that they ask us to perform and document that the
behavior is whatever the compiler that built make describes it to be.

Or, have the math implementation check for undefined behavior and make
it a fatal error.  gnulib provides a number of macros which will check
for overflow, for example, that could be used to implement this.

I'm somewhat agnostic on the whole thing since I have a hard time
imagining a situation where it would ever be an issue in any makefile I
might want to write.

In general I prefer to get a real failure rather than undefined
behavior: however, the vast majority of compilers use 2's complement
math for signed values so while the standard leaves it undefined, _in
practice_ it's well-understood what the behavior will be.  As a result
I don't have a strong opinion.

> Before I make my proposal, what do you think of supporting the
> following operators:
> +, -, /, *, not, and, or, comp, <<, >>

I'm not sure what comp is?  Is this <=>?

Do we need shift?  I mean I guess it doesn't hurt but you can always
use * and / instead :).

> Should the logical operators have english names or should they be C
> symbols like !, &, |, ~ ?

If we include bitwise operators I think we should use C symbols else
they may be confused for boolean operators; for example we have
$(and ...) and $(or ...) functions.




Re: math expressions (was: Re: Tail call elimination)

2020-05-28 Thread Jouke Witteveen
On Wed, May 27, 2020 at 8:47 PM Pete Dietl  wrote:
>
> A few questions.
>
> Technically, the C standard allows for machines which don't use 2's 
> complement.
> So should we consider our LONG_MIN to be -2^63 + 1?
>
> Also, signed arithmetic overflow is undefined behavior, so should we also
> indicate that we have undefined behavior or should we use some
> function that reliably detects and
> wraps signed arithmetic?
>
> Bit shifting to the right with signed integers is undefined behavior
> too. Usually this is an arithmetic shift,
> but it's not guaranteed. Should we try to guarantee this with some
> function or should we leave this as undefined behavior?

Here is a thought: The current support for numeric variables is
limited to unsigned numbers. We could choose to stick with that!
This would also deal with the earlier remark by Paul Smith regarding
the nasty nature of switching the sign of a numbers. In fairness,
switching a sign is really a syntactic operation:
minus = $(patsubst --%,%,$(1:%=-%))

> Before I make my proposal, what do you think of supporting the
> following operators:
> +, -, /, *, not, and, or, comp, <<, >>
>
> Should the logical operators have english names or should they be C
> symbols like !, &, |, ~ ?

I would definitely start with only addition, subtraction,
multiplication, and division:
$(math OP, LIST)
Note that when LIST is empty, addition and subtraction should yield
"0", while multiplication and division should yield "1". Every word in
list that is not a number must yield a "non-numeric argument" error,
number parsing should be shared with the current functions that accept
numeric arguments.

One more thing: I really like the proposal by Edward Welbourne for a
three-way comparison function. A numeric equivalent to $(if). His
$(conditional) proposal does not require any boolean tokens and feels
familiar with how things are working right now. One small issue is
that
$(conditional $(a),$(b),$(lt),$(eq))
should probably be empty when a is greater than b. A more ergonomic,
though probably too surprising alternative, is to use the second
argument also for the greater-than case if a third argument is
missing.

Let me know what your plans are, I am willing to help (but have limited time).
FSF copyright forms are in the process of being cleared at my work.

Regards,
- Jouke



Re: math expressions (was: Re: Tail call elimination)

2020-05-28 Thread Pete Dietl
Any suggestions or comments?

On Wed, May 27, 2020 at 1:47 PM Pete Dietl  wrote:
>
> A few questions.
>
> Technically, the C standard allows for machines which don't use 2's 
> complement.
> So should we consider our LONG_MIN to be -2^63 + 1?
>
> Also, signed arithmetic overflow is undefined behavior, so should we also
> indicate that we have undefined behavior or should we use some
> function that reliably detects and
> wraps signed arithmetic?
>
> Bit shifting to the right with signed integers is undefined behavior
> too. Usually this is an arithmetic shift,
> but it's not guaranteed. Should we try to guarantee this with some
> function or should we leave this as undefined behavior?
>
> Before I make my proposal, what do you think of supporting the
> following operators:
> +, -, /, *, not, and, or, comp, <<, >>
>
> Should the logical operators have english names or should they be C
> symbols like !, &, |, ~ ?



Re: math expressions (was: Re: Tail call elimination)

2020-05-27 Thread Pete Dietl
A few questions.

Technically, the C standard allows for machines which don't use 2's complement.
So should we consider our LONG_MIN to be -2^63 + 1?

Also, signed arithmetic overflow is undefined behavior, so should we also
indicate that we have undefined behavior or should we use some
function that reliably detects and
wraps signed arithmetic?

Bit shifting to the right with signed integers is undefined behavior
too. Usually this is an arithmetic shift,
but it's not guaranteed. Should we try to guarantee this with some
function or should we leave this as undefined behavior?

Before I make my proposal, what do you think of supporting the
following operators:
+, -, /, *, not, and, or, comp, <<, >>

Should the logical operators have english names or should they be C
symbols like !, &, |, ~ ?



Re: math expressions (was: Re: Tail call elimination)

2020-05-26 Thread Paul Smith
On Mon, 2020-05-25 at 15:44 -0500, Pete Dietl wrote:
> As for converting between bases, that could always be a separate
> function like `$(convert-base number,radix)` where radix is one of:
> 2, 8, 10, or 16

I agree it should be a separate function.

Perhaps it would be better to consider a more general $(printf ...)
style function, to provide more sophisticated formatting, than to
create something specific just for base conversion.

But this is something to look at some other day; we have more than
enough going on right now.




Re: math expressions (was: Re: Tail call elimination)

2020-05-25 Thread Pete Dietl
> This really annoys me and keeps me on the fence about gnulib, and
> prevents me from completely switching (for example, moving to modern
> glob/fnmatch).  I've only pulled in some relatively simple elements so
> far.
>
> So... I'm not sure which way to fall on that.

Apparently gnulib requires
> at least a freestanding C99 compiler
which is responsible for providing ``.
So we can just use int64_t.



Re: math expressions (was: Re: Tail call elimination)

2020-05-25 Thread Pete Dietl
> I believe the form being considered is:
>
>   $(math OPERATOR,LIST)

I am still partial to `$(math ...)`
with only one argument.

> The only one I'm not sure about is overflow.  That will need some
> thought.  Gnulib contains a comprehensive set of macros to deal with
> overflow, in various ways.

My initial thought was to simply leave it implementation defined, like
C does for signed integers.



Re: math expressions (was: Re: Tail call elimination)

2020-05-25 Thread Paul Smith
On Mon, 2020-05-25 at 13:28 -0500, Pete Dietl wrote:
> Question about 64-bit, what happens when compiling make for a 32-bit
> system? I don’t think c90 has `stdint.h`... maybe there’s something
> in gnulib. Anyway, would we want to support 64 bit integers even on
> 32-bit platforms?

32bit platforms can support 64bit integers.  I see no reason to suggest
we shouldn't.  I would prefer to not make this platform dependent
because that will lead to all sorts of portability issues.

Regarding C99: it turns out that gnulib already requires C99 (at least
parts of it) and since we started incorporating gnulib in GNU make 4.3,
we have sort of "backed into" requiring it as well.

I haven't made an official statement on this because I haven't thought
clearly enough about it yet (just discovered it recently).


Gnulib frustrates me because although it purports to solve portability
issues, and does so admirably between different variations of POSIX
systems, it actually _exacerbates_ portability issues to non-POSIX
systems.  In order to build gnulib-enabled software you have to have a
POSIX portability layer (for example, a POSIX shell and set of POSIX
shell utilities), which is a big ask.

This really annoys me and keeps me on the fence about gnulib, and
prevents me from completely switching (for example, moving to modern
glob/fnmatch).  I've only pulled in some relatively simple elements so
far.

So... I'm not sure which way to fall on that.




Re: math expressions (was: Re: Tail call elimination)

2020-05-25 Thread Paul Smith
On Mon, 2020-05-25 at 12:07 -0400, Sam Kendall wrote:
> I'd like to raise some questions that I think any proposal ought to
> answer. I'll assume a straw man proposal: there's one function, and
> it takes one of the following forms:
> 
> $(math OPERATOR,VALUE1,VALUE2)
> $(math OPERATOR,VALUE1)

I believe the form being considered is:

  $(math OPERATOR,LIST)

where LIST expands to a space-separated list of integer values.  The
operator is applied to the entire list, from left to right.

> A binary operator (first form) is one of + - * and /. The only unary
> operator is "-".

Negation (unary "-") is definitely a problem since unfortunately
standard math uses the same symbol for negation and subtraction.  I
don't want to use the OPERATOR (in the above form) to handle it,
because I don't want to have $(math -,2) behave differently from $(math
-,2 0): it's too bizarre and confusing.

I'd prefer to see it allowed in the parsing of LIST, and handled there.
This absolutely needs thought and needs to be in the proposal.

> There might also be equality and relational operators. A value is an
> optional "-" followed by one or more decimal digits. It represents a
> 64-bit signed integer.

If negation is handled during LIST parsing then we need to allow
multiple initial "-", so you can say "-$(foo)" where $(foo) is -5.

This does mean that we wouldn't support "--"/"++" operators.

For all your other questions I agree the proposal needs to address
them.  I agree with you that all invalid operations should yield fatal
errors.

The only one I'm not sure about is overflow.  That will need some
thought.  Gnulib contains a comprehensive set of macros to deal with
overflow, in various ways.




Re: math expressions (was: Re: Tail call elimination)

2020-05-25 Thread Pete Dietl
`long long` was not introduced until c99, neither was `stdint.h`, but
perhaps gnulib can help us out here.

On Mon, May 25, 2020 at 3:44 PM Pete Dietl  wrote:
>
> > I was not even considering specifying the base of the the resulting
> > expansion.  I was assuming it would always be base 10.  I don't have
> > any good way to specify the output form.
> >
> > I was only considering the parsing of input (constant) values: whether
> > we wanted to support 0xfff, 0o777, 0b111 as well as base 10.  I don't
> > want to support "traditional" octal values that start with plain 0... I
> > believe that's always been a bad idea and it's especially bad in the
> > context of makefiles where values are all strings right up until the
> > moment they're parsed.
>
> I definitely agree with 0x 0o 0b.
>
> As for converting between bases, that could always be a separate
> function like `$(convert-base number,radix)` where radix is one of: 2,
> 8, 10, or 16



Re: math expressions (was: Re: Tail call elimination)

2020-05-25 Thread Pete Dietl
> I was not even considering specifying the base of the the resulting
> expansion.  I was assuming it would always be base 10.  I don't have
> any good way to specify the output form.
>
> I was only considering the parsing of input (constant) values: whether
> we wanted to support 0xfff, 0o777, 0b111 as well as base 10.  I don't
> want to support "traditional" octal values that start with plain 0... I
> believe that's always been a bad idea and it's especially bad in the
> context of makefiles where values are all strings right up until the
> moment they're parsed.

I definitely agree with 0x 0o 0b.

As for converting between bases, that could always be a separate
function like `$(convert-base number,radix)` where radix is one of: 2,
8, 10, or 16



Re: math expressions (was: Re: Tail call elimination)

2020-05-25 Thread Paul Smith
On Mon, 2020-05-25 at 10:10 +, Edward Welbourne wrote:
> > > Mult-base support: should we support only base 10 integer
> > > constants in
> > > expressions, or also hex/octal constants?
> > I vote for decimal, hex, and binary.
> > Octal if you really want it.
> 
> A case for octal and bitwise and/or is that they're what you need to
> manipulate chmod permissions.  Of course, that'd also require being
> able to *expand* the resulting number as octal ...

I was not even considering specifying the base of the the resulting
expansion.  I was assuming it would always be base 10.  I don't have
any good way to specify the output form.

I was only considering the parsing of input (constant) values: whether
we wanted to support 0xfff, 0o777, 0b111 as well as base 10.  I don't
want to support "traditional" octal values that start with plain 0... I
believe that's always been a bad idea and it's especially bad in the
context of makefiles where values are all strings right up until the
moment they're parsed.

> I would tend towards defining a
> 
>   $(compare before, after, rise, same, fall)
> 
> which evaluates to rise if before < after, same if before == after
> and fall if before > after.

That's interesting but honestly I'm not sure I see the advantage of
doing something like this, over simply supporting the standard
operators with a normal conditional function.  It will certainly be
much more familiar to people.  I guess it's helpful in the less common
situation where you want to do three different things for <, ==, and >,
but it's more annoying for the more likely scenario where you want to
use <= or >=... you have to write the result twice.




Re: math expressions (was: Re: Tail call elimination)

2020-05-25 Thread Tim Murphy
On Mon, 25 May 2020 at 18:34, Pete Dietl  wrote:

> Question about 64-bit, what happens when compiling make for a 32-bit
> system? I don’t think c90 has `stdint.h`... maybe there’s something in
> gnulib. Anyway, would we want to support 64 bit integers even on 32-bit
> platforms?
>
> If at all possible, I think.

Tim


Re: math expressions (was: Re: Tail call elimination)

2020-05-25 Thread Pete Dietl
Question about 64-bit, what happens when compiling make for a 32-bit
system? I don’t think c90 has `stdint.h`... maybe there’s something in
gnulib. Anyway, would we want to support 64 bit integers even on 32-bit
platforms?


Re: math expressions (was: Re: Tail call elimination)

2020-05-25 Thread Edward Welbourne
Sam Kendall (25 May 2020 18:07) observed:
> If you have relational or equality operators, what does the boolean
> result look like? If the result is 1 for true and 0 for false, then
> you get a bad surprise: $(if $(math =,5,6),yes) expands to yes. If the
> answer is some nonempty string for true and empty string for false,
> then you can't do math on the result because it isn't a number. I
> think this has come up before in the discussion.

Definitely empty/non-empty for false and true; if you want to do
arithmetic, use an explicit $(if condition, 1, 0) expression rather than
taking for granted that true is 1 and false is 0 (an arbitrary
convention that happens to be widespread (and useful), not an inevitable
universal truth).

Eddy.



Re: math expressions (was: Re: Tail call elimination)

2020-05-25 Thread Sam Kendall
I'd like to raise some questions that I think any proposal ought to answer.
I'll assume a straw man proposal: there's one function, and it takes one of
the following forms:

$(math OPERATOR,VALUE1,VALUE2)
$(math OPERATOR,VALUE1)

A binary operator (first form) is one of + - * and /. The only unary
operator is "-". There might also be equality and relational operators. A
value is an optional "-" followed by one or more decimal digits. It
represents a 64-bit signed integer.

I'd like to see a proposal that's as simple as possible and that includes
use cases. I also like fatal errors in dubious cases, because you can
always relax such a rule later and still be backward compatible.

---

Can an input include whitespace? If so, where?

What happens with an unparseable input such as empty string, foo, or 0.5?
Precedent suggests a fatal error. For example, any of those strings as the
first arg to $(word ) produces a fatal error.

What happens with an out-of-range input such as 9223372036854775808?

What happens upon overflow, e.g., $(math +,9223372036854775807,1)?

How do you input the most negative integer? In other words, is
-9223372036854775808 a valid value?

What happens upon division by zero?

What are the rounding rules for division?

If you have relational or equality operators, what does the boolean result
look like? If the result is 1 for true and 0 for false, then you get a bad
surprise: $(if $(math =,5,6),yes) expands to yes. If the answer is some
nonempty string for true and empty string for false, then you can't do math
on the result because it isn't a number. I think this has come up before in
the discussion.

--Sam


Re: math expressions (was: Re: Tail call elimination)

2020-05-25 Thread Edward Welbourne
>>> Bit Manipulation:
>>> --
>>> * and
>>> * or
>>> * xor
>>> * complement
>>> * left shift
>>> * right shift
>>
>> Maybe.  I have a hard time coming up with uses for these, other than
>> possibly the shift operators (but multiplication/division can be used
>> instead).

Pete Dietl (20 May 2020 18:21)
> Yeah I was thinking the use case could be a little obscure,
> but maybe for some sort of version parsing where bits
> are strangely encoded.
>
> But again I'd say that it's pretty easy to implement.


>> Again, the questions in my email yesterday need to be addressed.

> I totally missed that email somehow. I'll address it in another email.

>> Mult-base support: should we support only base 10 integer constants in
>> expressions, or also hex/octal constants?

> I vote for decimal, hex, and binary.
> Octal if you really want it.

A case for octal and bitwise and/or is that they're what you need to
manipulate chmod permissions.  Of course, that'd also require being able
to *expand* the resulting number as octal ...

Eddy.



Re: math expressions (was: Re: Tail call elimination)

2020-05-24 Thread Paul Smith
On Sun, 2020-05-24 at 14:09 -0500, Pete Dietl wrote:
> > I think, as I mentioned before, that someone (I guess that's you
> > :)) should write up an actual proposal (maybe, for example, the
> > start of a new manual section) that can be examined and commented
> > on.
> 
> Challenge accepted! What is the best form to choose...
> maybe creating a branch of the source and adding a new manual page
> there that anyone can render?

As you may notice, Savannah doesn't support fork and pull request
capabilities like some other services, so we don't really have a way to
share branches like this.

You can just write the text and worry about formatting it later, or
make the changes to the texinfo file and send a diff, or make changes
to the texinfo file then format it for info output and send the
resulting formatted text.

As long as it's not a mess of unreadable HTML source it doesn't matter
to me :).

> > I do want to reiterate something I mentioned initially: any effort
> > of this size will require copyright assignment to the FSF / GNU
> > project.
> 
> Where can I find more information about this? And where do I do it?

I'll send you an email with next steps for this.

> > We can always use evaluation so you could just implement the basics
> > first and get grouping via evaluation for free, then add explicit
> > grouping as a next step if you want.
> 
> Yes incremental changes sound good. Would you recommend
> first trying to agree on a proposal and then attempt some
> implementation?
> Or to do these things together?

It's up to you.  If you want to just write something that's fine.  If
you feel like doing some prototyping would help you come up with the
proposal that's good too.  Note that we likely won't let amount of work
already completed to have much impact on requests to make changes, so
if it will cause sadness to throw out work or have to redo it, then the
less up-front work the better :).

FYI if you do start work on code be sure to read the GNU coding
standards which are slightly unique.  New code needs to follow the
existing formatting.




Re: math expressions (was: Re: Tail call elimination)

2020-05-24 Thread Pete Dietl
> I think, as I mentioned before, that someone (I guess that's you :))
> should write up an actual proposal (maybe, for example, the start of a
> new manual section) that can be examined and commented on.  Endless
> streams of mailing list responses quickly give diminishing returns.  My
> experience is that it's much easier to come to conclusions when there
> is a concrete plan to start from.

Challenge accepted! What is the best form to choose...
maybe creating a branch of the source and adding a new manual page
there that anyone can render?

> I do want to reiterate something I mentioned initially: any effort of
> this size will require copyright assignment to the FSF / GNU project.
> Please be sure you are OK with that.  Getting that in motion earlier
> will avoid delays at the end.

Where can I find more information about this? And where do I do it?

> We can always use evaluation so you could just implement the basics
> first and get grouping via evaluation for free, then add explicit
> grouping as a next step if you want.

Yes incremental changes sound good. Would you recommend
first trying to agree on a proposal and then attempt some implementation?
Or to do these things together?



Re: math expressions (was: Re: Tail call elimination)

2020-05-24 Thread Paul Smith
On Sat, 2020-05-23 at 15:43 -0500, Pete Dietl wrote:
> > I understand what Tim is saying but I still prefer to have a single
> > function.  I want to reduce the "namespace leakage" for these
> > capabilities.  If we decide to add more operations to this in the
> > future I don't want it colliding with something else we want to do.
> > 
> > However, sometimes it's hard to see exactly how something will look
> > until we actually see it.
> 
> Hm so does that imply that we're still on the fence?
> What can we do to resolve this? Take a poll?

I think, as I mentioned before, that someone (I guess that's you :))
should write up an actual proposal (maybe, for example, the start of a
new manual section) that can be examined and commented on.  Endless
streams of mailing list responses quickly give diminishing returns.  My
experience is that it's much easier to come to conclusions when there
is a concrete plan to start from.

I do want to reiterate something I mentioned initially: any effort of
this size will require copyright assignment to the FSF / GNU project. 
Please be sure you are OK with that.  Getting that in motion earlier
will avoid delays at the end.

> You're the benevolent dictator right Paul? :)

Perhaps, in the sense that I reserve the right of ultimate refusal :)

However, the person who makes the proposal and does the work gets to
make a lot of the decisions.

So, I say you should do that.

> > > I propose the following (a variation of example 2):
> > > 
> > > $(math + 5 (/ (* (/ (* 2 9) (+ 7 5 4)) (* 1024 1024)) 19))
> > 
> > If we want to support grouping directly we're still requiring the
> > function to be recursive.  If we use make expansion to provide
> > grouping the function doesn't need to be recursive (of course, we
> > get recursion implicitly because of make's expansion).
> 
> By recursive do you mean the implementation of
> $(math) in the make source is recursive?

Yes.

> It you need more convincing, one could argue that parsing it directly
> would likely lead to a more efficient implementation -- we would
> have the opportunity to implement this as an iterative process;
> either by loops or tail-call recursion. But I'll reiterate that my
> motivation is a more concise syntax.

We can always use evaluation so you could just implement the basics
first and get grouping via evaluation for free, then add explicit
grouping as a next step if you want.

I'm not sure that attempting to avoid recursion (which basically
involves replacing it with some sort of array- or list-based stack) is
worthwhile for the anticipated uses.  So, to me it all comes down to
the implementation: how much more complex is it.

I recommend as above: it is approached iteratively and then we can
decide at each point of it's "good enough" and how much complexity the
next step adds.




Re: math expressions (was: Re: Tail call elimination)

2020-05-23 Thread Pete Dietl
> I understand what Tim is saying but I still prefer to have a single
> function.  I want to reduce the "namespace leakage" for these
> capabilities.  If we decide to add more operations to this in the
> future I don't want it colliding with something else we want to do.
>
> However, sometimes it's hard to see exactly how something will look
> until we actually see it.

Hm so does that imply that we're still on the fence?
What can we do to resolve this? Take a poll?
You're the benevolent dictator right Paul? :)

> > I propose the following (a variation of example 2):
> >
> > $(math + 5 (/ (* (/ (* 2 9) (+ 7 5 4)) (* 1024 1024)) 19))
>
> If we want to support grouping directly we're still requiring the
> function to be recursive.  If we use make expansion to provide grouping
> the function doesn't need to be recursive (of course, we get recursion
> implicitly because of make's expansion).

By recursive do you mean the implementation of
$(math) in the make source is recursive?
I only prefer my suggestion because it removes a lot
of dollar signs and `insert name of function here` repetition.

It you need more convincing, one could argue that parsing it directly
would likely lead to a more efficient implementation -- we would
have the opportunity to implement this as an iterative process; either
by loops or tail-call recursion. But I'll reiterate that my motivation is
a more concise syntax.



math expressions (was: Re: Tail call elimination)

2020-05-23 Thread Paul Smith
On Fri, 2020-05-22 at 23:14 -0500, Pete Dietl wrote:
> So we are back to debating between many functions or (one or two)
> functions. Anyone else care to weigh in?

I understand what Tim is saying but I still prefer to have a single
function.  I want to reduce the "namespace leakage" for these
capabilities.  If we decide to add more operations to this in the
future I don't want it colliding with something else we want to do.

However, sometimes it's hard to see exactly how something will look
until we actually see it.

> As for a name for $(cond), we could call it 
> $(alu ...)
> And put arithmetic and logical operations in it :)

I guess this was not serious but... no :).

> I propose the following (a variation of example 2):
> 
> $(math + 5 (/ (* (/ (* 2 9) (+ 7 5 4)) (* 1024 1024)) 19))
> 
> This would involve doing our own parsing of the argument,
> however this should be trivial since we are using prefix notation.

If we want to support grouping directly we're still requiring the
function to be recursive.  If we use make expansion to provide grouping
the function doesn't need to be recursive (of course, we get recursion
implicitly because of make's expansion).

> I don’t like using $(cond)
> Because because I sort of want to option to implement cond like in
> Scheme.

I suspected someone would mention this :).  I want to reiterate that
even though we're adding some functionality, I'm not interested in
creating an entire programming language in make.

Today we have $(if ...) which has then/else clauses.  I understand that
a Lisp cond wouldn't need to nest each condition but I'm not convinced
that's a serious issue in any real makefiles.

And if you really want Lisp you can use the Guile integration.

So, I'm not too worried about this.  But, feel free to come up with
other names: I'm not saying it has to be that one.




Re: math expressions (was: Re: Tail call elimination)

2020-05-20 Thread Pete Dietl
> If anyone can provide any use case where >64bit math is needed in a
> makefile I'll be interested to hear about it.

Yeah fair enough :)
Then we can always build in support since the size addition to the
Make binary will be trivially changed.

> > * negate
> > * absolute value
> > * exponentiate
>
> Maybe.

My argument for these is that they are pretty easy to implement.

> > Bit Manipulation:
> > --
> > * and
> > * or
> > * xor
> > * complement
> > * left shift
> > * right shift
>
> Maybe.  I have a hard time coming up with uses for these, other than
> possibly the shift operators (but multiplication/division can be used
> instead).

Yeah I was thinking the use case could be a little obscure,
but maybe for some sort of version parsing where bits
are strangely encoded.

But again I'd say that it's pretty easy to implement.


> Again, the questions in my email yesterday need to be addressed.

I totally missed that email somehow. I'll address it in another email.

> Mult-base support: should we support only base 10 integer constants in
> expressions, or also hex/octal constants?

I vote for decimal, hex, and binary.
Octal if you really want it.



math expressions (was: Re: Tail call elimination)

2020-05-20 Thread Paul Smith
On Wed, 2020-05-20 at 10:34 -0500, Pete Dietl wrote:
> I really like the idea of using GMP to do the math.

No, I'm not willing to make that requirement.

If anyone can provide any use case where >64bit math is needed in a
makefile I'll be interested to hear about it.

But, my position is that if you need that you should be using one of
the already-supported facilities for embedded support (guile and/or
using loadable objects).

> Arithmetic Functions:
> ---
> * add
> * subtract
> * multiply
> * divide

These definitely.

> * negate
> * absolute value
> * exponentiate

Maybe.

> Bit Manipulation:
> --
> * and
> * or
> * xor
> * complement
> * left shift
> * right shift

Maybe.  I have a hard time coming up with uses for these, other than
possibly the shift operators (but multiplication/division can be used
instead).

> Comparison Functions:
> --
> * >
> * >=
> * <
> * <=
> * ==

These seem useful.

Again, the questions in my email yesterday need to be addressed.

Another one I forgot:

Mult-base support: should we support only base 10 integer constants in
expressions, or also hex/octal constants?




math expressions (was: Re: Tail call elimination)

2020-05-19 Thread Paul Smith
On Tue, 2020-05-19 at 15:21 +0100, Tim Murphy wrote:
> A question would be do we want to use GMP or are 64 bit ints enough?
> I'm inclined to say ints are ok of they are wide. 

Straight 64bit integer arithmetic is fine IMO.  I'm definitely not
interested in adding another library dependency.

> So for me an add function that took signed numbers would be enough if
> it came with < > = since we already have "or" and "and". e.g.
> X:=$(add $(X),-1) gives you decrement.
> 
> If one is minimal then there is less chance of creating a carbuncle.

No, I don't like this.  Perhaps addition is sufficient for your use-
case but others may need multiplication or division and I certainly
don't want to start adding 10 different explicit funtions like "add",
"mult", etc.  I prefer a single mathematical expression function.

These are the things that need to be decided from what I can tell:

Name: I'm using expr here just for convenience.  Is there a better
name?

Whitespace: do we have to put whitespace around every operator, like
expr(1), or is the function smart enough to understand $(expr 1+1+4)?

Grouping: do we try to implement expression grouping with () (e.g.,
$(expr (1 + 1) * 4) or is it good enough to just say people need to
nest expr functions: $(expr $(expr 1 + 1) * 4)?

Precedence: do we try to implement standard mathematical precedence
(multiplication/division before addition/subtraction) or do we just
evaluate left to right and require explicit grouping?  It would
definitely be a source of ongoing user confusion to not follow normal
precedence rules, but supporting it would make the implementation more
complex.

Increment/decrement: do we try to implement += / -= and/or ++ --?  It
would be something like the symbol on the left would be interpreted as
a variable name, so $(expr foo += 5) would add 5 to the variable foo
(and expand to the new value of $(foo)).  If we support ++/-- do we
support both pre- and post- operators?  This isn't needed in places
where you can just say "foo = $(expr $(foo) + 5)", but allowing
assignment within an expression could be very helpful.  It could be
done anyway with: $(eval foo := $(expr $(foo) + 5))$(foo) ... is it
worthwhile to add syntactic sugar for this?

If we support increment/decrement do we go farther and support variable
interpolation a la shell $((...)), where a symbol is assumed to be the
value of the variable (that is, $(expr foo + 10) is equivalent to
$(expr $(foo) + 10)?  I wouldn't bother implementing this by itself but
it becomes a question if increment/decrement needs it anyway.