CS 535 Object-Oriented Programming & Design Fall Semester, 2001 Scripts and Data Files |
||
---|---|---|
© 2001, All Rights Reserved, SDSU & Roger Whitney San Diego State University -- This page last updated 08-Nov-01 |
Smalltalk as Script
Compiler evaluate: aString
Compiler evaluate: ' 1 + 2'.
Compiler evaluate: 'Transcript show: (1 + 2) printString'
| userScript | userScript := Dialog request: 'Write a Smalltalk expression' initialAnswer: '1 + 2'. Compiler evaluate: userScript.
Evaluating Blocks
Blocks can be created and executed
| script | script := Compiler evaluate: '[1 + 2]'. script value
Embedding code in a Block
| userScript compiledCode | userScript := Dialog request: 'Write a Smalltalk expression' initialAnswer: '1 + 2'. compiledCode := Compiler evaluate: '[' , userScript , ']'. compiledCode value
Errors in the Evaluated String
Syntax error
Syntax errors open a text window on the error
Compiler evaluate: '2;'
Runtime Errors
Runtime Errors open a debugger
Compiler evaluate: 'bar + 3'
Handling Errors
If the default action is not correct for your situation then
on:do: can be used to catch the errors
[Compiler evaluate: '2;'] on: Notification do: [:error | error handling code]
[Compiler evaluate: 'foo + 2'] on: Notification do: [:error | error handling code]
External Variables in the Script
There are several easy ways to provide scripts access to existing variables in a program
| scriptString scriptBlockString scriptBlock | scriptString := 'price > 10 ifTrue:[ ''expensive''] ifFalse:[ ''cheap'']'. scriptBlockString := '[:price | ' , scriptString , ' ]'. scriptBlock := Compiler evaluate: scriptBlockString. scriptBlock value: 12
evaluate:for:logged:
Evaluates code as if it were part of an object
Used primarily for tools like debugger
Violates information hiding should be avoided
Can be used to add methods to objects
Example
Smalltalk.CS535 defineClass: #SampleClass superclass: #{Core.Object} indexedType: #none private: false instanceVariableNames: 'name ' classInstanceVariableNames: '' imports: '' category: 'Course-Examples'
Instance method
name: aString name := aString
Script
| dataObject | dataObject := SampleClass new. dataObject name: 'sam'. script := ' ''the name is: '' , name '. Compiler evaluate: script for: dataObject logged: false
Since the script is run as part of the object dataObject it can access instance variable 'name'
If the logged: parameter is true the execution of the code is recorded in the change file
Undefined Variables
Evaluate the following twice
Compiler evaluate: 'foobar'
The first time you will see in the transcript:
UndefinedObject #DoIt - foobar is undeclaredThe second time this message will not appear.
What is going on?
When running code runs across an undefined variable it is stored in Undeclared. So the second time foobar already exists in Undeclared.
Just say no to Undeclared
To see if you have any undeclared variables run:
Undeclared inspect
The inspector allows you to check for existing references to undeclared variables
The inspector also allows you to remove variables from Undeclared that do not have any references.
Or you can run:
Undeclared purgeUnusedBindings
To see how many undeclared variables are in your image run:
Undeclared size
Some Simple Data Storage
Delimited Files
How to read data delineated by a special character
Example
Let the file 'names' contain the following text:
roger;tom;sally;rhea;ritu;smita
The following will read each name and put it into an ordered collection
| dataFile stream names readingBlock | dataFile := 'names' asFilename. stream := dataFile readStream. separator := $;. names := OrderedCollection new. readingBlock := [ [stream atEnd] whileFalse: [ names add: (stream upTo: separator)]]. readingBlock valueNowOrOnUnwindDo: [stream close]. ^names
ASCII Serialized Objects
Smalltalk will serialize objects
The serialize object
anObject storeOn: aWriteStream
| dataStream serializedFive | dataStream := WriteStream on: String new. 5 storeOn: dataStream. serializedFive := dataStream contents
Deserializing an Object
Use the one of the following class methods of Object
readFrom: aStream
readFromString: aString
Simple Example
| dataStream serializedFive five | dataStream := WriteStream on: String new. 5 storeOn: dataStream. serializedFive := dataStream contents. five := Object readFromString: serializedFive
More Complex ExampleClass Used in Example
Smalltalk.CS535 defineClass: #Student superclass: #{Core.Object} indexedType: #none private: false instanceVariableNames: 'name phone graduationDate ' classInstanceVariableNames: '' imports: '' category: 'Course-Examples'
CS535.Student class methods name: aString phone: aPhoneNumberString graduation: aDate ^super new setName: aString setPhone: aPhoneNumberString setGraduation: aDate
CS535.Student instance methods
printOn: aStream aStream nextPutAll: 'Student: '; nextPutAll: name; nextPutAll: ', ' ; nextPutAll: phone; nextPutAll: ', '; nextPutAll: graduationDate printString
setName: aNameString setPhone: aPhoneString setGraduation: aDate name := aNameString. phone := aPhoneString. graduationDate := aDate
Example Continued
In this example we serialize a collection of different objects
| jeff data dataStream serializedObject deserializedObject | jeff := Student name: 'jeff' phone: '543-3445' graduation: Date dateAndTimeNow. data := OrderedCollection new add: 1; add: 'cat'; add: jeff; yourself. dataStream := WriteStream on: String new. data storeOn: dataStream. serializedObject := dataStream contents. deserializedObject := Object readFromString: serializedObject. deserializedObject at: 3Result
deserializedObject at: 3 is a Student object.
serializedObject is '((Core.OrderedCollection new) add: 1; add: ''cat''; add: (CS535.Student basicNew instVarAt: 1 put: ''jeff''; instVarAt: 2 put: ''543-3445''; instVarAt: 3 put: ((Core.Array new: 2) at: 1 put: (Core.Date readFromString: ''11/7/2001''); at: 2 put: (Core.Time readFromString: ''9:59:00 pm''); yourself); yourself); yourself)'
Changing the Shape of the Class
Changes you can make to the class and still read old objects
Binary Object Storage System - BOSS
BOSS
After a search of all parcels you will be asked if BOSS 5i4 is the one you wish to load.
Select it and click on yes.
Simple Examples of Using BOSS
| binaryFile binaryWriter binaryReader five | binaryFile := 'binaryFile' asFilename. binaryWriter := BinaryObjectStorage onNew: (binaryFile writeStream). binaryWriter nextPut: 5. binaryWriter close. binaryReader := BinaryObjectStorage onOld: (binaryFile readStream). five := binaryReader next. binaryReader close. ^five
BinaryObjectStorage Methods
Instance Creation (Class Methods)
onNew: aWriteStream
Reading
next
Student Example
jeff := Student name: 'jeff' phone: '543-3445' graduation: Date dateAndTimeNow. binaryFile := 'binaryFile' asFilename. binaryWriter := BinaryObjectStorage onNew: (binaryFile writeStream). binaryWriter nextPut: jeff. binaryWriter close. binaryWriter := BinaryObjectStorage onOld: (binaryFile readStream). recovered := binaryWriter next. binaryWriter close. recovered
Changing the Shape of a Class
Changes you can make to the class and still read old objects with no extra work
How to handle changing the Instance Variable listExample with Student
First start with the instance variable list as:
instanceVariableNames: 'name phone graduationDate '
Now save an object:
jeff := Student name: 'jeff' phone: '543-3445' graduation: Date dateAndTimeNow. binaryFile := 'binaryFile' asFilename. binaryWriter := BinaryObjectStorage onNew: (binaryFile writeStream). binaryWriter nextPut: jeff. binaryWriter close.
Now change the instance variable list to:
instanceVariableNames: 'name phone graduationDate foo '
If you try to read the object you will get an error
binaryWriter := BinaryObjectStorage onOld: (binaryFile readStream). recovered := binaryWriter next. binaryWriter close. recovered
Add the Class Method to Student The following class method in Student will convert the old instance variable list to the new one.
After adding this to the class you will be able to read objects in the old format and the new format
binaryReaderBlockForVersion: oldVersion format: oldFormat oldVersion isNil ifTrue: [| inst | inst := self basicNew. ^[:oldInstanceVarList | | newList | newList := Array new: oldInstanceVarList size+1. newList at: 1 put: (oldInstanceVarList at: 1). newList at: 2 put: (oldInstanceVarList at: 2). newList at: 3 put: (oldInstanceVarList at: 3). oldInstanceVarList become: newList. oldInstanceVarList changeClassToThatOf: inst]]. ^super binaryReaderBlockForVersion: oldVersion format: oldFormat
How does this Work
Each class has a format number.
Student formatReturns the format of the current version of the Student class
When you serialize an object with BOSS the classes format number is stored
When reading a serialize object BOSS checks the current and old format numbers
If the formats match the default process is used to deserialize the object
If the formats do not match then
binaryReaderBlockForVersion:format:
is called on the objects class
This method returns a block to perform the conversion
The Conversion Block
OldInstanceVarList is the list of the instance variable objects from the old object
^[:oldInstanceVarList | | newList |Now put the list in the correct order for the new object.
This is the section of the code to change for your classes.
The rest of the code remains the same in the block
newList := Array new: oldInstanceVarList size+1. newList at: 1 put: (oldInstanceVarList at: 1). newList at: 2 put: (oldInstanceVarList at: 2). newList at: 3 put: (oldInstanceVarList at: 3).Now some magic. Transform the list into a student object
oldInstanceVarList become: newList. oldInstanceVarList changeClassToThatOf: inst]].
Multiple Old Versions
If you have multiple old versions of objects that are stored you need to have a different convert block for each one.
The format: parameter is the format of the object you are converting
Use that to select the correct convert block
binaryReaderBlockForVersion: oldVersion format: oldFormat
Copyright ©, All rights reserved.
2000 SDSU & Roger Whitney, 5500 Campanile Drive, San Diego, CA 92182-7700 USA.
OpenContent license defines the copyright on this document.
Previous    visitors since 08-Nov-01    Next