Module header syntax -------------------- Function syntax --------------- Constructor/OO syntax ------------------ No constructor should mean that there is a default constructor where all uninitialized fields are assigned from a corresponding parameter. int x int y = 123 constructor int x code this.x = x end How to denote exported vs module-private vs class-private fields? How to denote exported vs module-private vs class-private functions? Should there be "friend classes"? Or "friend namespaces"? - Should those allow access from other modules? Probably not? For record-style classes, it would be nice if it was enough to specify only the fields, and then have a usable struct. Type syntax ----------- Integer types: - Should they be bit-sized? E.g. int32 - Should there be unsigned integers? E.g. uint/uint32 - Should they be range-limited? E.g. int from 0 to 9, int<0..9>, number from 0 to 9 Maybe "neutral" types like int and string should be avoided, and more specific types should be defined? At the defintiion, it could be possible to specify a range, maxlength or allowed characters. Data syntax ----------- Should the type specification syntax be: * `int i` * `i: int` * `i` i.e. inferred from name * `const i` i.e. inferred from name, but with explicit definition - or e.g. `def i`, `let i` * `num i`, `string s`, `ref o`, i.e. distinguishing between "major" types but inferring more precise types. * Allow type inferrence in `given` lines. As field in arena / At ...? - Should this be possible? - Where to put the definitions? A specific place per module? - Or should there be some kind of dynamic mechanism? (but then there could be a risk of name conflicts, unless each module has it's own namespace) As field in object / At file-level: # Final (only assignable in constructors, must be assigned) int x # function-specific instance variable var int y, only in (f,g) # Function-specific, but must be assigned in constructors int x2, only in f As local variable in function / At function-level: func f code # name only i = 123 # type+name int i = 123 # XXX this is probably a bad idea. it hides state! #instancevar state end Statement syntax ---------------- Expression syntax ----------------- Function calls. Only allowed at the beginning of statements, or at the beginning of grouping parentheses: f f arg1 f arg1, arg2 Should there be methods? Or should there be per-type identifier scopes? - That could mean that two places would have to be searched! - Unless "functions" and "procuderes" are different things But that would mean different function naming: add_number (from_thing t) Instead of: add_number (get_number t) I think there are pros and cons. In some cases one syntax is more readable than the other. obj.f arg1 obj.f arg1 The advantage of this is that getters can be called in subexpressions without using parentheses: obj.f obj2.get_x, obj2.get_y How should variables/fields(/properties?) be assigned? obj.value = 123 obj.value! = 123 obj!.value = 123 set obj.value, 123 set obj.value!, 123 set obj!.value, 123 # with getters/setters only: obj.set_value 123 obj!.set_value 123 There are actually only two types of expressions that can appear at the statement level: - function calls - assignment expressions Of course, the left-hand side is a subexpression and could be some deep multi-level expressionm e.g. obj.arr[obj.index][2].field Instance variable access and member function calls -------------------------------------------------- How to distinguish between instance-variables/locals/parameters/constants? In some languages that might be: this.instancevar localvar parameter CONSTANT Is there a way to make this/local use different syntax but still avoid the "this." thing? - "with" statement like in Pascal: (but it also leads to ambuigities) with this instancevar = 123 end - With sigills/prefixes .instancevar = 123 %instancevar = 123 m_instancevar = 123 .memberfunc 123 %memberfunc 123 memberfunc 123 # maybe all calls without an object should be this-calls? - With implicitly defined setters this.set_instancevar 123 set_instancevar 123 # with implicit this-calls when there's no object - With some keyword: our instancevar = 123 # related: typescopes our bgcolor = fromtarget green our bgcolor = fromtype green Main block ---------- Make simply programs easy to create: (the main file could inherit from SlulApp, and that could have functions such as `writeln`) main writeln "Hello" end (Disallow defining a constructor in this case?) File structure -------------- One-class-per-file can lead to lots of tiny files. Also, what identifier to use for files in subdirectories? But it is still really nice to be able to see which file a class is defined in by just looking at it's name. Maybe an implicit namespace is a good idea? And there could be some keyword for nested classes. If files have implicit namespaces, how to define instance fields and constructors? # should there be interfaces? implements Printable # must come before any functions or it gives a warning? int number bool flag # Should overloading be allowed? # Should constructors have a name or not? constructor new int number bool flag code ... end func do_stuff ... Extensability / API / Object Orientation ---------------------------------------- In most languages, interface types (for dynamic function calls) are implemented some some pointer (e.g. to some list of vtables). To make it possible to turn an "interface-less" class into a class with intefaces, without breaking ABI, it would be necessary to put the vtable separately. That could be done by passing the vtable in a "fat pointer" when passing around a reference to the object. I think that is how Go does it? Another (probably worse?) method could be to store the vtable pointer in an out-of-band structure, such as a ptr_address-to-vtable map in some thread-local area? Or, if arena-chunks are used (it might be better to use thread-local storage for arena allocation), then the arena chunk header could have such a tree. Or, it could be a list where each entry has a range (or bitmask) of addresses that it applies to (this would make objects allocated in a loop use only one vtable). A downside with this is that the vtables remain allocated even when not in use. A completely different approach to OO-interfaces ------------------------------------------------ Have functions return a "state" when the OO-interace should be called. But this would have to be a deep return (like from a co-routine) if the OO-interface is nested inside an object in a parameter. Can the need for "OO-interfaces" be completely eliminated? * For "global" interfaces, such as for logging, the function pointer could go into either the arena or in thread-local-storage. * For builtin types such as lists, there could be some sentinel value in the "header" of the data structure that indicates whether to use indirection via a vtable (e.g. for custom lists/maps). But it still needs to be compatible with objects that implement both a builtin interface as well as a non-builtin interface (or multiple builtin interfaces). Custom statements ----------------- It would be really nice to be able to create custom control structures etc. Problems: * How to distinguish them in the tokenizer? - it would actually have been "trivial" (exept for the "else" case) if functions had (). * How to handle following blocks, e.g. "else", "except", "finally", etc.? * How to implement it internally in an efficient way? 1. lambdas 2. an internal loop with switch-case of a return value, e.g. int rv; CustomCtl state; while (rv = custom_ctl_stmt(&state)) { switch (rv) { case 1: ... break; case 2: ... break; } 3. an internal loop, where the return value is a series of states? (which has the potential to decrease the number of function calls, but but on the other hand increases complexity and might increase the number memory access,