From: Karsten Wutzke on 22 Jul 2010 07:03 Hello, I'm referring to http://groups.google.com/group/comp.lang.python/browse_thread/thread/4f9ba9816fe4fd55# I'm currently implementing what looks like a promising solution. I have one problem though. My code generator isn't awfully complex, but still I have problems trying to figure out where to put the iteration code. Ideally, this should be in the classes the generator operates on. Take the following Python code from my generator class: def handleMethod(self, method): # generate indent depending on object depth in tree indent = self.generateIndent(method) # "public final" modifierString = "" i = 0 for modifier in method.getModifiers(): if i > 0: modifierString += " " modifierString += modifier i += 1 # "String firstName, String lastName" parameterString = "" i = 0 for parameter in method.getParameters(): if i > 0: parameterString += ", " parameterString += parameter.getType() + " " + parameter.getName() i += 1 code = indentString + modifierString + " " + (method.getReturnType() is None and "" or method.getReturnType() + " ") + method.getName() + "(" + parameterString + ")" code += "\n{" # here the statements should go code += "\n}" return code The place where the statements should go would require an iteration over the statements. When looking at other code samples, you often see def accept(self, visitor): for child in self.getChildren(): child.accept(visitor) visitor.visitMyClass(self) Now, I am wondering how separation of iteration and actual code generation can be done in my situation. def accept(self, generator): for child in self.getChildren(): child.accept(generator) generator.handleMethod(self) I could of course add a parameter to handleMethod which would be the generated code for the statements, but is that design of any good use then? I'm rather tempted to ditch the idea of separating iteration and code generation, but then the use of the visitor pattern becomes more and more questionable. What is it I'm missing? Karsten
From: Karsten Wutzke on 22 Jul 2010 07:11 > # "public final" > modifierString = "" > > i = 0 > > for modifier in method.getModifiers(): > if i > 0: > modifierString += " " > modifierString += modifier > > i += 1 > And please don't comment on the code itself, as I'm just starting to learn the Python API. The above should be modifierString = " ".join(method.getModifiers()) Thanks Karsten
From: Ian on 22 Jul 2010 16:25 Hi Karsten, On 22/07/2010 12:03, Karsten Wutzke wrote: > What is it I'm missing? > I think you are making it more complicated than it really is. The visitor pattern is about bringing all the little bits that would otherwise be scattered all over many node classes into one visitor class. For code generation this means that all the code generation is done in your visitor class. For pretty-printing you have another visitor class. For code optimization a third visitor class. If there is only one sequence in which the nodes should be visited, then you can build it in to the nodes of the tree. If you need to visit your nodes in different orders you might be better off building a separated tree-walker class for each order. Thus you might have a post-order-walker for use with the code generating visitor, and a in-order-walker for a pretty-printing visitor. The optimizing walker may need to take different routes through the tree depending upon what it finds. For example, it may compute the value of the RHS of an assignment before computing the address of the LHS, so it can make better use of registers. Here the visitor class itself needs to do the walking. Regards Ian
From: Mark Lawrence on 22 Jul 2010 16:35 On 22/07/2010 12:03, Karsten Wutzke wrote: > Hello, > > I'm referring to > > http://groups.google.com/group/comp.lang.python/browse_thread/thread/4f9ba9816fe4fd55# > > I'm currently implementing what looks like a promising solution. I > have one problem though. My code generator isn't awfully complex, but > still I have problems trying to figure out where to put the iteration > code. Ideally, this should be in the classes the generator operates > on. Take the following Python code from my generator class: > > def handleMethod(self, method): > > # generate indent depending on object depth in tree > indent = self.generateIndent(method) > > # "public final" > modifierString = "" > > i = 0 > > for modifier in method.getModifiers(): > if i> 0: > modifierString += " " > modifierString += modifier > > i += 1 > > # "String firstName, String lastName" > parameterString = "" > > i = 0 > > for parameter in method.getParameters(): > if i> 0: > parameterString += ", " > parameterString += parameter.getType() + " " + > parameter.getName() > > i += 1 > > code = indentString + modifierString + " " + > (method.getReturnType() is None and "" or method.getReturnType() + " > ") + method.getName() + "(" + parameterString + ")" > > code += "\n{" > > # here the statements should go > > code += "\n}" > > return code > > The place where the statements should go would require an iteration > over the statements. When looking at other code samples, you often see > > def accept(self, visitor): > for child in self.getChildren(): > child.accept(visitor) > > visitor.visitMyClass(self) > > Now, I am wondering how separation of iteration and actual code > generation can be done in my situation. > > def accept(self, generator): > for child in self.getChildren(): > child.accept(generator) > > generator.handleMethod(self) > > I could of course add a parameter to handleMethod which would be the > generated code for the statements, but is that design of any good use > then? I'm rather tempted to ditch the idea of separating iteration and > code generation, but then the use of the visitor pattern becomes more > and more questionable. > > What is it I'm missing? > > Karsten I suggest you google for "python patterns alex martelli". From what I've read, he's forgotten more about Python and/or patterns than most of us will ever know. HTH. Mark Lawrence.
From: Karsten Wutzke on 23 Jul 2010 08:07 On 22 Jul., 22:25, Ian <hobso...(a)gmaiil.com> wrote: > Hi Karsten, > > On 22/07/2010 12:03, Karsten Wutzke wrote:> What is it I'm missing? > > I think you are making it more complicated than it really is. > > The visitor pattern is about bringing all the little bits that would > otherwise be scattered all over > many node classes into one visitor class. For code generation this means > that all the code generation is done > in your visitor class. For pretty-printing you have another visitor > class. For code optimization a third > visitor class. > > If there is only one sequence in which the nodes should be visited, then > you can build it > in to the nodes of the tree. > > If you need to visit your nodes in different orders you might be better > off building a separated > tree-walker class for each order. Thus you might have a > post-order-walker for use with the code > generating visitor, and a in-order-walker for a pretty-printing visitor. > > The optimizing walker may need to take different routes through the tree > depending > upon what it finds. For example, it may compute the value of the RHS of > an assignment > before computing the address of the LHS, so it can make better use of > registers. Here the > visitor class itself needs to do the walking. > > Regards > > Ian My objects to iterate over are plain object-structures, composites. I have only one code generation pass, so generating code and then pretty printing is not intended/possible. I have many user options to configure the code generation. The visitor pattern is ideal for that matter, because I can keep the options in the generator rather than scatter all the options into the object classes' accessor methods. (making me think the visitor is just right and not more complicated than needed) I was just curious about separating the iteration code into the object classes, because GoF said "The main reason to put the traversal strategy in the visitor is to implement a *particular complex* traversal, one that depends on the results of the operations on the object structure." My code generator isn't really THAT complex (I thought), but reviewing the latter part of the quote makes me believe I was wrong. Code generation always depends on the previous results, that is the children of a composite in the object structure. Now that I realized it, I feel great about traversing in the visitor. Python just has a few consequences that makes creating common interfaces/abstract classes a little unusual. I'm just starting to really love Python (or its API), though I don't feel I've already discovered the core what it is really about. Best regards Karsten
|
Pages: 1 Prev: an error about DJANGO_SETTINGS_MODULE Next: Convert Unix timestamp to Readable Date/time |