-
Notifications
You must be signed in to change notification settings - Fork 76
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added a draft on programmatic code manipulation #349
base: master
Are you sure you want to change the base?
Added a draft on programmatic code manipulation #349
Conversation
### Creating a new package | ||
|
||
```st | ||
package := self packageOrganizer ensurePackage: 'PackageName'. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is P12 only so maybe the name of the article should be renamed?
package := self packageOrganizer ensurePackage: 'PackageName'. | ||
``` | ||
|
||
In Playground, you can use any object or class instead of `self`: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The playground have a self so we can use the same code.
package removeFromSystem. | ||
``` | ||
|
||
**Be careful!** In Pharo 11 and earlier, this will not properly remove classes from the system. So make sure to remove all classes before you remove the package. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In Pharo 12 we can also do:
self packageOrganizer removePackage: 'PackageName'
#removePackage: can take:
- A package name and remove it
- A real package and remove it
- A name of a package that does not exist and will silently do nothing in that case.
I use this a lot to create teardowns in tests because maybe the test failed directly and no package was generated. In that case I don't want the tear down to crash.
|
||
### Creating a package without installing it | ||
|
||
_(how to create an instance of a package without installing it into the image? - e.g., for testing)_ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By definition we cannot because currently we consider that code is installed if it is in a package.
If you want to manipulate packages that are not in the global organizer you can create a new organizer:
PackageOrganizer new
(Note that this name exist only in P12+)
Or better, create a new environment that will have a new package organizer (because the environment of an environmentless organizer will still be the global environment)
SystemDictionary new
Or to avoid hard references:
self class environment class new
builder := Object << #MyClass slots: { }; package: 'MyPackage'. class := builder install. | ||
``` | ||
|
||
The first statement will return an instance of `FluidClassBuilder`. The second statement will build the class, install it into the image, and assign it to the variable. If `MyPackage` does not exist, it will be created. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is false in P12.
We had:
- FluidClassBuilder
- ShiftClassBuilder
- ShiftClassInstaller
FluidClassBuilder was created with the fluid syntax. When you wanted to install it, you had the create a ShiftClassInstaller that was delegating the building to the ShiftClassBuilder.
But this had some flaws:
- The FluidClassBuilder could not manage to build a class with a name for the superclass instead of a class object. This was bad for code generation because it meant that the superclass had to exist when you wanted to define it (even if you did not build anything)
- The ShiftClassBuilder did not had a lot of API and some other API was complex because only used internally by the installer
- The API of both was kind of close but not exactly the same and this was confusing
In P12 I merged both of them inside the ShiftClassBuilder (There is no FluidClassBuilder anymore). And I tried to make sure both strength were kept.
Here is an example of how you can create a new class without installing it into the system. You can do that by sending `build` message instead of `install` as in the previous example. | ||
|
||
```st | ||
builder := OrderedCollection << #MyCollection.myCollectionClass := builder build.myCollectionClass compile: 'generate: aNumber "Generate aNumber random integers" | rand | rand := Random new. aNumber timesRepeat: [ self add: (rand nextInteger: 100) ]'. myCollection := myCollectionClass new.myCollection generate: 4. "a MyCollection(60 5 40 11)" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No description provided.