COORDS/PLATO Manifesto

Pure Software like Pure Mathematics is created not because of any intended use but because it is beautiful.

Note. References to "COORDS/PLATO," "PLATO++" and "PLATO" should be considered interchangeable.

Goals

  • Implement the PLATO system in C++ using the COORDS base.
  • Make a PLATO interpreter as a type (as in COORDS) which provides a command line interpreter for its native syntax.
  • Show how new PLATO types can be implemented in internal C/C++ or other languages.
  • Preface

    "PLATO" stands for "Programming Language of Abstract Type Objects." The PLATO language, which descends from our unpublished software system "COORDS" (C++ Object ORiented Data/Design System) is a type-only self-defining object-oriented language system. PLATO adds a complete function integration to COORDS data-centered type object abstraction.

    PLATO differs from COORDS in its treatment of functions, the semantics of parenthetical grouping (particularly for functions with arguments) and the notion of a universal type "Eval" based on the "Self" attribute as a basis for implementing functions.

    Manifesto

    PLATO is a single inheritance type/attribute system as in COORDS. All entities including attributes in PLATO are types. PLATO aims to be self-generated ("sui generis") in the sense that its types and their attributes are defined in terms of each other. As a result PLATO is totally reflective in that it can examine itself and its components to any depth. The minimal subset of types PLATO needs to completely define itself is called the kernel.

    Inspired by lisp and its variants, PLATO strives for the most power with the least syntax, and for a single operating principle which unifies all entities in its system. Just as lisp unifies function and data abstractions, PLATO unifies data and function in a type object system which does not just add type-selected functions to a LISP-like function language or glue functions into an object language as other object-oriented languages do. Function and data objects are unified.

    While COORDS syntax for accessing attributes without arguments is simple serial juxtaposition of type and attribute, PLATO differs in its method of evaluating attributes/functions with arguments: they are placed within parentheses in a style resembling LISP, although the semantics of evaluation differ.

    All types (and their components) including those that can serve as functions are entirely first class in PLATO and the distinction is to all intents seamless. Object-oriented dispatch selects an attribute (possibly a function) from a type or one of its supertypes. PLATO combines this selection principle with a type/function "Eval" in a single object-oriented evaluation/dispatch.

    Broadly viewed, a type is an entity that knows things and can communicate them on request. What does a type know? It knows what its own properties or attributes, it knows other types, and in a deep sense, it "knows itself."

    Each type knows its own attributes (in other systems variously called messages, variables, properties, slots, functions, members...). PLATO attribute values are always types themselves. A type inherits the attributes of its supertype intact, or it may "refine" them by subtyping their values, or define new attributes (see below, "The Subtyping Principle").

    The delphic motto: "Know thyself" is emblematic of the property that lies at the heart of PLATO's function/type integration. In PLATO, this is appropriately called the "Self" attribute, defined in its root type, TYPE, and shared by all other types in the system. This attribute has the same name as its possessor and is its intrinsic function. The default TYPE Eval would simply return the default Self value, the type itself. Thus every type can at least return itself as value.

    In PLATO, there is no difference between attributes which are conceptually stored data values, and attributes which involve functional computations. Attributes are one aspect of data/function unification. They only vary by how they are evaluated. Following COORDS, the usual object-oriented notion of variable get and set functions is subsumed into a single function definition,

    In some situations, some types as well as function types, the Eval method and Self attribute become non-trivial, thereby producing the defined function result. The basic idea is that all types know how to find and evaluate their own value, including function types.

    Evaluation of a type can be useful and non-trivial. In analogy to lisp, presenting a (type) symbol implies an Eval of it. Self evaluation of a type provides an implicit entry point. Such self evaluation can launch a subsytem, or perform some default action, thus doing away with the need of an explicit "main" entry point as in languages like C/C++ or Java.

    To complete its knowledge, a type must know more types than itself to interact in a universe of types. The set of other known types is called its "context." Since all types may have their own type context, this implies that knowledge is generally not global but local. In particular a type may have a type collection, or use that of its supertypes.

    The preceding leads to the final principle for PLATO: localization. No global information or functionality beyond what is in TYPE is maintained for all types. Any other properties are only what is defined by that type and its supertype ancestors. In particular, some types may know other types e.g. subtypes, which are unknown to TYPE. One consequence is that there may be more than one distinct type in different contexts but with the same name. This also permits capabilities to be added to the system locally in a way decoupled from the system as a whole.

    Evaluation is also localized, in that a type may have its own Eval method. This is the principle of "local Eval." While the kernel types will have a default Eval method, other (sub)types are free to define their own Eval methods. In particular all attributes descend from type ATT whose Eval is used to determine the attributes value. For example, the most obvious case is to get (or set) the value associated with an attribute. Function attributes are also subtypes of type ATT. The formal value defined with function attributes is its return type.

    PLATO is not intended as (just) a stand-alone system. It should be suited by its localization architecture to allow adding facilities from other language systems while preserving its own abstraction overall. Examples: a command shell using the PLATO abstraction, or a heterogeneous software systems containing types calling functions in external languages. By providing a "platonic" interface, external language facilities may be made available within PLATO.

    The Subtyping Principle

    PLATO is a single inheritance type system without instances. Doing without instances is not really a handicap since class/instance systems can be modeled in a type-only system by assuming the current leaves of the type inheritance tree represent "instances." This could be compared to prototype systems where a new object can be derived from any other object.

    When a type is subtyped, its attributes may be "refined." A refinement is the substitution of a subtype value for the inherited attribute's type value. If an attribute is not so redefined, it is simply inherited as is by the subtype.

    A subtype may even in the limiting case include no attribute refinement at all. It might define entirely new attributes. Or it may refine any subset of its supertype's attributes. Since types can be subtyped to any extent, attribute value types can also be refined indefinitely, putting no limit to the degree of subtyping. We have previously termed this generalized subtyping by step-wise refinement, incremental instantiation (Cf. "Object-Oriented Language Extensions for CAD/CAM", "Journal of Object-Oriented Programming", July-Aug. 1989). Here we prefer the term refinement due to PLATO's type only character.

    What is the correspondence then to class/instance systems? This is a generalization compared to traditional object-oriented class/instance systems which require that all attributes be redefined as instances of their supertype types. We suggested above that instances may be thought of simply as leaves of the current type tree hierarchy. By this correspondence a class/instance tree can be represented in PLATO.

    Eval/dispatch

    PLATO combines object-oriented dispatch and type evaluation. This is single procedure for all types be they attribute values or not. In what follows, we may refer to "dispatch" or "eval" when we are emphasizing one or their other aspect but always understand as the entire evaluation/dispatch procedure. Evals and dispatches may follow one another until the eval/dispatch process terminates.

    Given any type we can ask it for the value of various attributes, or other types, including itself (the "Self attribute") which may be an explicitly stored attribute/value pair or if not, implicitly is the type itself. For any attribute not defined in the type, we can refer the search to the supertype, and begin the process again. Once the attribute is found, its value is provided from the nearest type having one. This is the dispatch phase.

    The evaluation phase then Eval's this type. Most ordinary types will trivially return themselves as their value. Some attributes, viz., functions will have non-trivial Eval's which conduct a procedure to arrive at a type value. This type is in turn evaluated and so on. The Eval process ends when a result type Eval returns the same type again. Ordinary value types self-Eval to themselves by default, so that Eval ends trivially and immediately. (Implementations may use internal strategies to hasten this result.)

    Function arguments are defined as attributes of their function type. A function call creates a subtype of the function which cotains the refined attributes (analogous to an argument stack) for function evaluation. Since functions are attributes, we have recursively made attributes of attibutes serve as function arguments. Invoking the functions (inherited) Eval then produces the function's value.

    PLATO extends attribute dispatch for functions by seeking the nearest function definition in the supertype chain that has argument types consistent with arguments given for function evaluation (cf. Barrett and Giguere, "Covariance and Contravariance Unification," SIGPLAN Notices, Jan 1996). This allows both function and argument covariant subtyping.

    Simply requesting a given type implies a (Self-)Eval with the effect of asking a type for its self-attribute value and doing Eval on that. But even though this self-Eval produces the type back again, there may be (useful!) side effects to the explicit Eval process as noted previously.