Rough draft:




-------------------------------- Vocabulary ---------------------------------

Let's say specializer/mixer instead of optimizer.

Humor, simplicity, ...

---------------------------------- French -----------------------------------
Implementation is best translated in french by "realisation".


------------------ Mid Level Implementation Annotations: --------------------

-- A --
directives:
 __code_implemented__	general directive meaning that something may be
			implemented as executable code to increase time
			performance.
 __data_implemented__	general directive meaning that something may be
			implemented as data to simplify code semantics.
 These are general directives; they do not say exactly how the object will
be implemented; they just tell the specializer to think in that direction
first.

examples:
* let x be __code_implemented__ in { 1, 2, 3 }
 It will produce three versions of the procedure where x is defined; one
for each value of x

* let J be a __data_implemented__ involution of the Multipliplicative Group
of Z/nZ{ n=256 }

* let K be a __code_implemented__ exception (* the standard way of doing it *)

Notes:
* This has to do with factoring optimizations in the case of a run-time
constant (i.e. something that remains constant long enough (=is used many,
many times with the same value) for the program to be accelerated by
folding it).
* Data implementation is implementing the object as data for another one;
that is obj0 is implemented as specialization of obj1 by data obj2.
* Code implementation is having a variable as function of the program counter,
and is useful if it doesn't lead to too much copies of specialized versions of
the code, and of course if the specialization brings good results.
* Code implementation of increasing data is useful when combined with the
code corresponding to data below the current one being discarded. Such code
must be really discarded (i.e. for all instances of the object in memory) for
this optimization to be useful. This is the case when a program initializes
itself (for example, when the OS looks for hardware features and discards
drivers that aren't susceptible of being useful, or when a drawing software
initializes sine and cosine tables or such adapted to screen resolution, etc).


directives:
- specialize_for{ (distribution of bindings) }
- optimize_for{ (distribution of bindings) }


------------------- Garbage collecting and pointer problems ------------------

* Garbage collecting is necessary when data sharing make it impossible for
user objects to determine when an object is truely unused; then the object
server must manage this issue.
* In the (general) case of multiple object servers (and particularly in a
distributed or multiple system) (by multiple, I mean multiple subsystems
share the same resources, as with DOS, Apple ][, etc emulation), a GC
occuring in one server may lead to GC occuring in all servers (this is a
BIG problem for world-wide systems...). The inter-server gc must be adapted
according to speed and delay of inter-server communication, and may vary
according to server pairs. Thus, object servers are grouped in universes
of servers having common GC; GC accross universes is done by having
bidirectional pointers.
* The system must still live, even if a garbage collecting is on.
data being initialized must allow a GC occurrence at ANY time, even
while swapping pointers in a doubly linked list, for instance. Thus,
either critical portions of code must be able to prevent interrupts, or
the GC must be aware of the system being in such code portions and act
accordingly (=exit portion, or have portion-dependent GC; heavy !).
* Reserving resources: some time-critical or system code must also go on
working even if a GC is occurring, or no more memory is available. That's
why priviledge objects may reserve memory or other resources so that in case
of need, they don't have to rely upon GC or swapping. Note that sometimes, you
need only escape unavailability, but would like to have resizability. In those
case, you may still use GC, as long as the minimal size is reserved, and that
the GC process won't disturb you. This is the case when reserving pages of
physical memory. Pausable GC, i.e. the GC ensures that memory won't be
unavailable for more than a small time is also a solution. Such a GC will
certainly be mainly done through paging so that's almost th previous solution.


------------- Isolating or merging objects (=saving, loading) ---------------

* We must define the limits of a non-elementary object (i.e. object that
includes multiple parts with pointers to each other and to external objects).

----------------- Sharing objects between multiple users --------------------

* each user can add attributes to objects. These attributes may in turn be
read or modified by other users (according to the object's sharing policy).

* The first problem is how to implement these so that reading an added
attribute is not much harder than reading a "normal" one.

* In case where a user want his personalized object to evolve with another
user's version (e.g. the system administrator's version, etc), the problem is
that the user may not want exactly the other user's version, but a modified
version; there must be a system to log changes and apply them if they do not
interfere with the user's one; if the changes interfere, there must be a
system to rule which will win (it's safer to memorize the old user's version
before the modification); in case the modification is "equal or better" to
the user's own, it must be done (e.g. if the modification was done following
a suggestion from the user).
  Sometimes, the "original" file isn't even completely trusted. Thus, not only
should a copy of a "working" version of the user-customized file be maintained,
but it something should be made to allow the user to go back to it and manually
make any modification just in case.


----------------------- Distribution and version control --------------------

* As an object spreads accross the world, multiple copies of it are created;
some (a few) of them are modified, in good or ill. To manage the multiple
versions of an object is the role of the version control part of the software.
** Wish List
- newer better versions should replace older ones
- in case the new version may have lost data important in the old one
(=bug introduced, feature destroyed, or quirk disabled), the change must be
reversible until eventually proven right by everyone concerned.
- particularly in case of automatic update, security (1) is also a major
constraint. Thus an official maintainer is necessary for each evoluting
world-wide object (see the FSF and GNU software, etc).
- Now, there are cases where different people maintain concurrent versions of
the "same" product (example: MS- or DR- DOS, GNU or lucid emacs, the great
variety of compilers for the C language or any other, etc), whether because of
financial rivalry, or the lack of some features in the other versions, or the
unavailability of the other versions (again, for financial reasons, or any
kind of net failure). There must then be a system to have the version diverge
(each isolated portion of the net may modify its version of the software),
and to merge versions again when the net has been (momentarily or permanently)
reconnected.
- Each maintainer must export release versions, and amount of change between
consecutive versions and previous major release version, frequency of change
in released code, mechanism of update (=where to find most recent code),
merging decision mechanisms, level of testing of the release (=alpha, beta,
gamma versions).

(1) Security: Errors or piracy should not allow introduction of loss of
information or abuse of system resources, or "security holes" that would
allow further errors or piracy to achieve more easily such loss or abuse.

-------------------- Persistence and Disk consistency -----------------------

* The Disk Object-System must ensure maximum disk consistency:
most of the time, the disk contents must be consistent.
In the best case, this means that when the disk is not writing data (i.e.
displacing its head or waiting), the disk contents are consistent.

* Consistency means no existing object is overwritten before a new version
is made available. A strong version will not even allow overwriting by the new
version. Then, a special pointer in permanent battery backed CMOS memory will
show the main block.

* A special indicator in the CMOS memory indicates that file systems should be
checked if it is not present, or does not correspond to some value.


---------------------------- Proposed file system ---------------------------

* Files are physical representation of objects on disk. They must be
isolated (or at least isolatable) from the in-memory structure and location.

* The system will allow efficient allocation of both big or small files. It
will allow several cooperative or preemptive compression schemes.

* Actually, the file system will be divided in three layers: the blocking
layer, the filing layer, the compressing layer; the implementation of these
layers will mix them somehow to increase performance, but that's a compiler's
issue (even if code is hand-compiled to a low-level language like C).

* The blocking system will divide the disk logically in cylinders; a cylinder
cylinder is divided into blocks sized according to the processor paging
in used architecture (4KB for the i386, 8KB for the sun4, etc). The remaining
of the cylinder (if the cylinder size is not divisible by the block size) is
reserved for use with out-block allocation.

* Sectors may be unavailable in a cylinder due to physical error or a
reservation by another system resource (for example partitioning compatible
with another OS). Cylinders need not have all the same size. This can be
implemented by having unavailable ghost sectors in smaller cylinders...

* The filing system divides files into blocks; If file size is not divisible
by block size (in particular if file size is non-zero and smaller than block
size), the remaining is put into a special out-block file that uses the extra
sectors together with regularly allocated blocks.

* A same file can have different compression methods and strategies.

* Compression methods include no compression, huffman compression with
precalculated or included table, lempel-ziv compression with or without
huffman compression above, etc.

* compressed file may or not contain physical <-> logical pointer conversion
tables for easier random access. Compressed file may be completely uncompressed
when actually modified, and eventually recompressed only if closed by all
modifying processes.

* Files of some length may have a measured life, change rate, expected rest of
life. Compression strategy is done according to this data. Files that are
mostly read-only and/or that haven't been modified for a long time are
automatically compressed. If the file is long and with random access (as
opposed to sequential access), it is divided in compressed blocks such with
pointers to make correspond physical and logical blocks.

* All file-system level compression may be disabled with a file local flag.
This is useful to save time when the file is already compress, and further
compression is either unuseful or harmful, and spends time needlessly.

* Logical objects components can be separately compressed, opened, etc; As the
file system manages well small objects, the saved object must just export
explicitly the separate fields as being separately compressed.

* If multiple disks are available, one may contain swap and system pointers,
the other actual data.

* a checksumed CMOS indicator may indicate (if valid) possible states at
shutdown time: stopped (ok), writing data (must return to previous data),
data written but not pointers (may discard old data)

* If a great amount of frequently changing persistent data is needed, a
special sector may be reserved in each cylinder to contain the latest version
of these data, with a pointer to the latest version in CMOS and/or the date
of the version in each. This method may prove expensive if cylinders are small.
Having one such reserved sector every n cylinders is cheaper, but requires
seek time to be reasonably smaller than demanded update cycle. Less or more
than a full sector may be reserved each time, if the file system is written
accordingly (i.e. reserve the beginning of the per-character allocation).

* Automatic disk "compression" (block grouping) can run as a back-ground
process, grouping in priority read-mostly files.

---------------------------- Naming objects ---------------------------------

* First name the universe, then have a universe-dependent name.
a 64 bits number should be sufficient for each field, and may include a
key.
 
--------------------------------- Kernel -----------------------------------
* The kernel is the smallest part of the system that can consider itself as
an object. It must then be both an object server and an object inside it.

-------------------------- miscellaneous ------------------------

- The standard object server has self-adapting capabilities: objects
dynamically divide between attributes and functions; attributes dynamically
divide into dictionary-bound and reserved attributes.
- a = x+1 <!=> a = [x+1] <=> a = [x]+1  (where [o] is current value of
variable object o)
- implementation must group mutually heavily dependent code do achieve
better instruction caching.
- A user can customize attributes: Either he uses an object-external hash
table for objects with few added attributes, or he adds a personal
user-customize attribute to any object he wants; Then, the attribute manager
will be aware to look in the hash table first, then look (recursively) for
user-customized attributes before to use standard attributes.

------------------------- implementation ------------------------

- A generic thread object has Activate and Unactivate methods. System-level
threads may in turn have sub-threads that they activate at will, etc.
A good system will never know that it is a sub-system, except by measuring
leaks in system resources usage.
- an OSL Thread saves perhaps registers, but most importantly the OSL
context. Among these, default stacks for each opened class. Among the classes,
int, addr, code, obj have reserved cells.
- non-preemptive cooperative threads may be a better implementation than
preemptive threads, as the one who accepts to give the hand away will save
only what he needs, and not all the machine state; moreover, he will leave
the machine in some kind of good (not intermediate) state such that all data
are valid (all pointer variables point to some initialized zone, etc).

-------------------------- optimization ------------------------

- optimizations may be published so that new optimized programs can benefit
from these information.

--------------------------- Interactivity ------------------------

- by default, nothing is really a constant, as its type may change.
- to force a constant to be one, the user must "compile"
- being a constant is something very relative to the object that sees
you. You are constant to the object if you don't change during the object's
lifespan.

---------------- Hierarchical Constraint Logic Programming ---------------

  Contrarily to the xxx article, we don't think the constraint hierarchy
should be linear. Of course, during the process of resolving the constraints,
the system may choose a linear extension of the constraint hierarchy. But the
hierarchy is essentially "parallel"; it's a partial order, not a total one.

  Different users may be thought as independent nodes of this partial order.
Each user controls sub-constraints. User interact when their sub-constraints
add or negate each other.


---------------------------- Programming Plan ----------------------------

- Build any objective implementation
- Build I/O
- 

----------------------------- Object semantics ----------------------------


* Universes

   There are Universes U of objects.
   Among these are the two booleans True=1={empty}=Yes and False=0=empty=No.
   Any object may be compared to a boolean.
   Some objects operate on some others, and may return another object or never
return. We note f A the operation of f on A, and abusively its result.

A =(C) B  ::=	for any operator f in C,  f A = f B if one of f A, f B returns
		a boolean
A = B	  ::=	A =(U) B

   see lambda-calculus et al.
   Note that different universes may well contain each other.

* Machines

   Now, we have machines, which at any moment, consider a finite subset of
objects in a Universe U, called the state of the machine. Among these is the
dynamics of the machine. Each machine modifies its state by having the
dynamics operate on the state, which forgets some objects and/or adds new ones
that are result of operations of objects in the previous state.
   Note that a machine's state can contain sub-universes of U, and thus other
machines.
  

* Relations & Goodness

   Relations are special kinds of objects which always return a boolean.

   Considering a set of relations arbitrarily ordered, the state of a machine
is said to be good if all the relations would return true if operating on the
machine state. The goodness of a state is the subset of considered relations
such that all relations above it are verified by the state. A state is better
than another if its goodness contains that of the other.

   A good dynamics is one that given some state will stop on a better state.
Some dynamics is better than some other if it always stop on an even better
state. Note that before it stops, the machine may well consider states worse
than its starting state.

   Note that finite machines will behave well only for a finite (but
expectedly large enough) part an infinite Universe. For those machines to be
good, we must restrict the relations so that they specify the machine always
consider a good finite part of the Universe.

   An actual computer will always be such a finite machine.


-------------------------- OSL primitives ----------------------------------

  Given a universe U, we may consider objects Oi inside. In OSL, we consider
some special kind of good universes. In these there are some standard objects
according to the goodness of the universe.

  A Multiplexed Universe contains tuples; there is an operator creating tuples
(Pair), and functions (Fst) and (Snd) such that for any objects A and B,
(Fst ((Pair A) B)) = A and (Snd ((Pair A) B)) = B.

  A Set universe contains sets; sets come in two flavours: recursive sets and
enumerated sets. The first ones are computingly more usable. A recursive set
is an object always answering Yes or No.

  A Class universe (U), contains classes (which can be identified by the object
IsClass), and each class (C) is a universe whose operation and some objects are
included in (made available to) the Class universe; among these is an object
(IsMemberOf C) that answers (Yes) iff an object is in (C). An object (O) is
always considered together with a class, that can be returned by the object
(ClassOf O). Any class (C) is of the class (Class). An object can operate on
another of class (C) iff its class verifies (OperatesOn C). A Class contains

  A Named Universe is a Class Universe that contains a class (Name). An object
(ObjectNamed N) may be associated to any name (N); different names may refer to
the same object. Eventually, each object (O) comes with at least a name
(NameOf O), such that if (N) is that name, (ObjectNamed N) is (O).

  The (Sequence) Class

  A Stack Universe contains a (Stack) class with (Push), (Pop)

  A Number Universe contains numbers, with the usual operations.

  A memory universe contains for each object a si

  An interactive universe contains input streams and output streams, each of
some class.

  An auto-coding universe 

  An effective universe is contains among others effective objects. Each
effective object can be rough data or rough code. If it is rough code, it has
a calling convention. Before using an object, the machine must change its
calling convention state; therefore, there are calling convention transition
operators.


#### Code separately the __Static__ "data" universe and the __Dynamic__ "code"
#### universe.
#### There is an axiomatic (system-dependent) dynamic object "clock" with
#### infinite number of state changes, and with grain finer than anything else
#### in the system.
#### Mutable data are part of the "code" stuff. Objects that mute, approximated
#### by f(clock)-periodic objects (( f is an integer function that bounds
#### up or down the time between mutations of the object ))

------------------------------------------------------------------------------

Unix:

- main server
 * user-based ?
	-> no internal inter-user communication :(
 * or suid root and changing uid to become client user as required ?
	-> security hole that many other people won't allow
 * or "intelligent clients" that perform user-level things ?
	-> 

 ==> To me, the final solution is neutral servers (you connect to a socket
    and/or to shared memory; in the latter case, a network client can serve
    as an intermediate to map socket calls into shm calls) with chroot
    moose rights, and intelligent clients, that do
    read/write needed global files/pipes/sockets/devices and/or serve as
    intermediate between different servers, and are able to launch a private
    server if needed (no public socket).

 ==> A client can save its objects and (re)launch another server with its
    objects in the same state as the previous one left them in. In particular,
    a priviledged client (owner/root) can

- The event driver, if required, will fork/lightfork the server into the code
 executer and the keyboard/timer/mouse/network event listener.
 See dosemu "dosipc.?" files to see how it does it. Try to change forked
 arguments to show the second task so that ps will distinguish the main server
 from the forked thing.

- 

------------------------------------------------------------------------------
VSTa:
- bad language ("C" -- yuck). That's easily correctible.
- no checking semantics. No typing -> VSTa is unusable
- particularly, everything is done through more or less standard names.
but a name is but noise and dust. Thus, VSTa is very unstable. Moreover, there
seems to be no alpha-conversion (renaming) mechanism. Yuck.

------------------------------------------------------------------------------
Not Names, but signatures with properties.


------------------------------------------------------------------------------
   The good trick to use preallocated memory with a routine that calls
the dynamic allocator: patch the jump table so that it will return the
preallocated memory block, then patch back the table.
   This means that the address of the allocator won't have been linked in.

   This leads us to the concept of hooks.

   A hook is a point where a user-defined function enhances or customizes a
standard software behavior, upon some event. The difference between hooks and
just event-driven routines, is that hooks may behave as filters for such
events, and the event will not look the same before and after the hook was
executed. That's why hooks organize in an arbitrary (partial) dependence order
(mutual dependence must be resolved at this state). A common event-driven
routine is one which does not modify the event on which it depends; for
example, assuming the system timing routine is ok, hooks depending on the timer
are just event-driven routine. They are hooks if they maintain some alternate
timer visible instead of the system timer to objects below. The concept of hook
is strongly related with the concept of user; depending on what you think is
the user, something will be part of the system, or a hook, or a sub-user's
object.

------------------------------------------------------------------------------

* Language: text is enriched when read by its meaning. Ultimately, only the
meaning will remain while the exact text will be forgotten or at least much
simplified.

* Language semantics: attributes may be given to word sequences. Then when the
sequence is done again, the attributes must be retreived again.

Example:  (polished> stone) >is< ((an> improvement) <over> (cut> stone)).
  then when we talk again about polished stone, and ask if it is an
 improvement over cut stone, the system must answer "yes". If we ask the
 system all it directly knows about polished stone, it must retreive that. Of
 course, the system may know much more things about polished stone. Firstly, a
 polished stone is a stone (unless stated otherwise in the definitions).

------------------------------------------------------------------------------

Unix:
- it's too clumsy. First build an API with lighter threads, signal managing,
file interface, special file (blocks device, socket, pipe, tty) control,
exec'ing external commands, calling routines from external object modules,
writing such object modules. Then, work inside that. Note: AAARRRGGGH ! I
realize preemptive light threads are undoable, unless we have an interpreter !
So let's have an interpreter.
- A way of using a very simple API is working with only stdin and stdout (or
command line redirection of these). External programs filter stdin and stdout
to multiplex i/o (e.g.: sh as stdout interpreter), a named pipe as stdin,
with feedback from the stdout sh to it...

SI:
* No "Class" attribute, just a set of standard attributes: memory manager,
priviledged aspects, other aspects, etc.
* An aspect of an object O is the interface of another object O1 such that O
is a refinement (specialization, implementation) of O1.


i386:
* Use Relocatable zone between 1GB and 3GB only. Thus pointer values between
-1GB and +1GB are constants, and can be used as integer values too !
* 

pcore:
* Use a byte compiler to a 
* use mmap. But must be able to trap faults, or checking for overflow will
have to be done. Else same as i386 (?)


Both cases
--------------------------------------------------------------------
HL:
Actually, a class is an aspect of the object among others. Each object is part
of infinite number of classes.

LL:
The LL class describes the implementation of the LL object.

------------
The memory is divided into pages of objects having the same sizeable LL class.
example: strings, cons cells, class-preceded objects, etc. Big objects have
their own set of pages.

The (universal but clumsy) clad LL Class has consecutive cell fields:
- annotations (linked list of attribute <-> value)

------------
Pretty printer for in-memory objects: ???

------------
event programming is near functional programming in that instead of
reading an event E from an input with side effects to compute the value of
f(E), you directly ask the calculus of f(E) without visible side effect.
Of course, f may have side effects, but that's one side-effect less.








------------------------------ Buffering --------------------------------------
A buffer is an object that allows to connect an output-driven data producing
stream to another stream.
filters the output of an object so that it can
become the input of another one (so that it transforms an output-driven
stream into an input-driven stream).

A buffer is defined by two functions:
* when to block the writer	(if he wrote too much data)
* when to block the reader	(if he not enough data is present)
  The first condition to be filled, is that "enough" data is less than
"too much" data.
  Then, the writing object closes the buffer end, there is no more blocking
for the reading object; whereas if the reading object closes its end, the
writing object may be killed because not needed any more (not the case if
writing to more than just the closing reader).
  New problems arise when


that must be compatible in one way:
- both the writer and the reader can't be blocked
- if one flushes his part, the other must be unblocked





Defaults
-


------------------------------------------------------------------------------
Memory manager:
* Generic MM

* MM Page Allocation Layer:
 getting consecutive pages of virtual memory through MMU,
 moving them, copy-on-write, etc.

- BIBOP (da lulla): BIg Bunch Of Pages.


------------------------------------------------------------------------------
Word-code indirect threading
* opcodes are 16 bit tokens.
* threading is achieved using a jump table.
* Each thread has its own jump table, according to the modules it opened.
* Jump tables are shared by pages !
* That is, each page has PAGESIZE/POINTERSIZE (1024 for the i386) entries,
 so modules allocate opcodes without breaking page boundaries.
* This gives a limit of 65536 different opcodes and 64 opened modules for
 a program.
* Dynamic opening of modules is then forbidden (I mean during execution;
 all this is done at program loading time)

------------------------------------------------------------------------------
Sometimes, doing things immediately instead of doing it partially
saves memory. i.e. linking a process entirely instead of linking each object
lazily at its time. This saves memory, unless the linking tables may be
shared or swapped off memory.

Thus, when linking an object in a module, all the module is linked in.