Re: math expressions (was: Re: Tail call elimination)
> 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)
> 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)
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)
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)
`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)
> 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)
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)
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)
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)
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)
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: Tail call elimination
Pete Dietl (22 May 2020 09:18) > As for a name for $(cond), we could call it > $(alu ...) > And put arithmetic and logical operations in it :) Amusing as this is, I don't think it's a good name ! > I don’t like using $(cond) > Because because I sort of want to option to implement cond like in Scheme. There are already $(if, test, yes, no) evaluating to yes if test is a non-empty string, no if it is empty; $(or conds,...) evaluating to the first non-empty condition, empty if all are empty; and $(and conds...) evaluating to the first empty condition, else the last parameter. So no need for cond. 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 packs all of the <, <=, >, >=, == and != tests into one; when you want the cases where two come out the same, $(if $(compare $(a), $(b),,y,y),ge,lt) will evaluate to ge if $(a) >= $(b), else to lt, so that repeating y saves repeating a potentially long ge text. Obvious similar usage can handle the other "use same value in two cases" options. On the need for a named function: note that $*, $(*), $(*D), $(*F) and likewise for $+ all have meanings already, so overloading them to also be the multiplication and addition operators sounds imprudent, even if it is possible. I think $(math op, args) makes sense, so as to have only one entry-point in both code and documentation. I think each operator should initialize a result to its first argument then use the operator to combine the current result with each successive argument; so $(math *, 7) evaluates to 7, $(math /, $(size) 1024 1024) turns a size in bytes into a size in MiB and $(math -, $(total) $(subs)) gives the residue when each sub has been subtracted from a total. But then I've been influenced by Lisp, so I would think that. I'm sure there's a quote somewhere about every language eventually growing an implementation of Lisp. Perhaps it's best to stop short of actually dong that fully, though ... Eddy.
Re: math expressions (was: Re: Tail call elimination)
>>> 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.