[squeak-dev] [ANN] Tirade

Göran Krampe goran at krampe.se
Tue Mar 17 10:20:09 UTC 2009


Hi!

Nicolas Cellier wrote:
> 2009/3/16 Göran Krampe <goran at krampe.se>
>> Hi!
>>
>> Nicolas Cellier wrote:
>>
>>> Hi Goran,
>>> Two remarks:
>>>
>>> 1) closing the language:
>>>
>>> I know you want control and security.
>>>
>> Well, I want to maintain simplicity mainly. Currently it is so simple that
>> it is "intuitively safe". Safety is not necessarily about exploits but
>> rather about not inviting developers to do "smart stuff" that breaks tools
>> etc.
>>
>>  But are you sure the language is opened enough for future deltas
>>> extensions?
>>>
>> Can't really see what you mean.
> 
> The fact that you need a special interpretation of -> makes me suspicious.

The reason for #-> being handled differently is because #-> is in fact 
in Smalltalk implemented in Object:

-> anObject
	"Answer an Association between self and anObject"

	^Association basicNew key: self value: anObject


...it is thus not a literal syntax - which some may mistakenly believe!

BUT... in Tirade we don't allow expressions (messages to objects and 
using their results), but we really want a syntax to create Associations 
(and thus Arrays of Associations which easily can be turned into a 
Dictionary by the builder).

So this led me to implement the syntax <something> "->" <somethingelse> 
in the TiradeParser, "mimicking" Smalltalk. This is btw also a reason 
for choosing "brace arrays" because regular Array syntax in Smalltalk 
does not evaluate any expressions inside the Array, leading to this:

#('key'->'value')  ==>   #('key' #'->' 'value')

...but {'key'->'value'} works fine.


> Can you tell you won't ever need 1/2 for example?

Yes, I can tell you that. :) You can create tons of "nice things to 
have" but if you really think about it there are a lot of ways already 
in Tirade to avoid adding support for "expressions" like that, for 
example, simply make sure to send a message that knows that the argument 
is a mathematical expression that the builder can evaluate:

mathematicalExpression: '1/2'


> I mean representing arbitrary deep oject trees (not speaking of general
> graphs).
> The example you are presenting seems flat. Could you expose how you would
> build a deeper object?

Sure, either you build depth in "nested data":

structure: {'key'-> {
		'a'->12.
		'b'->13'.
		'c'-> {
			'd'->{123. 345. 567}.
			'e'->12}}}

...and let the builder create whatever objects it likes given that data.

Or more likely you build depth by using a message protocol that shows 
what you are doing, for example using a stack protocol or whatever:

createInstanceOf: #Animal.
	name: 'Tiger'.
  	description: 'Striped animal'.
	addInstanceOf: #Leg.
		name: 'left front'.
	endInstance.
	addInstanceOf: #Leg.
		name: 'left front'.
	endInstance.
	addInstanceOf: #Leg.
		name: 'left front'.
	endInstance.
	addInstanceOf: #Leg.
		name: 'left front'.
	endInstance.
endInstance.

(this was one reason I added indentation support in the writer, to give 
hints about structure and depth that actually is not there 
syntactically, but only semantically)

...then we can implement a builder for this:

createInstanceOf: aClassName
	"Create an instance of given class and put on top of stack."
	stack push: (Smalltalk at: aClassName) new


endInstance
	"Pop current object."
	stack pop


addInstanceOf: aClassName
	| obj |
	obj := (Smalltalk at: aClassName) new.
	stack top add: obj. "add the Leg to the Animal"
	stack push: obj "push Leg on stack"

name: aString
	"Yeah, we can use DNU to cover these."
	stack top name: aString

description: aString
	"Yeah, we can use DNU to cover these."
	stack top description: aString

...Also, if any of the above messages return another object instead of 
the builder (self) - that will be the receiver of the next Tirade 
message. But in order for #endInstance stuff to work we can't return a 
domain object as the receiver of the next Tirade message (to receive 
#name: and #description: directly) because it will not understand 
#endInstance and it does not have access to the builder object nor the 
stack etc.

Mmmmm, but... well, we could actually let the *TiradeReader* implement 
some Tirade messages to maintain the stack of objects that are meant to 
receive the Tirade messages. Aaaahhh. Then we let the reader implement a 
stack of receivers instead of just "let the result of this Tirade 
message be the receiver of the next Tirade message". Cool, definitely a 
useful kind of "reader".

Ok, I will add some of these examples - but to answer your question - it 
is quite easily done. :)

regards, Göran




More information about the Squeak-dev mailing list