toplevels --------- type NAME = T [interface] func N(T a, ...) [return T] KW... T NAME [= VALUE] should we have "->" or "return" or "returns" or ":" ? elementary types ---------------- bool size - unsigned ssize - signed offset - unsigned, offset in files soffset - signed, offset in files byte - unsigned, 8 bit, wrapping short - signed, 16 bit ushort - unsigned, 16 bit wushort - unsigned, 16 bit, wrapping int - signed, 16/32 bit uint - unsigned, 16/32 bit wuint - unsigned, 16/32 bit, wrapping long - signed, 32/64 bit ulong - unsigned, 32/64 bit wulong - unsigned, 32/64 bit, wrapping int32 uint32 wuint32 int64 *1 uint64 *1 wuint64 *1 (int128, uint128, wuint128) *2 (float, double, float16, float32, float64, float80, float128?) *2 *1 = not available in bootstrap *2 = only available if supported by target platfrom. not available in bootstrap other types ----------- - for parameters it is probably enough to have ref/out/inout/addr/stck - for data there is only stack (we don't allow pointers, since that would require an initializer) - for function-locals we need: -- var -- stck (for initialized const-arrays/structs and named types) -- addr -- ref -- rwref (or inout, varref or mutref?) -- wref (or out?) ("var ref" and "ref var" could be confusing, and even more so "ref var ref") for structs we need -- nested (for const-arrays/structs and named types) -- addr, ref -- rwref, wref (for write access, or copying to another location, these also require write access to the struct itself) structs can use plain () syntax without a keyword this should work well with the keywords (nested/ref/stck/etc) function pointers, should that be "ref func(T x, ...) return T" syntax? optional types could use "?" or "opt" before the type, e.g. "?int" or "opt int" enums could use "enum (a = 1)". and "enum byte (a = 1, b, c)" etc. - the syntax above will only allow elementary types (incl. named types)? (probably a pragmatic choice) arrays: - [3]int - [len]int - [enumtype]int - [inttype]int - how to combine inttype and length expression? -- pragmatic choice: use type of length expression. we could also use an "as" expression here -- or instead of "as": "[T L]A", e.g. "[indextype 3]arr" -- do we want to support lower bounds as well? e.g. [1..5,3..10] or [indextype 1..5, indextype2 3..10] parametric types: - list - or list ? types referenced by identifier - a type can't start with an identifier. - as a workaround, require: -- that enums start with "enum" (always) -- that stack structs have a "stack" qualifier IF we also disallow typedefs to builtin types, arrays etc. and only allow typedefs of structs/enums, this would mean that any bare identifier reference is a reference to a struct type. type qualifiers: - shared - reading(...) (objects that are read from) - (or "using"?) - writing(...) (objects that are written to) - readwriting(...) (objects that are read and written to) - static (for functions-locals). by default, it creates a constant non-pointer - (var?) - own - own(...) - takeown ("this" param takes ownership) - dropown ("this" param looses ownership) - takeown(x) / dropown(x) (x takes/looses ownership) - takeshare/dropshare ? or just use plain shared(...) - dedup (for generic-typed parameters, to allow values that fit in a pointer to be passed inside the pointer, avoiding creation of a temporary stack item and indirections to access it) Expressions ----------- - can we have only prefix and infix (+ maybe ternary-infix) operators? -- we still need . [] () - pointers: -- addrof -- deref (may be needed for final deref) - optional types: -- makeopt -- optval (or ? as postfix operator)... or use typeasserts instead, more meaningful! - arithmetic: -- + - * / mod -- ++ -- (or inc/dec) -- unary - - boolean -- and or xor not - bitwise -- bitand bitor bitxor neg shl shr (shra?) (rol ror?) - array index x[i] (with explicit pointer deref) - struct member s.m (with explicit pointer deref) - function call (with explicit pointer deref?) - ternary operator? select operator? in operator? etc... -- we want to avoid commas in multi-line statements -- multiline statements are probably a better idea (for readability) -- there could be built-in or stdlib functions/macros for common conversions like bool<->int select [0, 1] select [:false 0, :true 1] select [ :false 0 :true 1] select [ :false => 0 :true => 1] select { case :true => 0 case :false => 1 } # conversion functions with typescope :from_bool(:true) :from_int(1) # without typescope (clearer?) bool2int(:true) int2bool(1)