One thing I miss when programming in Wren is not being able to perform (full) 64 bit integer arithmetic, as we are effectively limited to no more than 53 bits because of the way that
Nums are represented.
I've been wondering whether there might be a way to achieve this without impacting on the simplicity of dealing with smaller integers and numbers generally that the
Num class gives us and have come up with an idea.
This is a fairly rough sketch so please bear with me.
The basic idea is to introduce a
Long class into the core library. A
Long object would be 8 bytes long and would be represented internally by a C99
signed long long. It would be immutable as numbers are now.
Long would be a value type as a variable of that type would hold its value directly.
Long class would not have constructors but instead a
Long object could be created in one of three ways:
From a literal - an integer with an 'L' suffix. Lower case 'l' would not be allowed as it's too easily confused with the digit '1'.
From a string by giving the
String class a
toLong method which could optionally specify a base from 2 to 36.
From a number by giving the
Num class a
Long class itself would support all the usual integer operators:
+ - * / % & | ^ ~ << >> < <= == != >= and >.
However, the operands would always need to be
Long objects - mixed operations with
Nums would not be allowed.
We'd also need a few methods such as:
sign as well as
Here's a few simple examples to show how some of this would look:
var r = 123456789L // Long created from a literal
var s = "123456789123456789".toLong // Long created from a String
var t = 12345678912345.toLong // Long created from a Num
var u = "abcdef".toLong(16) // Long created from a base 16 string
var v = s + t * u // arithmetic operations on Longs
var w = (s > t) && (t > u) // relational operations on Long
var x = s + 6 // not allowed, can't add Num to a Long
var y = s + 6L // fine
var z = r.toNum // Long converted to Num
Internally all operations would be performed from the C side using
long long arithmetic and conversion functions such as
There would clearly be a lot of work needed to implement this and so the question is would it be worth it?
On the plus side:
We'd get full 64-bit integer representation and arithmetic including bit-wise operations though the latter might necessitate an internal conversion to
unsigned long long. It would probably be best for overflows to wrap rather than producing an error.
As we'd just be dealing with integers, base conversions would be straightforward to implement.
Integer division would be just that (i.e. any remainder would be discarded) which is something I was banging on about in #907.
There would be no impact whatsoever on
It would be backwards compatible.
On the minus side:
There would be a certain amount of inconvenience in not permitting mixed arithmetic with
There would inevitably be an impact on the size of the core library though I don't really see how it could done as an optional module as you'd need support for
Long literals in the language itself.
Using a numeric suffix for literals is arguably a bit ugly but I can't think of a sensible alternative and, of course, C has used suffixes from day one.
Long would have a lower range than an unsigned 64 bit integer but I feel that the convenience of having signed integers outweighs this.
There would be more for newcomers to the language to learn.
Finally, I'd add that you could do a lot of this with a custom type which is represented internally by a
List of two
Nums. However, the trouble with this is that it's relatively slow and, as it's a reference type, it will be subject to garbage collection and can't be used directly as a
I look forward to hearing what you all think.