Orphan Objects and Other
Reflective Techniques
Brian Foote
The Refactory, Inc.
23 April 2001
Smalltalk Solutions ‘02
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 1
Reflective Programming in
Smalltalk
• Definitions
• Building a Language Out of Objects
• Examples
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 2
Frequently Asked Questions
Q: What is reflection?
A: It’s about building your language
out of first-class, dynamic objects that
you can look at and change at runtime.
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 3
Frequently Asked Questions
Q: Haven’t people really been doing
this for a long time?
A: They certainly have. Smalltalk
programmers have been doing this
since the ‘70s.
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 4
Reflection from the
Eisenhower Era
Hence, [the machine] can, in particular,
change the orders (since these are in
memory!)--the very orders that control
its actions
--John Von Neumann 1958
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 5
Frequently Asked Questions
Q: What about efficiency?
A:
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 6
Frequently Asked Questions
Q: What about efficiency?
A: There are a variety of techniques
that can be used to make reflective
systems faster.
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 7
Frequently Asked Questions
Q: Isn’t reflection dangerous?
A: Yes! You bet it is!
A: Yes, if you are not careful.
A: Yes, but you can make it safer.
A: Yes, but so is crossing the street.
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 8
Frequently Asked Questions
Q: Isn’t reflection just a fancy name
for a few clever hacks?
A: Well, that and so much more...
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 9
Frequently Asked Questions
Q: Why is so much of the reflection
literature so hard to read?
A: This is due, in part, to the area’s AI
heritage...
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 10
Reflective Terminology
• introspection
• reflection
• reification
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 11
Reflective Terminology
• infinite regress
• causal connection
• reflective tower
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 12
Introspection
When a program can look at at the
objects from which it is built
Smalltalk has a rich, comprehensive,
indeed, unrivaled collection of
introspective facilities
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 13
Reflection
When a program can change the
objects from which it is built
Smalltalk represents as much as it can
as as first-class dynamic objects, and
you can change them at runtime.
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 14
Consider these
Meta considered harmful
“Meta” considered harmful
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 15
Neat Hack Hall of Fame
 Parentless Objects
 Does Not Understand
 Metaobjects
 Lightweight Classes
 Method Wrappers
 Byte Code Manipulation
 Compiled Method Copying
 Context Manipulation
 Source Generation
 Association Hacks
 Becomes
 Class Change
 Instance Variable At
 Methods On-Demand
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 16
Objects themselves
Object
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 17
Object Introspection
Object size == basicSize hash identityHash printOn:
storeOn:
dependents ...
allOwners firstOwner nextInstance ownerAfter:
instVarAt:
isKindOf: class isMemberOf: respondsTo:
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 18
Example:
AccessibleObjects
Demonstrates:
doesNotUnderstand:
instVarAt: instVarAt:put:
at: at:put:
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 19
Accessible Objects
AccessibleObject class methods for: examples
example
"AccessibleObject example"
| temp |
temp := AccessibleObject new.
temp dog: 'Fido'.
temp cat: 'Tabby'.
Transcript print: temp dog; cr.
Transcript print: temp items; cr.
temp keysDo: [:key | Transcript print: key; cr].
Transcript print: (temp variableAt: #items); cr.
Transcript endEntry
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 20
Accessible Objects
AccessibleObject methods for: accessing
at: key
"Return the object associated with the given key..."
^self valueAt: key
at: key put: value
"Store the indicated value at the designated place in our item
dictionary... "
^self valueAt: key put: value
size
"Let's say our size is the size of our item dictionary
plus our number of instance variables..."
^self items size + self instVarNames size
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 21
Accessible Objects
AccessibleObject methods for: accessing
valueAt: key
"Return the object associated with the given key..."
^self valueAt: key ifAbsent: [self errorKeyNotFound]
valueAt: key put: value
"Store the indicated value at the designated place in our item
dictionary, unless there is an instance var by that name..."
items isNil ifTrue: [items := IdentityDictionary new: 16].
(self hasVariableNamed: key)
ifTrue: [^self variableAt: key put: value]
ifFalse: [^items at: key put: value]
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 22
Accessible Objects
AccessibleObject methods for: instance variable access
allInstVarNames
"Define a shorthand for this class method..."
^self class allInstVarNames
hasVariableNamed: name
"Say whether we have a variable by the given name..."
^(self variableIndex: name) ~= 0
instVarNames
"Define a shorthand for this class method..."
^self class instVarNames
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 23
Accessible Objects
AccessibleObject methods for: instance variable access
variableAt: name
"Return the named value..."
| index |
index := self variableIndex: name.
index = 0 ifTrue: [self error: 'Bad instance variable name...'].
^self instVarAt: index
variableAt: name put: value
"Set the named instance variable to the indicated value..."
| index |
index := self variableIndex: name.
index = 0 ifTrue: [self error: 'Bad instance variable name...'].
^self instVarAt: index put: value
variableIndex: name
"Return the instance variable index for this name, or zero..."
^self class allInstVarNames indexOf: name asString.
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 24
Accessible Objects
AccessibleObject methods for: error interception
doesNotUnderstand: aMessage
"Refer messages we don't understand to our item dictionary..."
1)]].
| selector name args |
selector := aMessage selector.
name := (selector copyWithout: $:) asSymbol.
args := aMessage arguments.
(self hasVariableNamed: name)
ifTrue: [args size = 0
ifTrue: [^self variableAt: name]
ifFalse: [^self variableAt: name put: (args at:
(items respondsTo: selector)
ifTrue: [^items perform: selector withArguments: args].
args size = 1
ifTrue: [^self valueAt: name put: (args at: 1)]
ifFalse: [^self valueAt: name ifAbsent:
[^super doesNotUnderstand: aMessage]]
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 25
Classes and Behavior
Behavior
ClassDescription
Class
Metaclass
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 26
Organizations
ClassBuilder
SystemOrganizer
ClassOrganizer
ClassCategoryReader
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 27
Code Representation
MethodDictionary
CompiledMethod
ByteArray
BlockClosure
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 28
Runtime Enviroment
Context
MethodContext/BlockContext
Message
MessageSend
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 29
Exceptions and Events
Event
Exception
Signal
SignalHandler SignalCollection
HandlerList
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 30
Process Scheduling
Process
ProcessScheduler
Semaphore
SharedQueue
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 31
Viewing the Program
Debugger
Decompiler
Inspector
ChangeList
<Browsers>
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 32
Making a Promise
Future methodsFor: ‘demonstration’
demo
|f|
f := Future promising: [2+2].
f printString '4.0'
Future class methodsFor: 'instance creation'
promising: aBlock
| aFuture |
aFuture := self new.
^aFuture promising: aBlock
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 33
Creating an Orphan
nil subclass: #Future
instanceVariableNames: ‘semaphore '
classVariableNames: ‘ '
poolDictionaries: ' '
category: ‘Reflection-Examples’
In VisualWorks, ClassBuilder does the rest. Default
implementations of doesNotUnderstand: and class are
provided.
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 34
We’ll do it eventually...
Future methodsFor: 'initialization/dispatching'
promising: aBlock
"Create a semaphore, and fork a block that
will signal it. The result of this block is stored
in result..."
semaphore := Semaphore new.
[result := aBlock value.
semaphore signal] fork.
^self
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 35
Keeping a Promise
doesNotUndertand: aMessage
"If this is our init message, let it by..."
aMessage selector == #promising:
ifTrue: [^super perform: aMessage selector
withArguments: aMessage arguments].
"Wait until our result is available..."
semaphore wait.
"If our result is a SmallInteger, it has no oop.."
(result isKindOf: SmallInteger)
ifTrue: [result := result asFloat].
"Become the result and do the
deferred message..."
result become: self.
^self perform: aMessage selector
withArguments: aMessage arguments
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 36
Metaobjects and
Lightweight Classes
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 37
Compiler Classes
Compiler
Decompiler
CodeRegenerator
Scanner
SmalltalkCompiler
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 38
Compiler Support
CodeStream
DefineOpcodePool
MethodNodeHolder
ProgramNodeEnumerator
ScannerTable
<more>
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 39
Variables and Scopes
ArgumentVariable InstanceVariable
LocalScope LocalVariable
NameScope NullScope
PseudoVariable ReceiverVariable
RemoteVariable StaticScope
StaticVariable TemporaryVariable
UndeclaredVariable
VariableDefinition
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 40
Parse Tree Nodes
ProgramNode
MethodNode ParameterNode
StatementNode ReturnNode
ValueNode ArithmeticLoopNode
AssignmentNode CascadeNode
ConditionalNode LeafNode BlockNode
LiteralNode VariableNode LoopNode
SequenceNode SimpleMessageNode
MessageNode
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 41
Smalltalk
SystemDictionary
Association/VariableBinding
<class and pool variables>
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 42
Storage and Garbage
ObjectMemory
MemoryPolicy
WeakArray
WeakDictionary
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 43
Levels of Representation
Source
Compiler
Parse Node
ProgramNode ProgramNode
Byte Code
VM
Decompiler
Native Code
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 44
Ways to Wrap
• Source Code Modifications
• Byte Code Modifications
• New Selectors
• Dispatching Wrappers
• Class Wrappers
• Instance Wrappers
• Method Wrappers
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 45
Compiled Methods
O rd ered C o llectio n class
m eth o d D ict
…
M eth o d D ictio n ary
# rem o v eF irst
…
# [1 7 6 8 … ]
C o m p iled M etho d
m class
b y tes
so u rceC od e
1
rem o v eF irst
self em p tyC h eck .
…
# em p ty C h eck
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 46
Method Wrappers
O rd ered C o llectio n class
m eth o d D ict
…
M eth o d D ictio n ary
# rem o v eF irst
…
1 1 8 56 7 69 6
M eth o d W rap p er
m class
b y tes
clien tM eth o d
so u rceC od e
1
2
…
# [1 7 6 8 … ]
C o m p iled M etho d
m class
b y tes
so u rceC od e
1
rem o v eF irst
self em p tyC h eck .
…
# em p ty C h eck
# receiv er:
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 47
Method Wrappers
valueWithReceiver: anObject arguments: args
self beforeMethod.
^[clientMethod
valueWithReceiver: anObject
arguments: args]
valueNowOrOnUnwindDo:
[self afterMethod]
originalMethodName: argument
^#() receiver: self value: argument
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 48
Multimethods
OptimizingVisitor>>visitWithNode: aNode <ParseNode>
^self value optimized
OptimizingVisitor>>
visitWithNode: aNode <VariableNode>
^aNode lookupIn: self symbolTable
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 49
Parse Tree
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 50
Issues
Power
Safety
Efficiency
Comprehensibility
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 51
Reflection in Smalltalk
Astonishing Introspective
Highly Reflective
Intelligently Factored
Uniquely Malleable
Unappoligetically Dynamic
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 52
Frequently Asked Questions
Q: What can’t I get my hands on?
A: In ‘89 we said: sending a
message, receiving a message,
returns, and instance variable
access. Oh, and the
ObjectMemory...
Progress has been made.
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 53
Metalevel Architecture
Building languages out of objects
allows one to achieve the goals of
reflection
Loops, Lazy Reification, and Induction
Where does the language end?
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 54
Go Ye Forth and Hack
The best way to learn how do reflective
programming in Smalltalk is to read
code and experiment.
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 55
Contact Information
Brian Foote
Dept. of Computer Science
3253 DCL
1304 W. Springfield
Urbana, IL 61801
(217) 328-3523
http://www.laputan.org
[email protected]
10/3/2015 (C) Brian Foote 2002
Orphan Objects
Slide -- 56
Descargar

Escape from the Spaghetti Code Jungle