I have a need to evaluate code where code is represented as a string.
| user | user:=123. myCode := '^user'. Compiler evaluate: myCode for: self logged: false. When I evaluate this from a workspace, this returns nil instead of 123. I am assuming the evaluation context must be passed to the Compiler to make the variable 'user' visible. How is this done? Also how can I get an object to the current workspace and the list of temporary variables? Thanks, Costas |
Costas,
> I have a need to evaluate code where code is represented as a string. > > | user | > user:=123. > myCode := '^user'. > Compiler evaluate: myCode for: self logged: false. > > When I evaluate this from a workspace, this returns nil instead of > 123. I am assuming the evaluation context must be passed to the > Compiler to make the variable 'user' visible. > How is this done? I don't think you can, workspaces are always evaluated with a receiver of nil. Also, when you evaluate the above in a workspace the "user" variable would only be created (speaking theoretically) as part of the compilation process of the complete statement (all four lines). I wouldn't think you can have a reference _within those four lines to something that will only be created as a _result of its own compilation. There are, that I can see anyway, three reasonable things you can do (below). There might be other ways, maybe involving blocks or dummy classes to give you a context in which you could evealuate the statement but I would think they would be a lot more complicated than these solutions. Evaluate the lot (a bit pointless really)- myCode := '| user | user:=123. ^user'. Compiler evaluate: myCode for: self logged: false. Insert into the compiled expression (only works when user is a simple object) - | user | user:=123. myCode := '^', user printString. Compiler evaluate: myCode for: self logged: false. Use the same technique that OA use for workspaces (works in all cases) - | user pool | user := 123. myCode := '^user'. pool := PoolDictionary new at: 'user' put: user; yourself. Compiler evaluate: myCode for: self evaluationPools: (Array with: pool) logged: false > Also how can I get an object to the current workspace and the list of > temporary variables? You'll have to expand on what you mean for both of those questions. Ian |
"Ian Bartholomew" <[hidden email]> wrote:
>Costas, > >> I have a need to evaluate code where code is represented as a string. >> >> | user | >> user:=123. >> myCode := '^user'. >> Compiler evaluate: myCode for: self logged: false. >> >> When I evaluate this from a workspace, this returns nil instead of >> 123. I am assuming the evaluation context must be passed to the >> Compiler to make the variable 'user' visible. >> How is this done? > >I don't think you can, workspaces are always evaluated with a receiver of >nil. Also, when you evaluate the above in a workspace the "user" variable >would only be created (speaking theoretically) as part of the compilation >process of the complete statement (all four lines). I wouldn't think you can >have a reference _within those four lines to something that will only be >created as a _result of its own compilation. > >There are, that I can see anyway, three reasonable things you can do >(below). There might be other ways, maybe involving blocks or dummy classes >to give you a context in which you could evealuate the statement but I would >think they would be a lot more complicated than these solutions. > >Evaluate the lot (a bit pointless really)- > >myCode := '| user | >user:=123. >^user'. >Compiler > evaluate: myCode > for: self > logged: false. > >Insert into the compiled expression (only works when user is a simple >object) - > >| user | >user:=123. >myCode := '^', user printString. >Compiler > evaluate: myCode > for: self > logged: false. > >Use the same technique that OA use for workspaces (works in all cases) - > >| user pool | >user := 123. >myCode := '^user'. >pool := PoolDictionary new at: 'user' put: user; yourself. >Compiler > evaluate: myCode > for: self > evaluationPools: (Array with: pool) > logged: false > >> Also how can I get an object to the current workspace and the list of >> temporary variables? > >You'll have to expand on what you mean for both of those questions. > I want to create a method that can create an OrderedCollection from a string as a shortcut to the normal way. Eg. user:='somebody'. password:='secret'. arr:='user. password. Date today. #something. #(1 2).' asValues. I thought it would be a breeze. So, naively, I wrote the following: String>>asValues | rs collection | rs:=ReadStream on: self. collection := OrderedCollection new. [rs atEnd] whileFalse: [ collection add: (Compiler evaluate: (rs upTo: $.) logged: false). ]. ^collection Evaluating the above you get: an OrderedCollection(nil nil Tuesday, December 26, 2000, #something #(1 2).) which is not what I want. Basically the logic is to parse the string for a '.' , evaluate whatever you get and stuff it into a collection. It works for literals but not for temporary variables which now makes sense. Of course it would work for anything provided you have a reference to the object that holds the variables. I can create an evaluationPool and pass it as a parameter, but then that defeats the purpose of the shortcut. So I was hoping that if I could get a reference to the temporary variables of the calling method (i.e. evaluate in a different context) then it would work. I know some other languages have this ability (Tcl/Tk) to do this which really is a very powerful capability. Costas |
Costas,
> I want to create a method that can create an OrderedCollection from a > string as a shortcut to the normal way. Eg. > > user:='somebody'. > password:='secret'. > arr:='user. password. Date today. #something. #(1 2).' asValues. Yes, I guessed it was something to do with the other thread that you have been taking part in. I thought that you would probably find that a general purpose shortcut for creating arrays might be bit more difficult than it first appears - I wasn't sure though, there are some clever Smalltalkers about. user:='somebody'. password:='secret'. arr := OrderedCollection new add: user; add: password; addAll: #(##(Date today) #something #(1 2)); yourself would be my best (shortest) solution and, I have to say, just as easy and clear to read IMHO, especially as I would probably not even bother with using the #addAll. Ian PS. If you want to compile the code today but run it tomorrow than using the ##(Date today) bit in my code would be an error as well |
On Tue, 26 Dec 2000 16:15:46 -0000, "Ian Bartholomew"
<[hidden email]> wrote: >Costas, > >> I want to create a method that can create an OrderedCollection from a >> string as a shortcut to the normal way. Eg. >> >> user:='somebody'. >> password:='secret'. >> arr:='user. password. Date today. #something. #(1 2).' asValues. > >Yes, I guessed it was something to do with the other thread that you have >been taking part in. I thought that you would probably find that a general >purpose shortcut for creating arrays might be bit more difficult than it >first appears - I wasn't sure though, there are some clever Smalltalkers >about. Yes, I am kind of persistent with some things but I learned a lot... Regards, Costas |
In reply to this post by Costas Menico-2
Costas,
You might want to consider the following ideas. I've chosen only mechanisms that could be added to any Smalltalk via messages. |c| c := OrderedCollection new. c << user << password << Date today << #something << #(1 2). ^c asStringList. "Or #storeString" "asStringList --> Returns a <String> composed of each item converted to a string representation and then concatenated and delimited (by default) with a $; . <#asStringList: aDelimiter> is also an option if $; is not appropriate." "SomeName;SomePassword;Tuesday, December 26, 2000;#something;#(1 2)" <!-- --> |c| c := aStringCollection asList. "Does the reverse of #asStringList" <!-- --> If Dolphin supports the Smalltalk message #storeString or some equivalent then you already have a built in behavior for simple conversion of objects into a source form. You can use the compiler to un-encode it, as in: aSourceForm := c storeString. ... c := Compiler evaluate: aSourceForm. "Or if it has #storeOn:" c storeOn: aStream. ... c := Compiler evaluate: aStringContainingTheStreamsContents. <!-- --> You might also want to consider writing some <MyEncoder> class that can take a <OrderedCollection> and return a <String>, or take a <String> and return an <OrderedCollection>. Your encoder class would then encapsulate all the specifics and would not necessarily need to involve the compiler. -- Dave Simmons [www.qks.com / www.smallscript.com] "Effectively solving a problem begins with how you express it." "Costas Menico" <[hidden email]> wrote in message news:[hidden email]... > "Ian Bartholomew" <[hidden email]> wrote: > > >Costas, > > > >> I have a need to evaluate code where code is represented as a string. > >> > >> | user | > >> user:=123. > >> myCode := '^user'. > >> Compiler evaluate: myCode for: self logged: false. > >> > >> When I evaluate this from a workspace, this returns nil instead of > >> 123. I am assuming the evaluation context must be passed to the > >> Compiler to make the variable 'user' visible. > >> How is this done? > > > >I don't think you can, workspaces are always evaluated with a receiver of > >nil. Also, when you evaluate the above in a workspace the "user" variable > >would only be created (speaking theoretically) as part of the compilation > >process of the complete statement (all four lines). I wouldn't think you > >have a reference _within those four lines to something that will only be > >created as a _result of its own compilation. > > > >There are, that I can see anyway, three reasonable things you can do > >(below). There might be other ways, maybe involving blocks or dummy classes > >to give you a context in which you could evealuate the statement but I would > >think they would be a lot more complicated than these solutions. > > > >Evaluate the lot (a bit pointless really)- > > > >myCode := '| user | > >user:=123. > >^user'. > >Compiler > > evaluate: myCode > > for: self > > logged: false. > > > >Insert into the compiled expression (only works when user is a simple > >object) - > > > >| user | > >user:=123. > >myCode := '^', user printString. > >Compiler > > evaluate: myCode > > for: self > > logged: false. > > > >Use the same technique that OA use for workspaces (works in all cases) - > > > >| user pool | > >user := 123. > >myCode := '^user'. > >pool := PoolDictionary new at: 'user' put: user; yourself. > >Compiler > > evaluate: myCode > > for: self > > evaluationPools: (Array with: pool) > > logged: false > > > >> Also how can I get an object to the current workspace and the list of > >> temporary variables? > > > >You'll have to expand on what you mean for both of those questions. > > > > I want to create a method that can create an OrderedCollection from a > string as a shortcut to the normal way. Eg. > > user:='somebody'. > password:='secret'. > arr:='user. password. Date today. #something. #(1 2).' asValues. > > I thought it would be a breeze. So, naively, I wrote the following: > > String>>asValues > | rs collection | > rs:=ReadStream on: self. > collection := OrderedCollection new. > [rs atEnd] whileFalse: [ > collection add: (Compiler evaluate: (rs upTo: $.) > logged: false). > ]. > ^collection > > Evaluating the above you get: > an OrderedCollection(nil nil Tuesday, December 26, 2000, #something > #(1 2).) > > which is not what I want. > > Basically the logic is to parse the string for a '.' , evaluate > whatever you get and stuff it into a collection. It works for literals > but not for temporary variables which now makes sense. Of course it > would work for anything provided you have a reference to the object > that holds the variables. > > I can create an evaluationPool and pass it as a parameter, but then > that defeats the purpose of the shortcut. So I was hoping that if I > could get a reference to the temporary variables of the calling method > (i.e. evaluate in a different context) then it would work. I know some > other languages have this ability (Tcl/Tk) to do this which really is > a very powerful capability. > > Costas > |
In reply to this post by Costas Menico
Costas,
Prompted by David's message, why not user:='somebody'. password:='secret'. x := OrderedCollection new << user << password << Date today << #something << #(1 2). which works in Dolphin after the implementation of one method Collection>><< something self add: something. ^self Don't know about other Smalltalks or even that it will work consistenly in Dolphin. Is Dolphin guaranteed to do the above left to right? You can change the symbol used but there are a restrictions due to Dolphin's compiler, you can't use the more obvious + for example. Ian |
In reply to this post by David Simmons
> > >> I have a need to evaluate code where code is represented as a string.
> > >> > > >> | user | > > >> user:=123. > > >> myCode := '^user'. > > >> Compiler evaluate: myCode for: self logged: false. > > >> > > >> When I evaluate this from a workspace, this returns nil instead of > > >> 123. I am assuming the evaluation context must be passed to the > > >> Compiler to make the variable 'user' visible. > > >> How is this done? In VisualWorks it can be accessed as the psuedoVariable named thisContext. The following workspace code will evaluate to 123: | user myCode | myCode := '^user'. user:=123. Compiler new evaluate: myCode in: thisContext receiver: nil notifying: nil ifFail: nil What are you writing, a new debugger? Why else would do you need this? (all kinds of alarm bells are ringing: there must be a prettier and *safer* way to do what you need) Cheers! Reinout ------- |
Reinout Heeck <[hidden email]> wrote:
> >> > >> I have a need to evaluate code where code is represented as a string. >> > >> >> > >> | user | >> > >> user:=123. >> > >> myCode := '^user'. >> > >> Compiler evaluate: myCode for: self logged: false. >> > >> >> > >> When I evaluate this from a workspace, this returns nil instead of >> > >> 123. I am assuming the evaluation context must be passed to the >> > >> Compiler to make the variable 'user' visible. >> > >> How is this done? > > >In VisualWorks it can be accessed as the psuedoVariable named >thisContext. > >The following workspace code will evaluate to 123: > >| user myCode | >myCode := '^user'. >user:=123. >Compiler new > evaluate: myCode > in: thisContext > receiver: nil > notifying: nil > ifFail: nil > > >What are you writing, a new debugger? >Why else would do you need this? (all kinds of alarm bells are ringing: >there must be a prettier and *safer* way to do what you need) This is exactly what I am looking for. A thisContext type of variable or message. I am not sure if Dolphin supports this. They may in an indirect way. They have a for: instead of in: but that is used to pass an object as the context. Costas |
Free forum by Nabble | Edit this page |