2015-02-08 19:46 GMT-03:00 Eliot Miranda <eliot.miranda@gmail.com>:
On Sun, Feb 8, 2015 at 1:26 PM, Hernán Morales Durand < hernan.morales@gmail.com> wrote:
Hi Eliot,
2015-02-08 12:50 GMT-03:00 Eliot Miranda <eliot.miranda@gmail.com>:
Hi Hernan,
On Feb 7, 2015, at 12:55 PM, Hernán Morales Durand < hernan.morales@gmail.com> wrote:
Hi Eliot,
2015-02-07 14:48 GMT-03:00 Eliot Miranda <eliot.miranda@gmail.com>:
Hi Hernan,
On Sat, Feb 7, 2015 at 7:41 AM, Hernán Morales Durand < hernan.morales@gmail.com> wrote:
2015-02-07 5:59 GMT-03:00 kilon alios <kilon.alios@gmail.com>:
Personally I don't like Pragmas, they have not convinced me so far that they fit the style of Smalltalk syntax. I have to confess though I never liked descriptive elements and languages .
Me neither. Actually the pragma idea is not wrong per se, it is the tag syntax to write them which bothers me. Because the world can be described with tags if you start that path.
How exactly is the syntax wrong?
I am not saying syntax is wrong, I just don't like it because:
1) Adds another level of representation inside an already reflective system.
What do you mean exactly? I don't have clear recollection of whether they were in Squeak in 08 or if I ported then, but at that time CompiledMethod had a properties object, and pragmas were merged into this. What I did do was save a lot of space getting rid if the properties object unless a method needed it. And IIRC I changed the implementing class from MethodProperties to AdditionalMethodState. So there was no additional level of representation. a) the syntax was already there fir primitives and b) the state was already there in methods.
The place where pragmas are located internally are not an issue for me. The fact that special tags are not following the message pattern template is. It says there is a special collector, parser, validator, etc. a whole mechanism because something is - supposedly - not easily expressible with plain reflective messages.
I don't understand. Pragmas are literal message patterns, period. There is an exception for the primitive pragma so that the variable name for a primitive's error code can be introduced, but that's part of primitive parsing, not general pragma parsing. At least in Squeak here's the code:
Parser>>pragmaSequence "Parse a sequence of method pragmas." [ (self matchToken: #<) ifFalse: [ ^ self ]. self pragmaStatement. (self matchToken: #>) ifFalse: [ ^ self expected: '>' ] ] repeat
pragmaStatement "Read a single pragma statement. Parse all generic pragmas in the form of: <key1: val1 key2: val2 ...> and remember them, including primitives." | selector arguments words index keyword | (hereType = #keyword or: [ hereType = #word or: [ hereType = #binary ] ]) ifFalse: [ ^ self expected: 'pragma declaration' ].
" This is a ugly hack into the compiler of the FFI package. FFI should be changed to use propre pragmas that can be parsed with the code here. " (here = #apicall: or: [ here = #cdecl: ]) ifTrue: [ ^ self externalFunctionDeclaration ].
selector := String new. arguments := OrderedCollection new. words := OrderedCollection new. [ hereType = #keyword or: [ (hereType = #word or: [ hereType = #binary ]) and: [ selector isEmpty ] ] ] whileTrue: [ index := self startOfNextToken + requestorOffset. selector := selector , self advance. words add: (index to: self endOfLastToken + requestorOffset). (selector last = $: or: [ selector first isLetter not ]) ifTrue: [ arguments add: (self pragmaLiteral: selector) ] ]. selector numArgs ~= arguments size ifTrue: [ ^ self expected: 'pragma argument' ]. (Symbol hasInterned: selector ifTrue: [ :value | keyword := value]) ifFalse: [ keyword := self correctSelector: selector wordIntervals: words exprInterval: (words first first to: words last last) ifAbort: [ ^ self fail ] ]. self addPragma: (Pragma keyword: keyword arguments: arguments asArray). ^ true
I can't speak for how its been implemented in Opal but I'd be surprised if it is using separate machinery. The Squeak code above is different from the normal message parsing precisely so that it can insist that arguments are only literals (pragmaLiteral: above).
Ok, I will stop here because I see contradictions and no way we can agree on them. Amazing code BTW.
2) It could be done with plain common message sends.
No it can't. Common sends are executable and we don't want pragmas executed when the method is run, we want the pragma executed when the method is added, or analysed. That was what was ugly about the use of plain sends in e.f. VMMaker, that there had to be lots of empty implementations of the messages used for metadata.
So using normal sends - prevents the metadata from being directly executed because executing them when the method is run is wrong - confuses meta level and normal level, putting them at the same level, and hence... - confusing for the programmer because its not obvious what's metadata and what's a normal send - makes analysis harder for the same reason
We are talking about different worlds here.
So let;s stop talking because I;m getting frustrated. I make a valid point about the inability to use normal selectors and you ignore my point.
Theoretically I could mark methods this way:
(Pragma for: (ASTBlockClosure >> #value:) selector: #primitive: arguments: (Array with: 60)) addPragma.
So the annotations could be written with normal message sends. And they could be tool supported, so no one gets confused.
So this is embedded in a method? So it gets evaluated every time the method is executed? Surely you're not serious.
Precisely that is what should happens behind the curtains. I cannot believe why is so hard to understand.
3) Should be (to me) "hidden" from method pane, and displayed by a specific tool inside the system browser.
I disagree. I want to see the pragma. It has essential information that shouldn't be hidden. I want to edit it easily.
I want to see and edit the pragma too, when I am really interested. Just like with the bytecodes.
And how can you in the one hand say it can be implemented as a normal message send a d at the same time want it hidden? Be consistent :-)
There is no inconsistency. I am saying they should be hidden from the method body.
The method pane you see in the browser should be used to send messages to your modeling domain (which already imposes its own difficulty), not being exploited to add meta information where meta could belong to instrumentation analysis (lint, profiling) or UI building (keymap, menu) or whatever excuse found to add more tags.
I wonder how one could refactor this method:
Greetings>>helloWorld <year: 2015> <status: #toDo> <author: 'Hernán'> <scope: #private>
<soapOperationName: #HelloWorld> <soapDocumentation: #'Returns Hello World'> <soapResult: #String> <soapStyle: #RPC>
<rmiOperationName: #HelloWorld> <rmiDocumentation: #'Returns Hello World'> <rmiResult: #String>
<asn1OperationName: #HelloWorld> <asn1Documentation: #'Returns Hello World'> <asn1Result: #UTF8String>
<dcomOperationName: #HelloWorld> <dcomDocumentation: #'Returns Hello World'> <dcomResult: #String>
^'Hello World'
Thus:
first, date & author can be recovered from the method source via timestamp, but if you want to separate the author of the text from the last editor of the method then...
Greetings>>helloWorld <addDocPage: #Greetings year: 2015 status: #toDo author: 'Hernán' scope: #private> <soapOperation: #HelloWorld documentation: #'Returns Hello World' resultType: #String style: #RPC> <rmiOperation: #HelloWorld documentation: #'Returns Hello World' resultType: #String> <asn1OperationOperation: #HelloWorld documentation: #'Returns Hello World' resultType:#UTF8String> <dcomOperation: #HelloWorld documentation: #'Returns Hello World' resultType: #String>
^'Hello World'
and then have implementations of e.g. SoapInterfaceBuilder>>soapOperation:documentation:returnType:style:, ASN1InterfaceBuilder>> asn1Operation:documentation:returnType:style:, etc, that add the method to the interface they're building.
So, assuming your interface methods are in a class hierarchy from SomeSoapInterfaceSubclass up to SomeSoapInterfaceBaseClass building looks like, e.g.:
| builder | builder := SoapInterfaceBuilder new. (Pragma allNamed: #soapOperation:documentation:returnType:style: from: SomeSoapInterfaceSubclass to: SomeSoapInterfaceBaseClass) do: [:pragma| builder method: pragma method. pragma message sendTo: builder]
But if you're able you'll do it just like this:
Greetings>>helloWorld <addDocPage: #Greetings year: 2015 status: #toDo author: 'Hernán' scope: #private> <externalOperation: #HelloWorld documentation: #'Returns Hello World' resultType: #UTF8String style: #RPC>
^'Hello World'
implement the same method in the various builders, and coerce UTF8String to String in those that only handle simple notions of string type.
Why on _earth_ are people writing 17 pragmas where I see only two?
Not the point I wanted to address, but thanks for the example and answering the questions patiently Cheers, Hernán