2015-11-23 13:45:01 +01:00
|
|
|
---
|
2016-12-19 16:43:59 +01:00
|
|
|
layout: typed
|
|
|
|
title: Typed intermediate representation
|
2015-11-23 13:45:01 +01:00
|
|
|
---
|
|
|
|
|
2016-12-19 17:56:35 +01:00
|
|
|
### Intermediate representation
|
2016-08-01 16:30:37 +02:00
|
|
|
|
2016-12-19 17:56:35 +01:00
|
|
|
Compilers use different intermediate representations to go from the source code to a binary,
|
|
|
|
which would otherwise be too big a step.
|
2016-08-01 16:30:37 +02:00
|
|
|
|
2016-12-19 17:56:35 +01:00
|
|
|
The **typed** intermediate representation is a strongly typed layer, between the dynamically typed
|
|
|
|
ruby above, and the register machine below. One can think of it as a mix between c and c++,
|
|
|
|
minus the syntax aspect. While in 2015, this layer existed as a language, (see soml-parser), it
|
|
|
|
is now a tree representation only.
|
2015-11-23 13:45:01 +01:00
|
|
|
|
|
|
|
|
2016-12-19 17:56:35 +01:00
|
|
|
#### Object oriented to the core, including calling convention
|
2016-03-07 16:37:24 +01:00
|
|
|
|
2016-12-19 17:56:35 +01:00
|
|
|
Types are modeled by the class Type and carry information about instance variable names
|
|
|
|
and their basic type. *Every object* stores a reference
|
|
|
|
to it's type, and while **types are immutable**, the reference may change. The basic types every
|
2016-03-07 16:37:24 +01:00
|
|
|
object is made up off, include at least integer and reference (pointer).
|
2015-11-23 13:45:01 +01:00
|
|
|
|
|
|
|
The object model, ie the basic properties of objects that the system relies on, is quite simple
|
2016-03-07 16:37:24 +01:00
|
|
|
and explained in the runtime section. It involves a single reference per object.
|
2016-12-19 17:56:35 +01:00
|
|
|
Also the object memory model is kept quite simple in that object sizes are always small multiples
|
2016-03-07 16:37:24 +01:00
|
|
|
of the cache size of the hardware machine.
|
|
|
|
We use object encapsulation to build up larger looking objects from these basic blocks.
|
2015-11-23 13:45:01 +01:00
|
|
|
|
|
|
|
The calling convention is also object oriented, not stack based*. Message objects used to
|
|
|
|
define the data needed for invocation. They carry arguments, a frame and return addresses.
|
2016-12-19 17:56:35 +01:00
|
|
|
Return addresses are pre-calculated and determined by the caller, and yes, there
|
2016-03-07 16:37:24 +01:00
|
|
|
are several. In fact there is one return address per basic type, plus one for exception.
|
2015-11-23 13:45:01 +01:00
|
|
|
A method invocation may thus be made to return to an entirely different location than the
|
|
|
|
caller.
|
2016-12-19 17:56:35 +01:00
|
|
|
\*(A stack, as used in c, is not typed, not object oriented, and as such a source of problems)
|
2015-11-23 13:45:01 +01:00
|
|
|
|
2016-12-19 17:56:35 +01:00
|
|
|
There is no non- object based memory at all. The only global constants are instances of
|
|
|
|
classes that can be accessed by writing the class name in ruby source.
|
2015-11-23 13:45:01 +01:00
|
|
|
|
2016-12-19 17:56:35 +01:00
|
|
|
#### Runtime / Parfait
|
2015-11-23 13:45:01 +01:00
|
|
|
|
2016-12-19 17:56:35 +01:00
|
|
|
The typed representation layer depends on the higher layer to actually determine and instantiate
|
|
|
|
types (type objects, or objects of class Type). This includes method arguments and local variables.
|
2016-03-07 16:37:24 +01:00
|
|
|
|
2016-12-19 17:56:35 +01:00
|
|
|
The typed layer is mainly concerned in defining TypedMethods, for which argument or local variable
|
|
|
|
have specified type (like in c). Basic Type names are the class names they represent,
|
|
|
|
but the "int" may be used for brevity
|
|
|
|
instead of Integer.
|
|
|
|
As mentioned a function may return to different addresses according to type, though this is not
|
|
|
|
fully implemented.
|
2015-11-23 13:45:01 +01:00
|
|
|
|
2016-12-19 17:56:35 +01:00
|
|
|
The runtime, Parfait, is kept
|
2016-03-07 16:37:24 +01:00
|
|
|
to a minimum, currently around 15 classes, described in detail [here](parfait.html).
|
|
|
|
|
2015-11-23 13:45:01 +01:00
|
|
|
Historically Parfait has been coded in ruby, as it was first needed in the compiler.
|
|
|
|
This had the additional benefit of providing solid test cases for the functionality.
|