Skip to main content
Commonmark migration
Source Link

#Smalltalk (Smalltalk/X) (87/101 chars)#

Smalltalk (Smalltalk/X) (87/101 chars)

Version 1:

###Version 1:### definedefine a number of variables in the evaluation namespace. So this will affect interactive doIts (aka evals):

Version 2:

###Version 2:### UseUse a methodWrapper hook, which allows for any existing code to be wrapped without recompiling. The following wraps the Parser's tokenizer to look for a roman identifier to be scanned and makes it an integer. The tricky part is to dynamically detect if the calling context is from the roman empire or not. This is done using a query signal (which is technically a proceedable exception):

#Smalltalk (Smalltalk/X) (87/101 chars)#

###Version 1:### define a number of variables in the evaluation namespace. So this will affect interactive doIts (aka evals):

###Version 2:### Use a methodWrapper hook, which allows for any existing code to be wrapped without recompiling. The following wraps the Parser's tokenizer to look for a roman identifier to be scanned and makes it an integer. The tricky part is to dynamically detect if the calling context is from the roman empire or not. This is done using a query signal (which is technically a proceedable exception):

Smalltalk (Smalltalk/X) (87/101 chars)

Version 1:

define a number of variables in the evaluation namespace. So this will affect interactive doIts (aka evals):

Version 2:

Use a methodWrapper hook, which allows for any existing code to be wrapped without recompiling. The following wraps the Parser's tokenizer to look for a roman identifier to be scanned and makes it an integer. The tricky part is to dynamically detect if the calling context is from the roman empire or not. This is done using a query signal (which is technically a proceedable exception):

Source Link
blabla999
  • 2k
  • 12
  • 11

#Smalltalk (Smalltalk/X) (87/101 chars)#

of course we could easily modify the parser's tokenizer (as it is part of the class library, and as such open for modification, and always present), but a challenge is to affect only evaluations in a given context, so that the rest of the system works as usual.

###Version 1:### define a number of variables in the evaluation namespace. So this will affect interactive doIts (aka evals):

(1 to:3999) do:[:n | 
    Workspace workspaceVariables at:(n romanPrintString asUppercase) put:n]

then I can do (in a doIt, but not in compiled code):

   |a b|
   a := MMXIV.
   b := V.
   a + b

-> 2019

Notice: the 101 chars includes whitespace; actually it can be done with 87 chars.
Also notice, when define in the global Smalltalk namespace, I'd see those constants also in compiled code.

###Version 2:### Use a methodWrapper hook, which allows for any existing code to be wrapped without recompiling. The following wraps the Parser's tokenizer to look for a roman identifier to be scanned and makes it an integer. The tricky part is to dynamically detect if the calling context is from the roman empire or not. This is done using a query signal (which is technically a proceedable exception):

define the query:

InRomanScope := QuerySignal new defaultAnswer:false.

So we can ask at any time ("InRomanScope query") to get false by default.

Then wrap the scanner's checkIdentifier method:

MessageTracer 
    wrapMethod:(Scanner compiledMethodAt:#checkForKeyword:)
    onEntry:nil
    onExit:[:ctx :ret |
        InRomanScope query ifTrue:[
            |scanner string token n|

            scanner := ctx receiver.
            string := ctx argAt:1.
            (n := Integer readFromRomanString:string onError:nil) notNil
            ifTrue:[
                scanner "/ hack; there is no setter for those two
                    instVarNamed:'tokenType' put:#Integer;
                    instVarNamed:'tokenValue' put:n.
                true
            ] ifFalse:[
                ret
            ].
        ] ifFalse:[
            ret
        ]
    ].

Now the scanner works as usual, unless we are in the roman empire:

InRomanScope answer:true do:[
    (Parser evaluate:'MMDXXV') printCR.
].

-> 2525

we can even compile code:

Compiler 
    compile:'
        inTheYear2525
            ^ MMDXXV
    '
    forClass:Integer.

nice try; but this fails with a syntax error (which is exactly what we want). However, in the roman empire, we CAN compile:

InRomanScope answer:true do:[

    Compiler 
        compile:'
            inTheYear2525
                ^ MMDXXV
        '
        forClass:Integer.
]

and now, we can ask any integer (sending that message) from inside and outside of Rome:

(1000 factorial) inTheYear2525

-> 2525