Types ----- Elementary: void -- () s char -- int8 u char -- byte (=uint8) short -- short (=int16) u short -- ushort (=sint16) int -- int u int -- uint long -- - u long -- - - -- int0, int1 ... - -- uint0, uint1 ... - -- ring0, ring1 ... int x:3 -- unaligned int3 bool -- uint1 size_t -- count ssize_t -- - Enum: enum { a, b } int(a | b) Struct: struct { int a; int b; } (int a, int b) Union: union { int a; int b; } union(int a, int b) The types must be guaranteed to be compatible by any user of the union. Private types are in fact allowed, and this can be used to implement multiple inheritance. See the rules for private types. Pointer: int * int* (if NULL is allowed, equivalent to int&?) int& (if NULL is not allowed) the compiler must check that the pointer points to a compatible value at compile time. Array: int[] int[] (but accessing is an error in strict mode) int[5] int[5] int[length] int[length] Strings, null-terminated: char[20] s byte[20] s char* s byte[strlen(s)+1]* s "test" "test" A null is always added at the end. Strings are UTF-8. Function: int func(int a, int b) (int) func(int a, int b) int (*func)(int a, int b) (int) (int a, int b)* func (int result) func(int a, int b) Named return parameter Variable arguments: int func(int a, ...) (int) func(int a, args...) constraint(x) args becomes an opaque type of unknown size. Unless a constraint is given it can only be accessed in unsafe mode. Data hiding: typedef struct _a a typedef a = private struct _a { int b } typedef a = (int b) typedef a = (int #refcount, private) A struct where only the refcount is public. It's allowed to have a private and a non-private type of the same name, if the non-private parts are compatible. Const: const int a = 0 const int a = 0 const value* find(const key *key) (const value* entry) find(const key& key) const makes everything after the keyword const. These are equivalent: const char *const s = "test"; const byte[]* s = "test; typedef coord = const (int x, int y) coord a = (0, 1); coord b = (x: 0, y: 1); coord will be immutable, but can be created Optional value (new): int? order_number Memory restrictions (new): int&none -- No ownership of pointer (default) int&owned -- Ownership of pointer is required (int #c)&refc -- Reference counted. The type must be a pointer to a struct, or an optional pointer to a struct. The struct must contain a reference counter, whose name must be prefixed with #. typedef node = (node*backptr prev, node*owned next, int value) The prev pointer must point to another node which owns the current node. Constraints (new): int a constraint(a < 0) int a constraint(value < 0) The constraint must be satisfied when modifying to a, and is assumed to be satisfied when reading a value from a. () sqrt(int* a) precond(*a >= 0) postcond(*a >= 0) The precondition must be satisfied when calling the function. The function must satisfy the postcondition before it returns (int r) modify(int a) constraint(readonly == false) The constraint must be satisfied during the call of the function. typedef oddint = int constraint(value & 1 == 1) The constraint must be satisfied for any value of this type. void memcpy(restrict char *dest, restrict const char *src, size_t length) () memcpy(byte[length]& dest, const byte[length]& src, count length) constraint(distinct(dest, src)) Inheritance (new): typedef FileSystem = private; typedef FTPFileSystem = (FileSystem base, private); typedef HTTPFileSystem = (FileSystem base, private); The inheritance is just syntactic sugar. If you have a member called "base" in a struct then it will work as the base class. private is not a real type, and is not compatible with any other type. Hence FTP and HTTPFileSystem are incompatible (they have no common real type). Multiple inheritance (new): typedef DatabaseColumn(Table) = private; typedef TypedColumn(Type) = private; typedef Column(Table,Type) = ( union(DatabaseColumn(Table),TypedColumn(Type)) base, private ); The rules for compatibility in unions apply. Namespaces (new): typedef Car = private; typedef Car = (Car *trailer, string& regnum); namespace (Car) { -- Static method (bool) check_registration_number(string& regnum); -- Constructor (actually, it's just a static method) -- How should we handle stack allocation? -- 1) with an extra parameter (like C++ does) -- 2) with a flag -- 3) with different methods? -- 4) by returning (Car this) and having the caller sort out -- allocation? (Car* this) new(Car* trailer = NULL, string& regnum); -- Instance method () start(Car& this); } Car &c = Car.new("ABC123"); c.start(); -- Should we have two constructors, like this? -- problem: we overwrite the state of a class with init()! (Car this) init(Car* trailer = NULL, string& regnum) -- this is optional of course constraint(uninitialized(this)) { this.trailer = trailer; this.regnum = regnum; } (Car* this) new(Car* trailer = NULL, string& regnum) { this = alloc(); *this = init(); } Generic types (new): typedef list(T) = private typedef list(T) = (int length, T[length]* data) Definition of a generic type. () add(T)(list(T) this, const T& element, count size = alignedsize(T)) constraint(size == alignedsize(T)) Expressions ----------- Should IMO be mostly the same as C, except: * Different priority of operators. x & 1 == 0 should mean (x & 1) == 0 * MAYBE we should remove post/pre addition/subtraction * MAYBE = should not return a value, except in cases like "a = b = z" * MAYBE < should be possible to write like -10 < x < 30 Exception modes --------------- strict -- the compiler checks that no exceptions can occur at runtime loose -- the compiler inserts checks for exceptions so the program is terminated before an exception would occur. unsafe -- no checks are done at runtime. exceptions may have undefined behaviour in some cases.