--- /dev/null
+
+Concurency is important to make full use of modern
+hardware.
+Lots of tasks really don't benefit: they are boring
+data manipulation and UI management. But when you
+have a CPU-intensive task, you really want to parallelize it.
+
+And you want data-structures that allow this.
+
+But if you don't have all that many CPUs, you want very
+light-weight tasks to do the work.
+
+We definitely want data structures like bag and lists that
+can be accessed concurrently safely, and we want dependencies
+to be sufficiently clear that some normally-sequential steps
+can run in parallel.
+This is where message passing comes in - having a 'channel'
+that is used to pass a message from one code block to another
+can then be a simple variable, or can be a synchronization object.
+You might need a lot of such objects, so they need to be created
+dynamically - like stack-frames.
+
+I probably need to experiment with some specific examples:
+ - quick sort
+ - unordered search
+ - image scale
+ - ..
+
+The other perspective on concurrency is the need to be non-blocking,
+even when using a single CPU. This needs to be more explicit,
+probably with a fork/join model. This could look like
+a 'continuation' where we store code in a variable, but
+the code starts running immediately and the variable changes
+value somehow when the code completes.
+
+
+Having thought about this during my run this morning, my current position is:
+
+1/ we have locking primitives, fields which indicate what lock protects them,
+ and pointers which are typed to say what lock they own.
+ Locks are generally nreader-xor-1writer and spin or wait on a queue,
+ possibly dedicated, possibly chosed by hash.
+ a refcount is a lock that is mostly in the nreader state.
+ A 'writer' which frees the object might get queued at object creation.
+
+
+2/ we have "completions" in the language which are a bunch of code
+ combined with some data state - a bit like an object, but described
+ dynamically in-line.
+ A completion can be created easily and might be:
+ - run immedately
+ - stored and run later
+ - run asynchronously. In this case the returned value is a queue
+ that is easily waited on.
+
+
+ A completion might return a 'channel' which returns a seqeunce of values.
+ In the run-immediately case, this is like a loop.
+ In the stored-and-run-later, it is like a generator.
+
+
+A completion combines code and data. The data is sucked from the
+environment. Any borrowed pointers need to have their owner too, and
+ownership needs to be duplicated or moved or whatever.
+For a generator, we need explicit "use" calls. So want them for regular completions
+too.??? or is "return" cleaner because it doesn't go to a channel exactly...??
+
+I need a clean syntax for this.
+
+foo := continuation
+? no, I think that looks weird. I want it to be obvious from the start.
+But where do we store the handle?
+
+ cont foo:= code
+
+ fork foo:= code
+
--- /dev/null
+
+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.