Last published: February 22, 2007 by 'nice'
Defines 1 Classes
Extends 38 Classes
ProgramRebuilder is a convenient class aimed at storing Objects as Smalltalk code.
It outputs a program that will reconstruct a copy of the original when executed.
ProgramRebuilder acts the same as storeOn: except that it can save and restore arbitrary object graphs.
(multiple reference and circular structures).
Programs are stored in the chunk format (could be revisited in xml...).
There are good reasons for fragmenting the program into small pieces (chunk or whatever):
1) a long program cannot be compiled (byte code limit).
2) a long program is not efficient for interpreter (imply large memory).
3) errors can eventually be recovered more easily in small chunks.
User have to define rebuildProgramNodeOn: in the classes he/she wants to be stored nicely,
otherwise, default implementation use horrible instVarAt: basicAt: construct.
This is the same strategy as storeOn: except this class does not use direct stream writing.
Instead, it uses structured ProgramNode to build the program via a ProgramRebuilder passed as argument.
ProgramRebuilder then store the ProgramNode onto the stream.
This enables better formatting, correct handling of parenthesis, eventually storing into other dialects...
Note that rebuildProgramNodeOn: should always return a ProgramNode (see pre-progammed examples).
Simple objects are saved as simple messages sent to classes.
Complex objects are saved using a local environment variable.
This way, the generated program has the ability to preserve complex object graph.
Circular references can also be stored.
This version is very elementary beta with very few services.
It is just to demonstrate that save/restore strategy can use message passing and variables as its main way.
I (nicolas cellier or shorter nice) publish it with MIT licence so that people can reuse as they want...
Small test case:
| str obj sub |
sub := Set with: -3/5 with: OrderedCollection new.
dic := Dictionary new.
dic at: 1 put: #bug; at: 'foo' put: (0@0 extent: 3@6); at: 'bar' put: sub.
obj := (Array new) writeStream.
obj nextPut: sub.
obj nextPutAll: #(nil true false 1 2.0 3.0d0).
obj nextPut: 1@2.
obj nextPut: sub.
obj nextPut: dic.
obj nextPut: ((1 to: 5) asSortedCollection).
obj nextPut: (#('a' 'aaa' 'cbsz') asSortedCollection: [:a :b | a size > b size or: [a size = b size and: [a > b]]]).
obj := obj contents.
obj := obj copyWith: nil.
obj at: obj size put: obj.
str := (String new) writeStream.
(ProgramRebuilder on: str)
register: sub withName: 'coolSubCollection';
str contents inspect.
Copyright (c) <2006>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.