[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
4.1 Language Overview | ||
4.2 Basic Data Types (tbw) | ||
4.3 Control Structure (tbc) | ||
4.4 Functions (tbw) | ||
4.5 Classes (tbw) | ||
4.6 Methods (tbw) | ||
4.7 Macros (tbw) | ||
4.8 Modules (tbw) |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
STELLA is a strongly typed, object-oriented, Lisp-like language. STELLA programs are first translated into either Common Lisp, C++, or Java, and then compiled with any conventional compiler for the chosen target language to generate executable code. Over 95% of the STELLA system is written in STELLA itself, the rest is written in target-language-specific native code.
The design of STELLA borrows from a variety of programming languages, most prominently from Common Lisp, and to a lesser degree from other object-oriented languages such as Eiffel, Sather, and Dylan. Since STELLA has to be translatable into C++ and Java, various restrictions of these languages also influenced its design.
In the following, we assume that the reader is familiar with basic Common Lisp concepts, and has at least some familiarity with C++ or Java. Let us start with a cursory overview of STELLA’s main features:
Syntax: STELLA uses a parenthesized, uniform expression syntax similar to Lisp. Most definitional constructs and control structures are similar to their Common Lisp analogues with variations to support types.
Type system: STELLA is strongly typed and supports efficient static compilation similar to C++. Types are required for the arguments and return values of functions and methods, for global variables, and for slot definitions. Local, lexically scoped variables can be typed implicitly by relying on type inference.
Object system: Types are organized into a single inheritance class hierarchy. Restricted multiple inheritance is allowed via mixin classes. Dynamic method dispatch is based on the runtime type of the first argument (similar to C++ and Java). Slots can be static (native) or dynamic. Dynamic slots can be defined at runtime and do not occupy any space until they are filled. Slots can have both initial and default values, and demons can be triggered by slot accesses. A meta-object protocol allows the control of object creation, initialization, termination, and destruction.
Control structure: Functions and methods are distinguished. They can have multiple (zero or more) return values and a variable number of arguments. Lisp-style macros are supported to facilitate syntax extensions. Expressions and statements are distinguished. Local variables are lexically scoped, but dynamically scoped variables (specials) are also supported. STELLA has an elegant, uniform, and efficient iteration mechanism plus a built-in protocol for iterators. An exception mechanism can be used for error handling and non-local exits.
Symbolic programming: Symbols are first-class objects, and extensive support for dynamic datatypes such as cons-trees, lists, sets, association lists, hash tables, extensible vectors, etc., is available. A backquote mechanism facilitates macro writing and code generation. Interpreted function call, method call, slot access, and object creation is supported, and a restricted evaluator is also available.
Name spaces: Functions, methods, variables, and classes occupy separate name spaces (i.e., the same name can be used for a function and a class). A hierarchical module system compartmentalizes symbol tables and supports large-scale programming.
Memory management: STELLA relies on automatic memory management via a garbage collector. For Lisp and Java the native garbage collector is used. For the C++ version of STELLA we use the Boehm- Weiser conservative garbage collector with good results. Various built-in support for explicit memory management is also available.
The Common Lisp features most prominently absent from STELLA are anonymous functions via lambda abstraction, lexical closures, multi-methods, full-fledged eval (a restricted evaluator is available), optional and keyword arguments, and a modifiable readtable. STELLA does also not allow dynamic re/definition of functions and classes, even though the Lisp-based development environment provides this facility (similar to Dylan). The main influences of C++ and Java onto STELLA are the strong typing, limited multiple inheritance, first-argument polymorphism, and the distinction between statements and expressions.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
To be written.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
To be completed.
4.3.1 Conditionals |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
STELLA conditionals are very similar to those found in Common-Lisp.
The main difference is that most STELLA conditionals are statements and
therefore do not return a value. For this reason, a C++-style
choose
directive has been added to the language to allow value
conditionalization based on a boolean expression.
Evaluate the boolean expression condition. If the result is true
execute then-statement, otherwise, execute else-statement.
Note that unlike the Common-Lisp version of if
the
else-statement is not optional in STELLA. Example:
(if (> x y) (print "x is greater than y" EOL) (print "x is less than or equal to y" EOL)) |
Evaluate the boolean expression condition. Only if the result is true execute the statement’s in the body. Example:
(when (symbol? x) (print "x is a symbol, ") (print "its name is " (symbol-name (cast x SYMBOL)) EOL)) |
Evaluate the boolean expression condition. Only if the result is
false execute the statement’s in the body. Therefore,
(unless test …)
is equivalent to (when (not
test) …)
. Example:
(unless (symbol? x) (print "x is not a symbol, ") (print "hence, its name is unknown" EOL)) |
cond
is a conditional with an arbitrary number of conditions each
represented by a clause. Each cond
clause has to be of the
following form:
(condition statement…) |
The first clause whose condition evaluates to true will be
selected and its statement’s will be executed. Each clause can
have 0 or more statements. The special condition otherwise
always evaluates to true and can be used for the catch-all case.
Example:
(cond ((symbol? x) (print "x is a symbol" EOL)) ((cons? x) (print "x is a cons" EOL)) (otherwise (print "x is an object" EOL))) |
Evaluate the boolean expression condition. If the result is true
return the value of true-expression, otherwise, return the value
of false-expression. STELLA computes the most specific common
supertype of true-expression and false-expression and uses
that as the type returned by the choose
expression. If no such
type exists, a translation error will be signaled. Example:
(setq face (choose happy? :smile :frown)) |
Each case
clause has to be of one of
the following forms:
(key statement…) ((key…) statement…) |
case
selects the first clause whose key (or one of
the listed key’s) matches the result of expression and
executes the clause’s statement’s. Each case
key has
to be a constant such as a number, character, string, symbol, keyword or
surrogate. Keys are compared with eql?
(or string-eql?
for strings). All keys in a case
statement have to be of the
same type. The special key otherwise
can be used to catch
everything. It is a run-time error if no clause with a matching key
exists. Therefore, a STELLA case
without an otherwise
clause corresponds to a Common Lisp ecase
. An empty
otherwise
clause can always be specified via (otherwise
NULL)
. Example:
(case car-make ("Yugo" (setq price :cheap)) ("VW" (setq price :medium)) (("Ferrari" "Rolls Royce") (setq price :expensive)) (otherwise (setq price :unknown))) |
Each typecase
clause has to be of one of
the following forms:
(type statement…) ((type…) statement…) |
typecase
selects the first clause whose type (or one
of the listed type’s) equals or is a supertype of the run-time
type of the result of expression and then executes the clause’s
statement’s. Therefore, typecase
can be used to implement
a type dispatch for cases where the run-time type of an expression can
be different from the static type known at translation time. Currently,
the static type of expression is required to be a subtype of
OBJECT
.
Each type expression has to be a symbol describing a simple type
(i.e., parametric or anchored types are not allowed). Similar to
case
, the special key otherwise
can be used to catch
everything. It is a run-time error if no clause with a matching type
exists. Therefore, a STELLA typecase
without an otherwise
clause corresponds to a Common Lisp etypecase
. An empty
otherwise
clause can always be specified via (otherwise
NULL)
. typecase
does allow the value of expression to be
undefined, in which case the otherwise
clause is selected.
Example:
(typecase (first list) (CONS (print "it is a cons")) ((SYMBOL KEYWORD) (print "it is a symbol")) (STANDARD-OBJECT (print "it is a regular object")) (otherwise NULL)) |
Note that in the example above it is important to list
STANDARD-OBJECT
after SYMBOL
and CONS
, since it
subsumes the preceding types. Otherwise, it would always shadow the
clauses with the more specific types.
The semantics of typecase
is slightly extended for the case where
expression is a local variable. In that case each reference to
the variable within a typecase
clause is automatically casted to
the appropriate narrower type. For example, in the code snippet below
method calls such as first
or slot accesses such as
symbol-name
are translated correctly without needing to
explicitly downcast x
which is assumed to be of type
OBJECT
:
(typecase x (CONS (print "it is a cons with value " (first x))) ((SYMBOL KEYWORD) (print "it is a symbol with name " (symbol-name x))) (STANDARD-OBJECT (print "it is a regular object")) (otherwise NULL)) |
Since the typecase
expression has to be a subtype of
OBJECT
, a typecase
cannot be used to test against literal
types such as STRING
or INTEGER
. If such type names are
encountered as keys in a typecase
, they are automatically
converted to their wrapped version, e.g., STRING-WRAPPER
,
INTEGER-WRAPPER
, etc.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
To be written.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
To be written.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
To be written.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
To be written.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
To be written.
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated by Hans Chalupsky on January 5, 2023 using texi2html 1.82.