Languages
Francois-Rene Rideau
rideau@clipper
Wed, 14 Dec 94 2:17:58 MET
">>>>" is me (Fare)
">>>" is JVS
">>" is me again
">" is Mike
> The primitives are
> implemented by the kernel, and should be with us forever?(!). Everything
> else builds on these.
Yes and no: Yes, we have something (that *you* call the "kernel", but that
I call some very basic low-level part of the library) that implements our
primitives; but *no*, that is not the kernel in the sense that it would be what
defines our system. We are not defining another ms-doggish assembly-level
operating system for some virtual machine; we are defining some new kind of
portable high-level system. Nothing should prevent us to eventually redesign
the LLL (i.e. the set of primitives) and still use "our system" so that a
simple recompile will have the same applications running !
Which leads me to another topic (to be discussed in another message thread):
what kind of API will we offer to users in what languages ?
> I get the feeling the grammar and generic
> constructs Fare is talking about is more OO and aimed at bridging the HLL and
> the kernel.
To me, the kernel is in the HLL constructors and abstractors, not in the
LLL primitives: the former define the system behavior; the latter only
implement them. Humans will manipulate the former; the latter is for computer,
and can be automatically re-generated or translated...
> That may not be possible and may actually cloud our judgement if
> me mandate it. As was previously mentioned (Johan?), heterogeniety has
> its place.
Again, I'm not against any kind of heterogeneity, but against compacity:
however heterogeneous the objects, if there is some way in which these
objects may communicate, we shall provide it.
>>> So, what primitives do we need? I would suggest:
Note that what is useful is not particular primitives, but the set of
operations generated by those primitives. Which exact generating family of
operations is chosen depends on other criteria: simplicity of use
(orthogonality), compactness of code and execution speed.
>>> A. "Passive items" -
>>> 1. constants
>>> 2. variables
%% And why do you call it "passive" ? Functions can be constants or
%% variables !!! Being constant or variable has *nothing to do* with
%% being active or passive...
> I don't want to put words in Johans mouth, but, passive items do not act
> on others. A variable (passive item) does not modify others, code does...
No ! No ! No !
A variable or a constant may well contain some function or other code.
Shall I repeat myself ? The "%%" quoted lines say it all.
Why shouldn't I be able to assign "click_event_handler := my_click_handler",
or pass a function as a parameter to a generic sorting algorithm ? Have you
never seen Scheme, Lisp, FORTH, ML, Miranda, BETA, SELF ? Have you never heard
about functional programming ? I'll let jch (some friend of mine who's just
joined the list) expand on functional programming; but SELF or BETA
object-oriented programming seem highly isomorphic to functional programming
to me...
> I believe by infusing functions and constants into the argument just
> confuses the issue unnecessarily. I think we all understand Johans point.
I think that arbitrarily differentiating variable and constant functions
from variable and constant terminal values is pointless and is what actually
confuses the issue quite harmfully; you're victims of an a-functional
computer education, and stupid harmful a-functional languages like 'C';
ok you're victims, but do not make new generations of victims by teaching the
same horrors to the users of our new system.
>>> 3. blocks of memory
>> All computers do not have a linear memory model (see hardware LISP
>> machines, or software virtual machines of any kind that may be the
>> underlying system).
>> That's why I think that memory blocks are some very low-level
>> thing whose use should be decided by the optimizer (whether human or
>> computer), not the high-level programmer (sometimes the same
>> human/computer, though); but in concertation with him (high-level
>> annotations may help the optimizer decide).
>> I'm not saying that our LLL won't provide these, but that it
>> shan't be a part of the grammatical kernel of our system, just one
>> of the lowest-level
>> (and very important) of the standard vocabulary (library).
>
> Again, you're mixing up the library part with the kernel part. One
> part of the kernel says to another, I need some mem, give me a block.
> That's pretty fundamental.
You're confusing kernel and device drivers. Actual memory move is
let to some hardware interface -- a device driver. There should be no
such thing as a monolithic program that everyone calls. Just have
everyone do things directly, call directly the good other object it
needs, etc. Some object uses a (persistent) memory object (which in
turns uses a raw memory object); it also uses a sound object, and a
graphic device object (which calls the hardware memory object to access
video memory). All the calls are *inlined* by the compiler (which is
automatically activated at run-time if needed). No need to inline the
calls by hand in a particular system to obtain some static, monolithic,
unmaintainable, badly interfaced, program.
My motto is "be dynamic and generic, never static or specific".
Staticism and specifism are for perfect, finished works, not for an
OS which is the basis for infinite unknown extensions: human work.
So we must be clear: are we talking about specifications or
implementation ? I agree with what you say about some implementation;
but we shouldn't make the implementation the reference or we are just
ms-doggish.
>>> 5. 32 bit integers
>>> 6. reals
>> These are fine; but should really be included in the standard
>> library, not the kernel: people may wanna use any kind of integers
>> or reals, with any size, fix or floating point, etc. On the other
>> side, the computer has got a little number of different builtin number
>> sizes. We should allow transition from one to the other, thus support
>> both approaches. There should be generic *library*
>> routines to handle these...
>
> Again, what it boils down to is you need something at the very bottom
> (read kernel). And we need to agree on these. You can't create a
> bottomless argument (we'll leave the word sizes up to the compiler) in
> order to not trap yourself into a compromise situation. Same again for
> library vs. kernel. These are kernel issues and cannot be floated on top
> of the compiler. I completely agree with Johan about establishing
> primitives (although I have my own slightly different version =).
I agree our implementation dependencies will be 32 bit, etc. But we
shouldn't ever build the whole system around these. That is, I talked
about implicit choice by the system; the implementation will thus reply
32 bit integers when asked for its standard fast integer type; but we
shouldn't explicitly make everything 32 bit.
>>> 4. pointers
>> Here should be the basic abstraction of the low-level side of our
>> system. The low-level begins with pointers. Local pointer size is
>> host-defined;
>> pointer size inside a file may be file-defined (or sub-file defined).
>
> Nope. Remember we're talking LLL. Your HLL may create as many
> abstractions as it wants until it runs out of memory or is blue in the
> face. But we're talking fundamental/primitive instructions here!
We're not talking only LLL, but the specifications of some generic
binary encoding format that must be able to express any kind of objects !
Even if we were building "only" a LLL, this LLL is meant as a portable
target language for compilers, not as the the foundation language for
all further user interaction. Again, we should be able to replace the LLL
without changing the semantics of the system: persistence, distribution,
unity, high-levelness.
Moreover, not differentiating pointers and integers scrambles any kind
of simple and efficient garbage collection, while GC is of utmost
importance in a persistent problem...
>>> B. "Active items"
>>> 1. verbs
>>> 2. "user defined functions" (I will call these "friends")
>>> 3. "objects"
>
>> I see no clear distinction between these...
>
> Again (again again again), I believe your mixing HLL with LLL. The HLL
> may be able to view all of these together, but to get something off the
> ground, we need to establish our basic command set (verbs). A friend (if
> I'm reading this correctly is a chunk of code/function/method whatever,
> and an object is a convenient way of grouping these together. Am I on
> target Johan?
Why not call these by their name ? Instruction, code chunk,
abstractions... Then we have not advanced much. Of course there are
instructions and code chunks; but the SELF model shows that you may
obtain such kind of code with on-the-fly compilation of some higher-level
abstractions; so that most of the time, such compiled-on-the-fly assembly
or interpreted code or just sufficient. For the remaining 1% of time, 99%
can be obtained by tweaking the compiler options, and the remaining 1% of
1% is for hand-written assembly code.
So what are we argueing for actually ?
I just want such kind of instructions/friends be part of a (standard)
module for our system, and not have it (or actually have anything)
hard-wired. Nothing should be hard-wired. Everything should be plugged, and
unpluggable (least you furnish the solder-iron plus manual and plans).
>> I completely agree there is heterogeneity; what I want is smooth interaction
>> and communication between different objects, and eventuality of a direct
>> access between any indirectly linked universes.
>
> That may not be possible. Remember everything goes to machine code and
> runs with the kernel.
Everything will *dynamically* go to machine code, and the dynamics is
controlled by the HLL. Again, there is no such thing as a kernel. Where
does it begin, where does it stop ? The "kernel" is a non-sense concept,
when it isn't monolithic, and it's a harmful concept when it is.
> All that matters is that the kernel provides
> services for different processes to communicate. It doesn't make sense
> to stipulate a development environment (say MOOSE) to HAVE TO be able to
> talk natively with a VBX application. The LLL/kernel provides the
> functionality, use it who may like it!
No hard-wired processes, no hard-wired communication. Chips are
hard-wired enough. Why build some virtual hardware ? Let's build some
real software, and allow full software freedom by not hard-wiring any
calling convention, etc, in the specifications (but of course, objects
will communicate iff you can find the correct plugs, i.e. you can
ultimately find a common calling/communication convention).
> How do we get around ASCII in the kernel for naming things? I'm just
> saying a name is a length delimited string of bytes. Put in ASCII if you
> please.
Why not have just objects of any type to name others ?
After all, you'll manipulate names using some kind of pointer or token.
Why not allow any consistent kind of names to be pointed at or tokenized ?
Let namers be just some association from a name type to a named type...
>>> Variables would be locally defined and could be allocated ANY value.
>> Let's have variable scoping like in *any* good language (i.e. not C), with
>> more or less local things; but what imports is: if you "see" an object, you
>> access it, whether it is implemented as local, remote, distributed, or
>> whatever...
> Here's my little speech about scoping; I propose we have the union of a
> method and data. If you want the data, the ONLY way to get it is to ask
> the method.
Again, why differentiate arbitrarily kinds of objects ?
Let us only say that there are internal subobjects and exported
subobjects. That's all. Being exported or not is orthogonal to being of
some functional type or not...
> Methods are named and are listed in the namespace. This way
> we don't need complex scoping rules, permissions, etc on the LLL/kernel
> layer. (a method may be huge and have hundreds of variables arrays, etc
> in its scope, or it may be 20 bytes of code and an integer). There are
> no pointers to distant objects. If you want something from a far away
> object you send a message to its method, it pulls the data, and you get a
> message back (all using agents of course =). Now all we need is for the
> kernel to support message passing/agents. KISS!
You get it. Your stuff is defining local scoping, and letting the scope
resolver outside the action semantics... Again, let's not call the LLL the
kernel of the system (but you may talk about the kernel of the LLL, which is
*not the same*).
>>>[about blocks]
>> Firstly, the user shouldn't even see blocks -- this should be
>> transparent !
>>[examples]
>> Blocks are fine for implementors, and that's all. When I use the
>> system, I never ever wanna see blocks or pages. Let the system hackers
>> have all the fun, and not disturb *unwilling* users with implementation
>> dependencies that only annoy them (if they're willing, that's another
>> problem: we *must* provide those ones access to it, as long as it is
>> secure).
> Separate the users from the progammers (see previous thread). A block
> will be a system primitive, users won't see it! Maybe even HLL
> programmers won't see it. You can't use those arguments against a
> low-level primitive.
Yes I can. Blocks should be provided in some abstracted LLL library, not
as a standard primitive of the LLL kernel. The LLL kernel should be minimal;
you told it yourself. And the Scheme vs. Lisp or RISC vs CISC (and MISC vs
RISC ?) experience show that you should never multiply language axioms.
KISS. Blocks will be included in some system library (again, never worry
about efficiency -- human/computer optimizers can do it well for you later).
The library will present blocks as some quick and simple implementation of
arrays -- a point-modifiable version of functions from an index set to
another set.
> I'm for blocks, but a slightly different version which we'll discuss later.
Please open a separate discussion thread, then...
> The kernel does not understand abstract operators. Maybe it would
> simplify things if we replaced every occurance of kernel/LLL with "Our
> new microprocessor, the 80686". We need to settle on compromises, we
> cannot skirt the issue by saying keep it abstract.
> A pointer is an integer that points into a block. Fine with me!
Not fine for the garbage collector.
Have you thought about the garbage collector ?
How will it find pointers and not get mixed ?
How do you intend having it. Count-based ?
We need have a way to differentiate integers and pointers.
So either we have different stacks (which leads to further
complications) or we lose one bit to differentiate them (at least
on stack, at time when garbage collection may take place).
>> Let's have some LLL-dependant instruction set, undefined at high-level.
>> This way, we allow further change of LLL, or using any kind of language
>> (particularly assembly, or Scheme, or the SELF virtual machine, etc) for a
>> LLL (if you're masochistic enough, you could use plain C as a LLL).
>
> Nah. The LLL is what glues everything together. I'm in Bangladesh (Year
> 2005) using some leftover Pentium system running tunes v1.0. I've got
> all my little objects humming along together (remember everything boils
> down to LLL) when I get an internet++ hookup. All my little objects jump
> for Joy as they realize their ability to migrate onto a nearby SparcStation
> 101010. Alas, because we did not standardize on one LLL instruction set,
> they are incompatable.
>
> Don't let this happen to you!
We will standardize the LLL; only we say that, yes, this standard is
arbitrary, and, yes, we may upgrade anytime to a new, better standards
that we'll design before 2005; but programs using the older LLL may
still work after proper translation/interpretation, and we'll provide the
necessary modules for that (or if you're using some old processor which
had a native module for the old LLL, you can use it directly).
As we already noticed, the vocabulary frontier is having us argue when
we agree. Who's maintaining the glossary project, already ? So our arguments
are settled once and for all...
> Ca depend. We're mixing high and low again. All the kernel needs is a
> way of receiving a chunk of bytes, and passing them off to a decomposer,
> to make sense of them. Probably the decomposer should be part of the
> kernel, breaking out our methods and data and giving the agents in the
> packets some execution time.
>
> Want another layer on top of that, add your own HLL flavor.
>
> The inter-kernel packet format is very simple. You can build anything
> on top of that you like, but don't impose HLL constructs/desires on what
> is a simple protocol for transfering info between kernels.
The problem is the semantics of the decomposers; how they are added or
selected, how the user can interact with it, etc.
Linux has its decomposers: they load a.out, coff and elf files (ok,
not for our virtual machine; only for the local processor), and root may
add kernel modules to support more. And nothing prevents you from writing
your own user process that will load any kind of file.
You see the difference:
That's not how I see it. Everything is user-definable to me. It's not
the LLL kernel calling the decomposers, but the decomposers calling the
LLL kernel to me. There is no such thing as a "system kernel"; there are
only object freely interacting, the LLL being one of them (a standard one).
>>>> Also note that we may also change the format, if one day we find
>>>> ways to considerably enhance it by using uncompatible techniques.
>
> Nope, I'm with Johan. Get it right the first time.
How can you be sure you're right ?
Of course, you'll do the best you can.
But how can you be sure nobody will never ever be able to
do even better ? You just can't. We're humans, not gods (you say it
yourself later); we may fail. Let our *possible* failures not impair
definitively the system. Let the system be *open*.
> Fat binaries encourage obesity. I'm for a pure LLL distribution.
And how will you distribute the latest hyper-fast bitblt routines ?
Or 3D game engine ? In LLL ? Let me laugh. Highly optimized code is needed
in 1% cases; but when it's needed, you can't escape it without greatly
reducing system performance. And recompiling with hyper optimizing options
is sometimes not enough, or takes so much time it's not worth it.
Fat is not for the 99% code that needs not be fast or may be compiled
easily. Fat is just for that irreducible 1%. It is *needed*. If you're
system does not support it, it will suck rocks.
> Actually I like the other version of KISS;
> Keep it simple studid.
> It forces us to recognize we are not the GODs of PROGRAMMING but are mere
> mortals. Do it simply and do it right.
>
> Do not overextend our selves and fail to accomplish anything.
Ditto.
-- , , _ v ~ ^ --
-- Fare -- rideau@clipper.ens.fr -- Francois-Rene Rideau -- +)ang-Vu Ban --
-- ' / . --
MOOSE project member. OSL developer. | | /
Dreams about The Universal (Distributed) Database. --- --- //
Snail mail: 6, rue Augustin Thierry 75019 PARIS FRANCE /|\ /|\ //
Phone: 033 1 42026735 /|\ /|\ /