Requirements for the Tunes HLL
Basic Principles
-
- Genericity
All the next features must be included in their fullest genericity.
No arbitrary restriction should be added to the syntax or semantics
of the language.
In particular, the ability to use a feature must be actually independent
of the ability to use another one whenever they are theoretically orthogonal.
We need genericity to obtain maximal software reuse and compression.
- Uniformity
There is a Unified way
to manipulate computer abstractions. All computer abstractions are made
equal in the same whole system, whether give them the name
object,
function,term,
pattern,
foo,
bar,
or whatever.
Code chunks, functions, classes, symbols, attributes, are equally objects.
We need Uniformity to achieve the simplest possible semantics for the system.
- Dynamism
A computing system is to evolve, to learn and
to adapt, to interact with the human world, not to sit there and stay the same.
Hence a deepest feature of its interaction language must be dynamism;
that is, new objects of any kind (we saw already that somehow there was a
generic kind) may appear or become obsolete at any time.
- Higher-Order
You may abstract any subterm in any term of any order, to obtain a function
of a higher order. Variables, integers, types, or functions parameters,
function return values can independently be of any kind and any type,
including variables, integers, types, functions.
We need higher-order to achieve maximal power, because if we don't,
other systems will have to be built on top of ours nonetheless,
and our system will be yet another sucker system.
- Purity
Pure code (with no side effect), and read-only data, should be recommended and
favorized. Also, The language semantics must not depend in any way on
the peculiarities of today's computers (e.g. size of binary words or
characters), which does not mean it cannot interface to it,
which it should do very easily.
Purity is to be encouraged, because it leads to much cleaner semantics and
much more efficient implementations when it comes to distribution, object
sharing, and parallel optimization.
- Lazy evaluation
Evaluation is done only as needed.
Lazy evaluation is needed, because only it allows so much things that
strict evaluation forbids, and simplifies many a program's structure;
for the usual argument: if you don't implement it, people will reimplement
it on top of the system, and you'll lose any advantage from having an
integrated system.
Extensibility
-
- Modularity
Objects come in replaceable, upgradable modules.
Modules are identified uniquely accross the
computing world,
and
come with their specification.
Modules and new semantics may be created and added dynamically to the
system. Objects may be automatically relinked to upgrades or extensions,
or translated into a new universe of values.
Actually, extensibility is just the (important) combination of modularity,
dynamism, and higher-order: modules of any abstraction order may be
upgraded dynamically.
We need modularity for object sharing and fine grain software
competition.
- Reflection
The language can talk about itself, manipulate code at any level:
source code, intermediate representations or processor executable format,
so that extensibility is at all computing levels.
It means the language provides (direct or indirect) uniform access
to the internal representation of objects, of which
source code should merely be an external representation.
It alllows easy meta-programming in the language: the compiler is its own
preprocessor; the language is its own macro-command language.
Reflection is a generalization of higher-order: not only the universe is
layered by abstractions, but it has got standard embeddings into itself.
- Security
Objects come with their full specification,
so that system security is never endangered.
Specification can be multi-level (i.e. conditions for the
object not to crash the system, conditions for it to work properly),
may come with proofs assuming different assumptions (according to the
level of trust you give to each module's providers),
and may involve any kind of strong typing, from first-order typing to
full computational logic.
Code with side-effects will have pre/post conditions, or will be
considered as iteration of pure code. Temporal logic may even be
involved for time-aware proofs...
Security is a must, because better have no computer than a computer you
cannot trust, especially when computer information is used in any
critical work that may involve human lives or lots of money, or the
victory of the forces of evil ;->
Extensibility without Security is not worth a penny (see C, Elisp, et al.)
- Parallelizability
Modules are executed in parallel, and scheduled by the system
(with directives from the programmer).
parallelized partial-lazy evaluation leads to future values as in Ellie.
The language has built-in multi-threading and parallel constructs.
Parallelizability is needed because parallel computers have so much
performance improvement to bring to sequential ones, and a distributed
system is inherently parallel.
- Interactivity
By means of reflexivity and dynamism,
the language allows direct, interactive development of programs,
without a stupid slow inefficient edit/compile/debug cycle.
It also allows any kind of direct interaction between the system and
its human user, so that it replaces a shell (and its associated
scripting languages).
This is a feature of the language, because it means its semantics
allow efficient semi-compilation and interpretation.
This is also a feature of the standard library and environment. The rest
follows from dynamism, extensibility, and reflexivity.
Interactivity is needed, because else, yet other languages will have to
be written and learnt, so this one won't have been useful.
Low-level awareness
-
- Scalability
When you needn't features like higher-order programming,
you can tell the system (if it doesn't find it by itself),
so that it may scale down its power, and take advantage of
the peculiarities of the restriction of the system to
implement objects more efficiently, with less resources.
e.g. if a program explicitly handles virtual memory (using Forth-like
BLOCK statements), it doesn't need a MMU processor; if it explicitly
handles memory allocation/deallocation, it needn't run in an implicit
garbage collecting environment; if it only uses 16 bit integers, it needn't
use 32 bit integers on hardware where 16 bit is cheaper and as (or more)
efficient; etc.
We need scalability for efficiency, and adaptability to mobile
computers and obsolete hardware.
- Hardware consciousness
The actual resources (size of memory, of words in the arithmetic or floating
point unit, CPU cycles, etc) of computers will always be finite,
whereas the field of computing possibilities is infinite;
thus the programmer must be able to control resource use of his program,
and to handle overflows that will eventually occur.
The HLL must thus be aware of side-effects, because they are intrinsically
inevitable.
Hardware consciousness is required because time and space resources
are a major concern for humans, who cannot wait and pay
indefinitely to waste new resources.
- Integration
The language must allow easy access to external objects from other systems,
written using any semantics or syntax. All these objects (including languages),
whether low-level or high-level, should be embeddable into the HLL.
Integration is needed to allow soft and efficient upgrading of existing
systems toward the Tunes project, and communication with the world external
to the Tunes system.
- Partial evaluation
Evaluation is done as early as information and resources allow.
Function calls, message passing et al. can be dynamically compiled or inlined.
e.g. when an object '1+1+x' is seen, it's automatically evaluated as
'2+x'. When a generic function is called with specific but incomplete
parameters, it may get specialized and optimized accordingly.
It's a little more precise than "eager evaluation" since it also applies to
non-terminal objects (actually, all objects are equal, so the concept of
terminal object isn't clear in Tunes as it is in lower-order, non-reflective
systems).
The compiler/interpreter might then be as simple as just a trivial
(parametrizable) front end and then partial evaluation done on parsed objects.
Partial evaluation is needed because it involves such performance improvements.
The programmer must be aware of it to help the system manage it better when he
knows while the system doesn't (which will always eventually happen).
- Persistence
Object automatically persist together with the system. There is no need to
explicitly convert objects to and from unsafe persistent binary or ascii
files. This is a language feature, as it greatly affects
the language's standard library and programming habits.
Persistence is needed, because not granting it is wasting at least 30% of
users' time, not to talk about parsing or complex error recovery.
- Garbage collection
This feature is the complement of persistence: object are automatically
destroyed when no more needed.
Garbage collection is needed because no persistent higher-order is possible
without it: either space resources will explode, or low-level memory
management will have to be done manually by the users.
Note that Scalability above means that GC should be implemented directly in
the user program if/when possible and simpler.
Nice Human interface
-
Syntax is purely for human convenience. LISP sucks because it forgot that
simple statement. Other languages focus on the convenience, but offer no
nice semantics; they suck even more.
- Automatic rewrite
Conceptually, the semantics are everything;
the syntax is only sugar for the human user.
Thus so the language system shall automatically rewrite programs
according to user-defined criteria.
Particularly, the human user completely controls the level of redundancy the
language will provide or require when he reads or writes programs.
Automatic rewrite is needed because different users have different
understanding of computing at different moment and in different context,
and the computer shall adapt to the user's syntax, not the converse.
- Self-Extensible syntax
The syntax can evolve according to the context,
new syntaxes may be dynamically defined.
Particularly, any language can be added in a module as a sublanguage
of the HLL.
Self-extensible syntax is needed to dynamically allow all kind of objects
to be equally well interfaced between humans and computers.
- Implicitness
The human should never have to say more than s/he needs.
S/he should be constantly able to control which information to explicitly
give to the computer, and which to have the computer find out by itself,
and how the computer will try to find out.
The human user completely controls the level of redundancy the
language will provide or require when he reads or writes programs.
S/he may ask the computer to replace any implicit object by the
explicit object it found.
Implicitness is needed because computers are as good as men at tracking
redundancies, and any man's work saved is worth much more than computer
work spent.
Note
Phew ! Those are enough, aren't they ? Well, if you know of any other
feature it should have, please tell me.
At least, they are enough to prevent any existing language I know
from being selected )-8.
However, I do not know that many, and may be wrong about some.
So if you do know of any language that you think
fulfills those requirements, please do tell me !
If you think it fulfills many of them, but find it not in the list of
languages that were considered, please also tell me.
Summaries about such languages are also greatly appreciated.
To Do on this page
All HLL requirements were presumably found.
Rewrite them better.
Add references to the Glossary.
Wait for feedback and criticism.
Back to the Tunes
HLL Subproject.
Page Maintainer:
Faré
-- rideau@clipper.ens.fr