How to visit over packages, classes, methods (all types)

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

How to visit over packages, classes, methods (all types)

Tim Mackinnon
Hi - is there  a way to iterate over all the code in a package (or class or baseline) in a generic way (to pretty print out class definitions, and methods - including extensions ).

I was kind of hoping that with TonelWriter and Fileout and Critics that we would have a generic visitor mechanism but it seems that all of them just implemented it again - which misses a big opportunity for refactoring so that when you want to reason/print/manipulate code - it would be more straight forward.

Is there anything/anyone addressing this ? Or maybe I’ve missed an obvious trick somewhere?

Tim

Sent from my iPhone

Reply | Threaded
Open this post in threaded view
|

Re: How to visit over packages, classes, methods (all types)

Dale Henrichs-3

Tim,

I know that this doesn't answer your question, but one of the features that I'm building into Rowan is just this capability:

  • project definitions composed of package definitions
  • package definitions composed of class and class extension definitions
  • class and class extensions definitions composed of method definitions

... there are also definitions that cover what is now handled by Metacello: conditional packages, package grouping and project dependencies ...

I am intending/hoping that Rowan will eventually be available for Pharo:) ... I have to finish Rowan for GemStone first:)

Dale

On 5/19/19 10:23 AM, Tim Mackinnon wrote:
Hi - is there  a way to iterate over all the code in a package (or class or baseline) in a generic way (to pretty print out class definitions, and methods - including extensions ).

I was kind of hoping that with TonelWriter and Fileout and Critics that we would have a generic visitor mechanism but it seems that all of them just implemented it again - which misses a big opportunity for refactoring so that when you want to reason/print/manipulate code - it would be more straight forward.

Is there anything/anyone addressing this ? Or maybe I’ve missed an obvious trick somewhere? 

Tim

Sent from my iPhone

Reply | Threaded
Open this post in threaded view
|

Re: How to visit over packages, classes, methods (all types)

Tim Mackinnon
Hi Dale - thanks for chipping in. I’ve seen references to Rowan, but hadn’t investigated. Interesting. 

Were you thinking of a standard visitor pattern (Gof) or something else? And/Or, Is this visiting piece already done, or would it help if we had such a beast in Pharo that you could then reuse for your purpose?

As an aside, in a separate message, I was lamenting the complexity of managing 100 simple similar packages with the same dependency - would Rowan help with that?

Tim

Sent from my iPhone

On 20 May 2019, at 20:16, Dale Henrichs <[hidden email]> wrote:

Tim,

I know that this doesn't answer your question, but one of the features that I'm building into Rowan is just this capability:

  • project definitions composed of package definitions
  • package definitions composed of class and class extension definitions
  • class and class extensions definitions composed of method definitions

... there are also definitions that cover what is now handled by Metacello: conditional packages, package grouping and project dependencies ...

I am intending/hoping that Rowan will eventually be available for Pharo:) ... I have to finish Rowan for GemStone first:)

Dale

On 5/19/19 10:23 AM, Tim Mackinnon wrote:
Hi - is there  a way to iterate over all the code in a package (or class or baseline) in a generic way (to pretty print out class definitions, and methods - including extensions ).

I was kind of hoping that with TonelWriter and Fileout and Critics that we would have a generic visitor mechanism but it seems that all of them just implemented it again - which misses a big opportunity for refactoring so that when you want to reason/print/manipulate code - it would be more straight forward.

Is there anything/anyone addressing this ? Or maybe I’ve missed an obvious trick somewhere? 

Tim

Sent from my iPhone

Reply | Threaded
Open this post in threaded view
|

Re: How to visit over packages, classes, methods (all types)

Dale Henrichs-3


On 5/20/19 12:38 PM, Tim Mackinnon wrote:
Hi Dale - thanks for chipping in. I’ve seen references to Rowan, but hadn’t investigated. Interesting. 

Were you thinking of a standard visitor pattern (Gof) or something else? And/Or, Is this visiting piece already done, or would it help if we had such a beast in Pharo that you could then reuse for your purpose?

I haven't focused on visitors at the moment I am focusing on building out the basic definition structure ... providing apis for creating packages in projects, classes in packages and methods in classes, etc.

Currently I am using several  flavors visitors for modifications (visiting the result of comparing two project definitions) ... the most interesting pattern is that the modification visitor is being used to write only the changed structures to disk -- instead of rewriting the whole package. A modification visitor is also used by the loader to drive the loading process -- again identifying the definitions that have changed and then applying those changes to the image ...

I haven't run into a use case where I needed to use a visitor on the defintion structure itself ... so far doing projectNamed:/packageNamed:/classNamed:/methodNamed: has met my needs, but I would be interested to learn a bit more about the application that you have in mind ...


As an aside, in a separate message, I was lamenting the complexity of managing 100 simple similar packages with the same dependency - would Rowan help with that?

I assume that you are referring to this email[1]?  If so, then I do think that Rowan would simplify things as there as the whole structure is controlled by a definitions structure api, so there is an API for creating and managing packages/classes, so if you were going to add a new class that was supposed to be independently loadable then you would do something like the following:

| project className |
project := (Rowan projectNamed:'Exercise') asDefinition.	
className := 'Acronym'.
packageName := 'Exercise-', className.
((project 
	addPackageNamed: packageName 
		toComponentNamed: className 
		withConditions: 'gemstone' 
		andGroup: 'core')
	addClassNamed: className super: 'Object' category: packageName)
	addInstanceMethod: 'foo ^1' protocol: 'accessing.

((project 
	addPackageNamed: packageName, '-Test'
		toComponentNamed: className 
		withConditions: 'gemstone' 
		andGroup: 'test')
	addClassNamed: className, 'Test' super: 'TestCase' category: packageName)
	addInstanceMethod: 'test ...' protocol: 'testing.

(project componentNamed: className)
	addComponent: 'ExercismTools'.
project export. 			"to write project to disk"
project load.				"to load the project in the image"

In Rowan, packages are not independently loadable. A component is the loadable entity and it may be composed of one or more conditional packages. A component has dependencies upon other components ... One other thing about Rowan is that there is no such thing as load order ... the components/packages are loaded atomically, so dependencies may be circular.

The #export method above, writes the package and component structure to disk, and the component would look like the following:

RwComponentLoadConfiguration{
	#name : 'Acronym',
	#version : '0.1.0',
	#conditionalPackages : {
		[
			'gemstone'
		] : {
			'core' : {
				#packageNames : [
					'Exercise-Acronym'
				]
			},
			'test' : {
				#packageNames : [
					'Exercise-Acronym-Test'
				]
			}

		}
	},
	#componentNames : [ 'ExercismTools' ]
}

At the end of the day, you'd have 100 components (one for each exercise).

A "well formed" component should have tests. For something to be independently loadable, it is absolutely necessary that the independent aspect be validated by tests ... so I added a Test class and package for Acronym:) ...

ExecercismTools is a separate components with all of the necessary packages and "prereqs" defined...

Hopefully, I've given you a flavor of how I think your problem would be addressed with Rowan ... The thing that I like is that everything is a definition with an api for creating/maintaining the definitions and all of the definitions exist independent of the loaded image ... the definitions can be read/written from disk without going through a load process  ...

Let me know what you think ... as these components are still fluid at the moment, feedback will have a real impact on the end product.

Dale

[1] http://forum.world.st/The-baseline-complexity-of-tiny-big-projects-td5099495.html


Tim

Sent from my iPhone

On 20 May 2019, at 20:16, Dale Henrichs <[hidden email]> wrote:

Tim,

I know that this doesn't answer your question, but one of the features that I'm building into Rowan is just this capability:

  • project definitions composed of package definitions
  • package definitions composed of class and class extension definitions
  • class and class extensions definitions composed of method definitions

... there are also definitions that cover what is now handled by Metacello: conditional packages, package grouping and project dependencies ...

I am intending/hoping that Rowan will eventually be available for Pharo:) ... I have to finish Rowan for GemStone first:)

Dale

On 5/19/19 10:23 AM, Tim Mackinnon wrote:
Hi - is there  a way to iterate over all the code in a package (or class or baseline) in a generic way (to pretty print out class definitions, and methods - including extensions ).

I was kind of hoping that with TonelWriter and Fileout and Critics that we would have a generic visitor mechanism but it seems that all of them just implemented it again - which misses a big opportunity for refactoring so that when you want to reason/print/manipulate code - it would be more straight forward.

Is there anything/anyone addressing this ? Or maybe I’ve missed an obvious trick somewhere? 

Tim

Sent from my iPhone

Reply | Threaded
Open this post in threaded view
|

Re: How to visit over packages, classes, methods (all types)

Dale Henrichs-3
In reply to this post by Tim Mackinnon

clarification embedded below

On 5/20/19 3:43 PM, Dale Henrichs wrote:
| project className |
project := (Rowan projectNamed:'Exercise') asDefinition.	
className := 'Acronym'.
packageName := 'Exercise-', className.
((project 
	addPackageNamed: packageName 
		toComponentNamed: className 
		withConditions: 'gemstone' 
		andGroup: 'core')
	addClassNamed: className super: 'Object' category: packageName)
	addInstanceMethod: 'foo ^1' protocol: 'accessing.

((project 
	addPackageNamed: packageName, '-Test'
		toComponentNamed: className 
		withConditions: 'gemstone' 
		andGroup: 'test')
	addClassNamed: className, 'Test' super: 'TestCase' category: packageName)
	addInstanceMethod: 'test ...' protocol: 'testing.

(project componentNamed: className)
	addComponent: 'ExercismDev'.
project export. 			"to write project to disk"
project load.				"to load the project in the image"
'ExercismDev' above and 'ExercismTools' should be the same component name ('ExercismDev' ?) ... this is the component name containing the required packages ...
RwComponentLoadConfiguration{
	#name : 'Acronym',
	#version : '0.1.0',
	#conditionalPackages : {
		[
			'gemstone'
		] : {
			'core' : {
				#packageNames : [
					'Exercise-Acronym'
				]
			}
			'test' : {
				#packageNames : [
					'Exercise-Acronym-Test'
				]
			}

		}
	},
	#componentNames : [ 'ExercismTools' ]
}
Reply | Threaded
Open this post in threaded view
|

Re: How to visit over packages, classes, methods (all types)

Marcus Denker-4
In reply to this post by Tim Mackinnon


> On 19 May 2019, at 19:23, Tim Mackinnon <[hidden email]> wrote:
>
> Hi - is there  a way to iterate over all the code in a package (or class or baseline) in a generic way (to pretty print out class definitions, and methods - including extensions ).
>
> I was kind of hoping that with TonelWriter and Fileout and Critics that we would have a generic visitor mechanism but it seems that all of them just implemented it again - which misses a big opportunity for refactoring so that when you want to reason/print/manipulate code - it would be more straight forward.
>
> Is there anything/anyone addressing this ? Or maybe I’ve missed an obvious trick somewhere?
>

I think we always wanted to add some default “visitor” style way of  iterate over the structure…

I will add this higher on my priorities, because it actually should be quite simple.


        Marcus


Reply | Threaded
Open this post in threaded view
|

Re: How to visit over packages, classes, methods (all types)

Tim Mackinnon
If you have any thoughts on direction, I could take a look - I did the “dirty” and reimplemented the methods like everyone else… but it really felt like I shouldn’t have had to…

So my code looked a bit like this (where I should have used some sort of visitor with my stream instantiated, or maybe I could pass through some block,  I think)

(exercise solutionClasses asSortedCollection: [ :a :b | a name <= b name ]) do: [ :class |
                                        (exercise exercisePackage extendsClass: class)
                                                ifTrue: [
                                                        class exPrintOutExtensionsFor: exercise exercisePackage on: s ]
                                                ifFalse: [
                                                        class exPrintOutOn: s ] ] ].


And then in ClassDescription I had methods like this (noticed I need to visit the definition, the comments, the categories for class and instance etc.:

exPrintOutOn: aWriteStream
        "Print a description of the receiver on aWriteStream."

        aWriteStream
                nextPutAll: '"-- #', self name, ' (class) --"'; cr; cr;
                nextPutAll: self definition;
                nextPut: $.; cr; cr.
       
        self hasComment ifTrue: [
                aWriteStream nextPut: $".
                self comment trimBoth encodeDoublingDoubleQuotesOn: aWriteStream.
                aWriteStream nextPut: $"; cr; cr ].
       
        self exPrintOutCategoriesFor: self class on: aWriteStream.
        self exPrintOutCategoriesFor: self on: aWriteStream

> On 13 Jun 2019, at 08:26, Marcus Denker <[hidden email]> wrote:
>
>
>
>> On 19 May 2019, at 19:23, Tim Mackinnon <[hidden email]> wrote:
>>
>> Hi - is there  a way to iterate over all the code in a package (or class or baseline) in a generic way (to pretty print out class definitions, and methods - including extensions ).
>>
>> I was kind of hoping that with TonelWriter and Fileout and Critics that we would have a generic visitor mechanism but it seems that all of them just implemented it again - which misses a big opportunity for refactoring so that when you want to reason/print/manipulate code - it would be more straight forward.
>>
>> Is there anything/anyone addressing this ? Or maybe I’ve missed an obvious trick somewhere?
>>
>
> I think we always wanted to add some default “visitor” style way of  iterate over the structure…
>
> I will add this higher on my priorities, because it actually should be quite simple.
>
>
> Marcus
>
>