Types have a per-module namespace. This is pre-populated with int i8 i16 uint u8 u64 etc num float f64 f128 Bool byte char string Types can be added with: struct name: content record name: content enum name: content class name: content name is optional, and can list (parameters) and /attributes Types can be constructed with name(args) parameterized type name^ reference type name[size] array type (args:: args) procedure type (args:: type) function type The content of struct and record are a list of: fieldname: type or fieldname/attribute: type 'attribute' can: indicate endianness - bigendian littleendian hostendian 'const' ?? identify a refcount, protected by a given lock?? For enum, content is list of name = value where "= value" is optional Pointers: to assign a pointer, use foo = stuff to update what the pointer points to, use foo^ = stuff to get a reference to store in a pointer.... references are either borrowed or owned. a name defined "type^" is a borrowed reference, a name defined "type@" is owned. borrowed references may be taken of anything, but only remain defined as long as the owner remains defined. owned references can only be taken of ownable objects, and remain indefinitely. There are various ways to own an object: - refcount or lock - ownership of a containing object. - ownership provided by class method non-type names (vars, constants) can be introduced with const prefix: name = value; ... func: name(args::type): statements proc: name(args::result): statements main: statements init: exit: enum name: values Plan: decide on data structure different types can't really be handled by a big switch now, I probably need and object with function pointers. free_value(), vtype_compat(), val_init(), dup_value(), value_cmp(), print_value(), parse_value() parse_value only needed for args - str and num val_init... print_value - only needed for print and code-dump dup_value - needed until pointers can make sense vtype_compat - needed for various things value_cmp - needed until we have object behaviours pre-defined Bool int - sizes char string array I think I need to disassociate the type from the storage. So a 'value' is a parsed constant, but something new is needed for the content of a variable. const struct ---------- I currently have an enum of types that is used to test compatability and for propagation. This needs to change .... I guess I need a struct type* What goes in it? - name - scalar/record/struct/array/pointer/func/enum - other details. Do I need forward declarations? Maybe I can just be lazy and require everything to be declared eventually. That isn't sufficient for: - mutually recursive functions - mutually recursive structures What about unions ??? blend with enum: a tag with fields? struct name: x:int; y:int .Bool.true = a:char; b:char .Bool.false = ...... Are enums just a fancy way of doing 'const'? I could have const: a=1; b=2; c; d which defines module-wide consts. And separately have enum foo: a, b, c which defines consts foo.a foo.b foo.c But I don't really like foo entering the val namespace. If bar:foo, then bar.a could be true/false depending on value of bar. bar.a! could set it?? bar.a=true? var = .foo.a How do we allocate new objects? new(type) ??? ptrname = new ?? new(ptrname) ptrname := new(type) Maybe ^= assigns a borrowed reference, and @= assigns an owned reference. allocating isn't really a top priority, so I should just focus on non-allocated types.