Challenge my assumptions!

Jim Little
Tue, 06 Jul 1999 02:40:38 -0600

Thanks to everybody who responded to my original post.  I'm responding
to everybody in this one post, mostly because there seems to be a lot of
confusion about Prism and what I was asking.  I've replied to specific
individuals at the bottom of this post.

I think everybody knows this by now, but just so we're all on the same
ground: Prism is a metaprogramming environment which emphasizes
interoperability of multiple languages.  In practical terms, it's a
scriptable compiler designed to work with multiple languages
simultaneously.  Users can create new languages and load interoperable
parsers and compilers for them into Prism.

To add a new language to Prism, you have to create a new metamodel.  The
metamodel defines how programs written in that language will be modeled
internally within the Prism compiler.  The point of my challenge was to

1) If there were any limits on which metamodels could be created
2) If it was going to be difficult for the average programmer to create
new metamodels.
3) If there were a better way to do it.

When creating a metamodel, you define how Prism atoms (instances of
Prism's _Bit, _Map, and _Stream data types) may be combined together and
what they mean when they are combined in particular ways.  The
definition is made in a natural language such as English.  It's just
like creating a normal programming language -- you define how different
constructs may be combined together and what they mean in each
combination.  Like the keywords in a lanuage, the Prism atoms have no
intrinsic meaning.

I chose _Bit, _Map, and _Stream for two reasons.  First, they seemed to
be the minimal set which could represent any set of concepts.  Second,
they seemed to provide simple and intuitive mappings to different types
of concepts:

A _Bit is always in one of two states.  It's the most basic unit of
information.  It's well suited to representing any bivalued concept,
such as true or false, black or white, etc.

A _Stream is an ordered collection of other atoms (it's not limited to
only _Bits).  It's well suited to any sequential concept, such as
algorithms, phone numbers, and text.

A _Map is an unordered, indexed collection of other atoms.  Actually,
this one seems sort of reduntant and I'm considering removing it.  I
might replace it with:

_Bag, an unordered collection of other atoms.  Suited to representing
any concurrent concept, such as declarative programs, concurrent
algorithms, and spatial arrangement of furniture.

As a trivial example, the following metamodel is for programs which
print the same string over and over again, a favorite of beginning
programmers:  (I.e., programs which follow the pattern "FOR I=1 TO 10;
PRINT "Hello World!"; NEXT I;")

=== Begin Example ===
_Stream (Trivial Example)
| 1 | Include: Integer  (Repetitions)    |
| 1 | Include: String  (Text to Display) |

The above table uses Prism/GTL (a language defined on the Sphere web
site, to describe a set of models. 
Each model consists of an Integer (defined on the Sphere web site)
followed by a String (also defined on the Sphere web site).  For this
metamodel, the String will be the text which is displayed, and the
Integer will describe how many times the text is displayed.  The integer
must be greater than zero.
=== End Example ===

Anyway, I hope that clarifies my position.  Now for the individual

Here's an explanation of the difference between models, metamodels, and

A 'model' is a concrete representation of any thing.  A source code file
is an example of a model.  In Prism, models are formed from 'atoms,'
which are instances of the _Bit, _Stream, and _Map data types.

A 'metamodel' is a model representing how a particular set of models is
interpreted.  The metamodel tells you what the set of models mean.  A
language definition such as the C standard is an example of a
metamodel.  In Prism, metamodels are formed from a natural language such
as English.

A 'meta-metamodel' is a model representing how a particular set of
metamodels is interpreted.  For most programming languages, the
meta-metamodel is implicit: (E)BNF and natural language.  In Prism,
there is one meta-metamodel.  It says that metamodels describe a set of
models, that the models are formed from _Bit, _Stream, and _Map
instances, and that the meaning of each model is described with natural

> may i suggest an alternative structure
> for representing information: the binary tree ("function application")
> with a finite set of words for the nodes. Actually, strictly, just one word
> would suffice (but this might make the interpretion more difficult); if you
> are willing to have self-referencial trees, then no words are necessary
> (this would be like Brian's arrow system i suppose).

Now that I've explained the reasons behind my choice of _Bit, _Map, and
_Stream more clearly, I hope you'll defend your choice of a binary tree
as well.  I'm definitely open to using different data types for Prism
atoms... that's basically what I'm trying to determine if I should
change.  One thing to consider, though, is that I want the Prism's
internal representation of programs to be syntax independent.

I'd also be interested in seeing an example of a metamodel which used
binary trees for its atoms.  As a simple example, how about a metamodel
for integers?  My solution to the same problem is at, and is
fairly intuitive, I think.

>         Okay.  I'd also like to question what you're trying to achieve.  Is
> it something which CORBA already does?

Current mechanisms for achieving language interoperability are large
grained and difficult to do.  I hope to make interoperability more

>         No, because programs = data + algorithms.  Prism only models data.

Not true.  See the example above.

> I can't think of anyone who would like to deal with
> programs as streams of bits as a concept, unless they really had to think
> that way at some point.

_Bit, _Stream, and _Map are Prism's INTERNAL representation of
programs.  The programmer doesn't need to deal with them unless he is
defining a new metamodel, or creating a metaprogram which manipulates
models.  Most of the time, the programmer won't be doing that.  He'll be
defining programs with source code, and simply using other people's

> That only suggests a lack of imagination on your part.  So, let me ask you:
> how do you represent a human concept like Einstein's principle of general
> relativity?  Do you suggest modeling the equations and space-time
> constraints with bits and streams and maps?

Um... yes.  Although I haven't done so, I see no reason a metamodel for
scientific equations couldn't be created.  But once again, _Bit,
_Stream, and _Map are meant for internal representation only.

> Well, I'll grant you that your ideas are not so terrible that they
> completely restrict a person from eventually builiding up their desired
> concepts in terms of your primitives, if they don't die of sheer boredom and
> frustration in the process.

One point that I haven't made clear in the past is that, once a
metamodel (such as the "Integer" metamodel) is defined, it may be
referenced in the definition of other metamodels.  That saves quite a
bit of frustration, not to mention time.

> > 1) The basic Prism data types (_Bit, _Stream, _Map) are SUFFICIENT to
> > represent any concept, particularly programs.
> In order to comment on this, one needs to know what ways can _Bit,
> _Stream and _Map can be manipulated. 

Well, manipulation is the province of metaprogramming, and not what I'm
discussing here.  Instances of the above types are combined together to
represent a single program (or other concept):

_Bit is either "FOO" or "BAR".
_Stream is an ordered collection of other atoms (not just bits)
_Map is an indexed collection of other atoms.

Say what you will, but there's got to be SOME attraction in a system in
which "FOO" and "BAR" play such a major role.  ;)

> Data in itself without any ways to
> interpret it is effectively useless. Like Billy says, programs = data +
> algorithms.

Except that, in this case, the data is REPRESENTING a program, not being
used by it.

> Dependent on your goals. Personally, I think relflection is a point, and
> I don't see how that is provided in your model.

Reflection is a noble goal, but not what I am personally striving for. 
Reflection can "easily" be added to Prism without changing Prism itself,
though.  You just have to define a subset of the Prism meta-metamodel
which formalizes the definition of metamodels so that they no longer use
natural language.  Then Prism's scripting language (a metamodel itself)
could be used to write programs which achieve reflection.  Anybody care
to try?  ;)

I do plan on experimenting along these lines after I finish my other
Prism goals.  One thing I want to do, for example, is to write a Prism
compiler in a Prism language which supports dynamic recompilation.  Then
new Prism scripts can be compiled into the compiler itself.  :)  I also
want to formalize some subset of metamodels so that some degree of
automatic metaprogramming is possible.  But I've still got a lot basic
things to worry about, first.


Prism is at