Lpp achieves dynamic typing capability by having all Lpp objects be of
type let. The type let is actually an Let* where
Let refers to the base class for all specific Lpp types like
Symbol, Cons, Integer etc. The actual base class of Lpp objects is
abstracted away by the let and Let type definitions.
Thus while working with Lpp objects all objects are considered to be
one cell pointers. However since the programmer never uses
Lpp* or Lpp the concept of pointers is abstracted away
with the use of let. So it is also correct to refer to Lpp
objects as let objects (objects of type let).
Furthermore all computational aspects of pointers is encapsulated in
the Lpp classes. This means that in essence the programmer never has
to deal with pointers while working specifically with let
objects. This is consistent with the way Lisp works. In addition to
this the programmer can declare let members in conventional C++
classes where non-abstracted pointer representations are needed.
The Lpp class defines a slot that contains a pointer to a type
meta-object of type Type. This pointer is a let type
and so the type meta-object itself is also a an Lpp object.
Type objects themselves being of base type let, can be
stored and operated on like any other Lpp object. So for example
let x = S(foo);
let y = list(x, typeOf(x));
cout << first(y) << second(y) << endl;
would print x followed by its type.
Type objects contain meta information about the specific
objects it is a type of. Some of the information it contains are a
type name, a type lattice member, and type dispatching
functions. Type dispatching functions are very similar to virtual
functions, but are more powerful in that they themselves can be
dynamically manipulated. An example of type dispatching functions are
the various printing functions for Lpp objects.