do not allow assignment expressions where booleans are expected --------------------------------------------------------------- prevents common errors like these: bool a, b; if (a = b) { ... } while (a = b) { ... } but we still want to allow these: bool a, b; a = b = true; we could make an exception for assignment expressions, like this: * If a boolean expression is NOT expected in a given node in the parse tree, * Or, if the node is an assignment node, * Then accept the node. unary plus/minus ---------------- should we allow things like this? c = a + -b or only allow unary minus when it's at the start? or only allow unary minus when it's not before a plus? incomplete types ---------------- It's easy to accidentally create an incomplete type: typedef bintree[T] = (bintree[T]^? left, right; T value); // incomplete! typedef bintree[T] = (bintree[T]^? left, right; T^ value); Such mistakes ought to be detected when the type is compiled, not when it's used. One way of detecting this early is to require a qualifier on incomplete types: typedef bintree[T] = incomplete (bintree[T]^? left, right; T value); typedef item = incomplete ( int x; private; ); optional private types ---------------------- An optional type can be merged with it's target type sometimes. For instance, pointers can have a NULL value in their underlying type, so making a pointer optional will simply allow the NULL value to be stored as well. On the other hand, struct types will be prepended with a boolean flag which tells whether the value has been set or not. Because the underlying structure of optional types depend on the target type it's not possible to have optional private types: typedef A = private; // could be a pointer, or something else A?^ value; // not allowed // types from type parameters are private typedef B[T] = ( T? x; // not allowed ); But these types can be rewritten as incomplete structs: typedef A = private; (A)?^ value; // Optional struct. This is OK typedef B[T] = ( (T)? x; // OK ); floating point NaN ------------------ Operations with NaN is always false. This probably useful in many cases, but not when you want to test for NaN (a friend encountered this problem). Solution: forbid comparison with a constant NaN (always false) and add a .isNaN() method. then-else and subtypes ---------------------- // B and C are subtypes of A (i < 1 then b else c).print(); * Should method overriding be allowed in subtypes? * Should then-else be allowed in this case? * What should the code above mean? // This is not going to work with multiple then-elses in the same // expression due to combinatorial explosion. if (i < 1) b.print(); else c.print(); or // We don't know which function to call, if it has been overridden! A^ temp = (i < 1 then @b else @c); temp^.print(); or // Not allowed if it can cause slicing! // (could probably be avoided by making the decision when the // function "this" argument is passed) A temp = (i < 1 then b else c); temp.print(); private types and constraints ----------------------------- // private definition typedef t = ( count length; int[length]^ entries; ); // public definition - incorrect/unsafe typedef t = ( count length; // ERROR! length is used in a constraint, so it private; // may not be writable by code which is not aware ); // of the constraint. // public definition - correct typedef t = ( readonly count length; // OK private; ); exported functions/symbols in .lc files --------------------------------------- It should be possible to see in an .lc file which things are exported and not (similar to how you can look for the "static" keyword in a .c file) E.g int prepare_internal() { } public int dosomething() { prepare_internal(); ... } // or export int dosomething() { prepare_internal(); ... } However, the code at the caller side should *not* need to change if a function is changed to be public or no longer public. So underscore prefixing ("_interal") or significant upper/lowercase characters (e.g. "PublicFunction" and "private_function") aren't any good ideas IMO.