Integer types ============= Option 1: int/uint + (u)int8..int64 or even int128 Option 2A: int with range (default is int32), compiler chooses representation Bonus: Gets an implicit `eint32` type, which is 0..2^31-1 Bonus: A range with explicit infinite bound(s) could be handled as a bigint. U8/I8..U64/I64 could be RTL-defined types. Maybe even U128/I128 Problem 1: Should there be implicit packing in structs? Maybe not without an explicit bitfield container? Problem 2: Increasing range can change ABI. But it kind of already changes API, so maybe it's a non-issue? (But this could lead to permanentization of typos or off-by-one errors...) Problem 3: Tricky to extend to floating point types. That would also need precision. Also, should such floats be based, i.e. should "float >= 1.0" have 1.0 represented as 0.0? That would increase accuracy, but wouldn't work well with operations other than addition/subtraction. Problem 4: Needs non-pointer types for custom integer types. But maybe this is good to have anyway, in particular for integer types that shouldn't be mixed up. Option 2B: int with range, int64/uint63, compiler chooses representation. One keyword for unsigned integers (uint63 by default). Another keyword for signed integers (int64 by default). Yet another keyword for custom-range integers. Keywords / Type names: * Different keywords? Pos / Signed / Number 0..9 * Signed as a prefix, like C? num / signed num / num 0..9 num / signed / num 0..9 Option 3: bigint by default unless a range is specified. Problem 1: This could lead to code that is inefficient by default. Syntax for range-less variables: # Titlecase type (an ordinary type defined in the stdlib?) # This is tricky because: # 1) int needs range syntax # 2) the compiler needs to know bool in boolean expressions # Or maybe Int/Bool could still be in some kind of built-in "prelude" file Int n = 0 Bool b = false # lowercase type (special case for int,bool) int n = 0 bool b = false # With Option 2B: num n = 0 signed d = -2 float p = 0.5 # Type inferrence. This is fine as long as there isn't arithmetic # operations that could extend the range indefinitly. # With artihmetic operations, it becomes trickier (but maybe # 0..2^31-1 could be the default range? Or -2^31..2^31-1?) n = 0 b = false Syntax for variables with restricted range: # with space inbetween Int 0..=9 n = 0 int 0..=9 n = 0 # with space and hyphesminusdash (why can't it simply be called "dash"...) int 0-9 n = 0 int 0~9 n = 0 # <-- but ~ looks to similar to - and is less intuitive to make # Could perhaps work with Maps also: Map Int-String n = 0 Int->String n = 0 # with intN..n syntax Int..=9 n = 0 int..=9 n = 0 # With parentheses vs not int(0-9) n = 0 int 0-9 n = 0 int 0-9 n = 0 # with intN-N syntax, with intN for 2^N types int-9 n = 0 # maybe skip this? int0-9 n = 0 int0-* n = 0 int64 n = 0 int* n = 0 # with iN-N syntax # note 1: i-9 is also an expression, so the parser/tokenizer # would have to be clever. # note 2: identifiers wouldn't be able to start with `i` followed by # a number. E.g. you can have `i2` as a variable name. i-9 n = 0 # <- ambiguous, but could be skipped i0-9 n = 0 i0-* n = 0 i64 n = 0 i* n = 0 # With option 2B: num<=99 n = 99 num 1<=99 n signed -10<=10 d num ..99 n = 99 num 1..99 n signed -10..10 d # or even 0..99 n = 99 1..99 n -10..10 d # Or, have a longer syntax BUT instead encourage custom types type MyNum = int 0..=9 type MyNum = int from 0 to 9 ... MyNum n = 0 Syntax with inferred range (maybe easy to get wrong?) func f int i int j constraints i >= 0 i <= 10 code i = 0 while i < 10 i = i+1 j = get_number j += 1 assert m >= 0 assert m < 10 ... end