LRL, but simplified! comments: - only #, this makes code review easier and also avoids nested comment handling doc comments: - TBD syntax - no ; - no () in control statements - "return if ..." syntax - meaningful keywords: if/unless/while/skip/break/... - goto/skipto/repeatfrom? - operators, symbols(&&) or keywords(and)? - if we require a ref/addr/stack prefix for non-primitive types, then parsing would be simplified -- that would also require moving the array and optional-value symbols first, e.g. [1]int and ?int -- also require this for arrays and maybe optional value types (those are not primitive) -- this way it *might* be possible to use <> for generics (because the generic params come first) - type keywords vs symbols -- some symbols may be cumbersome to enter like ^ ~ ` -- many symbols have no little meaning $%|\`'~ --- others could have a meaning ^(pointer) @(at) ?(optional) -- stuff like "[10]ref own someobject varname" is hard to group visually. --- possible improvements? expressions: - disallow mixing and/or/xor, bitand/bitor/bitxor - can we avoid the shunting yard algorithm? namespaces: - avoid, since it hampers searchability modules: - 1 module = 1 linkage target - one header per module - enforce backwards compatibility (functions, structs, etc) - symbol versioning, and allow building for an older version types: - write once compile anywhere, i.e. don't allow "int x = 100_000;" if we want to support 16-bit systems - memory saving types: -- bitfields -- compact unions (with unchangeable type, and not allocating unnecessary bytes) -- encourage "interpreted" data, such as byte arrays -- relative pointers. could be of smaller size -- indexes. could be of smaller size - should we have built-in types: string/list/map/set? -- ref/out/inout for modification methods (most be ref/inout, except perhaps clear() etc) data/linkage: - disallow initializers completely (i.e. no pointers in initialized data) - keywords: addr for things that we want to be able to take the address of? memory safety - pointers? implicit pointers a.k.a. references? -- can we have something for the "common case" -- perhaps type prefixes like Perl? Perhaps $ for stack-based types and ^ for reference-based -- or keywords. ref/out/inout/addr/stack etc. -- Perhaps addr should be separate from ref etc, to allow merging constant data --- or just disallow comparisons of pointers of incompatible types - ownership/arena/borrow tracking -- keywords? like "keep" or "own/arenaown()/ownby()" -- how should it work together with ref/out/inout keywords? -- (default) keywords on data structures? -- e.g. "[10]ref own someobj" - array index - how to handle uninitialized data other safety: - library APIs/versions, build time vs runtime - optional values - union types - type states/flags (also needed for memory safety, e.g. ) oop: - interfaces -- fat pointers needed for type and for I -- fat pointers should "merge" into the type, like non-pointer optional values ### # Example documentation header. # # @param a: blabla (primitive types, referenced by their builtin name, are always stack) # @return blabla func xyz_dosomething(int a) -> bool ### # Blabla. # since 1.2 func xyz_dosomething2(ref set o) -> bool func xyz_dfdsf(stack point p) noreturn deprecated 1.2 removed 2.0 func xyz_done() ---> in the binary this could then become 0: xyz_dfdsf 1: xyz_done (available in the binary but not available when compiling for 2.0) 2: xyz_dosomething 3: xyz_dosomething2 (i.e. symbols are sorted by version, and then by name) merging multiple APIs? - use multiple levels, e.g. 0:library1,1:library2 - have a special interface definition for merging, e.g. library lib1 1.0 library lib2 1.0 library lib1 1.2 etc...