language design for system vs. application implementation

David Hough uunet!Eng.Sun.COM!David.Hough
Thu Dec 19 10:05:07 PST 1991


     While struggling recently with several unrelated issues, including
this one relevant to NCEG:
   
	What's the right level of functionality for numerical support in 
	programming languages?

I came to the conclusion that a fundamental problem was attempting to
provide two levels of abstraction with one programming language.   There
really are two distinct levels of programming languages, which I call System
Implementation Language and Application Implementation Language.  A lot of
confusion results from trying to make one language serve both levels.

Levels of Abstraction

     Consider the following levels and corresponding interfaces:

Interface                               Layer                       Example

                                        CPU+FPU                     R4000 or 586
electrical signals
                                        minimum hardware platform   Sun IPC
instruction set architecture
                                        supervisor code             Unix kernel
supervisor call interface

System Implementation Language
(SIL) implementation platform -
written in SIL:
                                        SIL compiler                C
                                        SIL standard library        stdio
Application Implementation Language
(AIL) implementation platform -
written in SIL:
                                        AIL compiler                C++
                                        AIL standard libraries     class library

Application implementation platform -
written in AIL:
                                        application libraries       multi-media 
								    libraries
                                        application for end users   multi-media 								    application
graphical user interface


     This picture is imperfect - some aspects of instruction set architecture
permeate many levels.   But in general the design of each level could be con-
sidered defective to the extent that it required cheating on the normal inter-
face to obtain optimal performance.  By this measure most existing languages
come up short.

     How are system implementation languages and application implementation
languages different?   The fundamental distinction is that application levels
are for solving problems directly of interest to end users, and system levels
are for solving lower level problems that arise indirectly from using comput-
ers to solve end user problems. Consequently application level languages try
not to get in the way of the application programmer's thinking about the ulti-
mate problem, while system level languages try not to get in the way of the
system programmer's thinking about the machine and low-level software.

     The SIL has two parts - the "portable" part that generates machine
instructions and supervisor calls that are universal, or nearly so, and the
"specific" part that generates machine instructions peculiar to a particular
CPU and supervisor calls peculiar to a particular kernel. In principle, one
command line option should disable features generating "specific" stuff, to
help in creating portable code, and another should disable features generating
supervisor calls, to help in creating supervisor code.  Perhaps this can be
accomplished by having operator syntax and similar low-level language con-
structs for the features that have universal machine instruction representa-
tions, and function call syntax for everything else.  The compiler for a
specific SIL interface should be very highly optimizing for that platform.
Specific features in functional notation should be compiled as efficiently as
explicit operators (rather than compiled into actual function calls) whenever
appropriate.   SIL compilers know a lot about their target platform.

     The SIL can be a subset of the AIL, in principle, although I doubt that
this would make an outstanding design.  In any event, the common data types
should be implemented identically; calling sequences should be identical for
identical types.

     What features vary between SIL and AIL?  The flavor of SIL is represented
by:

        no dynamic types
        explicit storage management
        support for intercepting hardware traps at lowest level
            consistent with system integrity
        explicit minimal multi-thread primitives
        strong type checking easily bypassed
        static "hard-compiled" tendency
        varargs is questionable
        it's easy to express hardware and supervisor primitives

while the flavor of AIL is represented by:

        dynamic types (character strings, array temporaries)
        implicit garbage collection
        built-in signal and exception handling
        nested functions
        implicit multi-thread support
        implicit multi-tasking
        strong type checking enforced
        dynamic "interpretive" tendency
        varargs is natural
        it's easy to express application primitives


     To demonstrate the difference in another way, consider that at the
current level of practice, floating-point addition and multiplication are
primitive SIL operators, while matrix-multiplication would be an AIL primi-
tive.  Vector operations are trickier: they are common but not universal in
instruction sets of interesting machines, so a case could be made for defining
them in SIL in a syntax that was portable but might be implemented in hardware
or software.

     It sounds reasonable to implement an AIL with a translator into SIL -
C++, Modula-3, Fortran-77, and Fortran-90 have all been implemented as trans-
lators into C.  So whatever its other faults, C can be used as a SIL.  This is
only faint praise, for the same can be said of Fortran-66: until Fortran-77
became popular, a number of computational languages were implemented as trans-
lators into Fortran-66.  The enabling feature shared by C and Fortran-66 as
SIL's was ubiquity on the target platforms of interest.

     This translation model enforces either that all AIL's contain only
features expressible in the SIL - or else that the SIL must be able to imple-
ment all features of all AIL's.

Possible Implications

     For NCEG: Array extensions should not include matrix multiplication.
Complex arithmetic is questionable.

     Since presubstitution is not likely to be implemented in hardware, it
should not be specified as part of NCEG C - the minimal support to recover
after hardware traps is what should be specified.    Conversely one might
argue that since presubstitution might well be implemented as a kernel ser-
vice, that interface should be part of NCEG C.

     Generally: 
Nowadays instruction set architectures are designed to rapidly execute
existing programs in C and Fortran, while the evolution of C and Fortran is
influenced by existing instruction set architectures.   This self-referential
recursion could presumably only be broken by a vendor of integrated systems,
yet integrated systems vendors are tending toward fragmentation based on
proprietary implementations of frozen public interfaces.



More information about the Numeric-interest mailing list