Prism Mechanics, Part 2
Wed, 06 Jan 1999 21:42:45 -0700
Thanks for your response. :) You make a lot of good points in your
article, and I'll try to respond to them as best I can...
Billy Tanksley wrote:
> [Jim Little wrote:]
>> I call this [phrase-structure grammar] a SYNTACTIC meta-metamodel.
>> That's because it's entirely focused on syntax. Prism, on the
>> other hand, defines a SEMANTIC meta-metamodel. It defines a set
>> of data types (which could roughly be described as "bit," "32
>> bits," and "map") and then says that any metamodel may be
>> defined with these data types.
> Judging from your discussion below, you're still defining a
> syntactic meta-model -- or more accurately, failing to define one.
> The reason I say this is that your discussion below has to assume some
> syntax for the meaning.
It's true that we have to use syntax -- language -- in order to discuss
the concepts. But that doesn't mean that the concepts are inextricably
tied to a particular language. THAT'S the difference between a semantic
meta-metamodel and a syntactic meta-metamodel. If you define a
metamodel ("language") with a syntactic meta-metamodel such as
phrase-structure grammar, you are tying your concepts to a particular
syntax. In the case of phrase-structure grammar, you're limited to what
you can reasonably express in a one-dimensional stream of text, AND you
have to figure out how to make that stream of text work as a
phrase-structure grammar. (Which isn't at all easy!)
But with a semantic meta-metamodel, you can let your mind run free when
you define your metamodel. You don't have to worry about "How can I
express this concept?" You just concentrate on finding the concepts
that best fit the domain abstraction you want to use. THEN, after
you've defined your metamodel, then you create a language to go with it.
Prism isn't perfect in this regard, I'll admit. You still have to
express your concepts within the confines of "bit, 32 bits, and map."
But that's easier than thinking up keywords and worrying about syntax,
in my opinion.
> Your words are big, but the underlying
> concept isn't any different from any other compiler compiler I've
In the sense that both yacc and Prism work with meta-metamodels, I
agree. The biggest difference between Prism and other compiler
compilers will become clear (I hope!) when I discuss the rest of Prism:
the global heap and the reflection domain.
A Prism compiler is definitely closer to yacc than any other type of
program I know of.
> Whoops, my mistake. The result defines something that could
> be compiled into a library; it doesn't define a language. I'm
> not sure I see the advantage. It might be a useful tool.
There's several advantages. The first I described above -- it allows
the programmer to brainstorm more effectively. The second is that it
allows multiple languages to be used for a single metamodel. That would
be like being able to trade in C in for Pascal without changing your
program. The third advantage is specific to Prism's goals: it's a lot
easier to mix and match metamodels when they are expressed with data
structures than with languages.
> I see above that your datatypes are bit, 32bit, and map. bit
> and map make sense to me; however, 32bit is a little more than
> dangerous. Is there some reason why you chose "32"? Do you not trust
> the programmer to be able to type "define 32bit as map (int->bit)"
> or whatever? It would seem to me that a more valuble semantic concept
> would be a "reference", which would serve as a pointer to a bit (or
> possibly a map). Like a map, its size is indeterminate.
I've thought about what you were saying and I think you're absolutely
right. My goal in defining the meta-metamodel was to allow as wide a
variety of metamodels as possible to be defined. To allow this, I
wanted it to impose minimal semantics on the metamodels. Therefore, the
Prism meta-metamodel defines only the form of its data types, not the
I also wanted the meta-metamodel to be as simple as possible. Every
data type was to be orthogonal with the others. I thought I had
achieved that goal with my choice of _pBit, _pBits32, and _pMap.
But, in trying to defend my choices to you, I discovered that you're
right. _pBits32 doesn't belong. It's not orthogonal at all -- it's
just a limited version of _pMap. They're both indexed collections of
data, and _pMap is the more flexible one.
So, _pBits32 is out! :) However, we need something to replace it,
because otherwise there's no way to dereference _pMap. :) I think I
have just the thing, too: _pStream.
_pStream represents an ordered bag of data. Like _pMap, it can contain
any datum. Unlike _pMap, it's not indexed, it's ordered. So to
manipulate the contents of a _pStream, you would use operations like
"move forward," "move backwards," "get datum," and "replace datum."
NOW the Prism meta-metamodel is completely orthogonal. Let me
_pBit: The fundamental unit of information.
_pStream: An ordered collection of data.
_pMap: An indexed collection of data. It's indexed by _pStream data.
(I don't want to confuse things by going into the details of how
_pStream can index _pMap, but rest assured that it can. Efficiency is
another matter entirely, though. :) --Hmm... but I'm not sure if I'd
want to allow a _pStream to act as an index if it contained _pMap
As before, the collection data types, _pStream and _pMap, may contain
other collection data types. But they may not contain themselves, not
even indirectly. As before, they contain actual data, not references to
Let me know what you think of this.
>> One important thing about _pMap is that it can contain other _pMaps.
>> But it can't contain itself, not even indirectly. Think of the _pMap
>> as physically containing other _pMaps, not just references to them.
> With the 'reference' type, it could.
> I'm not sure that the reference type owuld be wanted, of
> course. It does seem like it should be a part of the metamodel
> rather than Prism
Exactly. You're showing a pretty deep understanding of Prism with this
> -- but then it's possible that even bits should be discarded and
>replaced with Numbers.
I'm not sure what you mean by this sentence, though. You'll have to
enlighten me. :) As you probably know, Numbers don't belong in the
meta-metamodel because they impose specific semantics on the metamodels.
>> An Arrow consists of references to other arrows. In the metamodel,
>> this is represented by Slots. An Arrow consists of two or more
>> Slots. Slots are contiguous -- that is, the first one is at
>> index 0x0, the second at 0x1, the third at 0x2, etc., without any
>> gaps in the sequence.
> This is a good excuse for replacing bits and 32bits with
I found this type of situation coming up a lot while working with
example metamodels. _pStream addresses it perfectly, which is a good
sign that it's the right choice, I think.
Just for fun, I've re-implemented the Arrow metamodel in the new
meta-metamodel (i.e., with _pStream rather than _pBits32). Here it is:
_pMap (Arrow Space)
| _pStream (Index) | _pStream (Arrow) |
| +----+-------+ | +----+------------------------------+ |
| | 32 | _pBit | | | 2+ | _pStream (Slot) | |
| +----+-------+ | | | +---+----------------------+ | |
| | | | | 1 | _pBit (Empty) | | |
| | | | | 1 | _pStream (Reference) | | |
| | | | | | +----+-------+ | | |
| | | | | | | 32 | _pBit | | | |
| | | | | | +----+-------+ | | |
| | | | +---+----------------------+ | |
| | +----+------------------------------+ |
(I'm using a table-based syntax here. The left-hand column means
different things for a _pMap and a _pStream. For a _pMap, the left-hand
column shows the layout of the datum which is used to index the datum
shown in the right-hand column. For a _pStream, the left-hand column
shows the number of times the datum in the right-hand column is
Here's the semantics of the above metamodel. (The overall semantics
haven't changed, but the expression of them has, so there are some
Brian's metamodel, "Arrow Space," consists of zero to (2^32)-1 Arrows.
Arrows are indexed by an "Index" which uniquely identifies each Arrow.
An Arrow consists of references to other Arrows. In this metamodel,
this is represented by Slots. An Arrow consists of two or more Slots.
A Slot defines a reference to an Arrow in Arrow Space. A Slot may also
be Empty, in which case it does not contain a reference. In the
metamodel, if the Empty datum is 1, then the Slot is 'empty' and the
Reference datum is ignored. However, if the Empty datum is 0, then the
Slot is not empty and the Reference datum shall refer to an Arrow in
Arrow Space. The exact Arrow referenced is that whose Index is
identical to Reference.
This definitely feels like an improvement. One thing I really like is
that now the size of the Arrow Space is completely at Brian's discretion
-- all he has to do is change the size of the Index and Reference
> Thank you. This explanation and example made everything MUCH
> more clear. I had no idea what you were talking about before. PLEASE
> post an easily accessible example on your web page.
Thanks! I know that the Prism documents on the web site aren't the
easiest to understand, and I've agonized quite a bit about finding the
right words -- particularly in the overview. But I knew that I wouldn't
be able to really make things clear until I had some feedback. The
results of our discussions here on the Tunes list will definitely make
their way back to the web page.
One thing that would be a big help would be if you could let me know
(perhaps in a separate email, so we don't clutter up the Tunes list)
where the biggest obstacles towards understanding are. I already plan
on following your advice and putting up an example -- is there anything
else that would help? (Maybe a crucial point is poorly explained, or a
key concept undefined?)
Thanks for your response. I feel like this exchange has resulted (or at
least, will result) in a fundamental improvement to Prism. :)
Jim Little (email@example.com)
Prism is at http://www.teleport.com/~sphere.