section 8: simula smalltalk evolution of software...
TRANSCRIPT
Evolution of Software Languages 1
Evolution of
Software Languages
Theo D'Hondt
Bachelor of Computer Science Faculty of Sciences and Bio-Engineering Sciences
Vrije Universiteit Brussel Academic Year 2015-2016
Section 8: Simula⇾Smalltalk
6: Simula⇾Smalltalk
Evolution of Software Languages 2
Ole-Johan Dahl Kristen Nygaard
6: Simula⇾Smalltalk
http://www.jot.fm/issues/issue_2002_09/eulogy/
Simulation language Simula I ⇾ Simula 67 Extension of Algol 60 Call-by-value default Call-by-name still around Hoare’s Record Classes
Evolution of Software Languages 3
Simula basics
6: Simula⇾Smalltalk
The development of the SIMULA languages Kristen Nygaard, Ole-Johan Dahl
HISTORY OF PROGRAMMING LANGUAGES 439, 1981 ACM ISBN 0-12-745040-8
Class class C( ... ); begin ... end;
Prefix class A class B; begin ... end;
Nested classes class A; begin
class B; begin ... end; B class C; begin ... end; ...
end;
No multiple inheritance X, Y class Z( ... ); begin ... end;
Assignment begin x := y; p :- q; end;
Garbage collection
Prefix blocks A begin
... B ...
end;
Procedures setter :- boolean procedure ( ... ) begin ... end;
Casts a qua B.c
Dot notation C.v
Class parameters class C( ... )
... new C( ...)
Virtual entities virtual procedure V( ... ) begin ... end;
Evolution of Software Languages 4
Hoare’s Record Classes
6: Simula⇾Smalltalk
https://www.cs.cmu.edu/~charlie/courses/15-214/2014-fall/slides/25-history-oo.pdf
Hoare’s Record Classes
• C. A. R. Hoare proposed Record Classes in 1966– Goal: capture similarity and variation in data structures
record class Expression (
subclassesConstant(real value),
Variable(string name),
BinaryExpr(reference(Expression) left, right;
subclasses Sum, Difference, Product, Quotient));
• Each class described a particular record structure
• A subclass shared fields from its parent
• Variables could take any type in the subclass hierarchy
• A record class discriminator provided case analysis on the record type
OO HistoryPrinciples of Software System Construction
© 2014 Jonathan Aldrich8
Expression
Constant
value: realVariable
name: stringBinaryExpr
left: reference(Expression)
right: reference(Expression)
Sum
Product Quotient
Difference
Subclassing through concatenation
Evolution of Software Languages 5
Simula example: overriding
6: Simula⇾Smalltalk
Vehicle class Bike; begin procedure sound; begin OutText("Ding ding"); OutImage; end; end;
ref (Vehicle) array vehicles (1 : 2); Integer i; vehicles (1) :- new Car; vehicles (2) :- new Bike; for i := 1 step 1 until 2 do vehicles(i).sound end;
begin class Vehicle; virtual: procedure sound is procedure sound;; begin end;
Vehicle class Car ; begin procedure sound; begin OutText("Beep beep"); OutImage; end; end;
https://www.cs.cmu.edu/~charlie/courses/15-214/2014-fall/slides/25-history-oo.pdf
taken from:
Evolution of Software Languages 6
Simula example: simulation
6: Simula⇾Smalltalk
begin ref (Car) aCar; ref (Truck) aTruck;
class Car; begin Integer N; detach; for N := 1 step 1 until 10 do begin OutText("Driving me insane"); OutImage; resume(aTruck); end; end;
class Truck; begin Integer N; detach; for N := 1 step 1 until 10 do begin OutText("Keep on truckin'"); OutImage; resume(aCar); end; end;
aCar :- new Car; aTruck :- new Truck; resume(aCar); end;
https://www.cs.cmu.edu/~charlie/courses/15-214/2014-fall/slides/25-history-oo.pdf
taken from:
Evolution of Software Languages 7
Alan Kay: Xerox PARC
6: Simula⇾Smalltalk
http://www.thepositiveencourager.global/alan-kay-on-creativity-3/
http://www.mac-history.net/
computer-history/2012-03-22/apple-and-xerox-parc
Evolution of Software Languages 8
Smalltalk 80
6: Simula⇾Smalltalk
• Requires a workstation • 1Mpixels memory-mapped display • 1Mb memory • 32bits processor • pointing device with 2 buttons
• Uses a virtual machine with bytecodes • Uses a garbage collecting memory manager • Uses a uniform memory model (image) • Uses an integrated graphical kernel • Uses an object model for all language concepts • Single inhertance, ad-hoc poymorphism • Uses strong and dynamic typing of all values • Metaprogramming and computational reflection • A true IDE
Evolution of Software Languages 9
Smalltalk-80 “the Blue Book”
6: Simula⇾Smalltalk
http://stephane.ducasse.free.fr/FreeBooks/BlueBook/Bluebook.pdf
Evolution of Software Languages 10
Smalltalk @ VUB
6: Simula⇾Smalltalk
Evolution of Software Languages 11
Terminology1
6: Simula⇾Smalltalk
Element of Smalltalk composed of private datastructures and a set of operations.
Request for an object to perform one of its operations.
Object that receives a message.
Set of messages identified by an object.
Specification of the set of objects with identical behaviour
Representative of a Class
Object
Message
Receiver
Interface
Class
Instance
Evolution of Software Languages 12
Terminology1
6: Simula⇾Smalltalk
Element of Smalltalk composed of private datastructures and a set of operations.
Request for an object to perform one of its operations.
Object that receives a message.
Set of messages identified by an object.
Specification of the set of objects with identical behaviour
Representative of a Class
Object
Message
Receiver
Interface
Class
InstanceEveryth
ing is an object
Evolution of Software Languages 13
Terminology2
6: Simula⇾Smalltalk
Instance variable
Method
Primitive method
System class
Name of a private datastructure of an object
Implementation of an operation of an object
Method directly executed by the Smalltalk virtual machine.
Class of the Smalltalk virtual image
Evolution of Software Languages 14
Literal objects
6: Simula⇾Smalltalk
Numerical Character String Symbol Aggregate
literal objects
#('January' 27 1985)
#((‘one' 1 $1) ('two' 2 $2) . . .
(‘zero' 0 $0))
Evolution of Software Languages 15
Variables
6: Simula⇾Smalltalk
Variable name
Private variables
Shared variables
Letters, digits
Lower case initial
Upper case initial
Evolution of Software Languages 16
Pseudo variables
6: Simula⇾Smalltalk
nil Undefined variable true, false Boolean values self, super Reference to receiver
Boolean object = object with interface all messages for logical operations
• Names that refer to specific objects
• Cannot be assigned a value with <-
• Some are constant
• Some have a value depending on the context
Evolution of Software Languages 17
Temporary variables
6: Simula⇾Smalltalk
• argument names and self only exist during the method activation
• moreover one can introduce local variables with the same characteristics
• these are being enumerated nominatively between message - pattern and method, preceded and followed by $| ; these are initialized to nil
Evolution of Software Languages 18
Assignment
6: Simula⇾Smalltalk
name1 <- name2 <- ... <- nameN <- expression
• binds structure as well as contents to a name
• name refers to an instance of the class determined by the expression
colour <- #('red' 'orange' 'green')
Evolution of Software Languages 19
Messages
6: Simula⇾Smalltalk
<receiver> = object that receives and implements the <selector> = identity of the message <arguments> = additional expressions that play a role in the method that implements the message
= interactions between objects
<receiver> <selector> [ <arguments> ]
Evolution of Software Languages 20
Message patterns
6: Simula⇾Smalltalk
one or two non alpha–numerical symbols ( last ≠ $–); there is exactly one argument
unary message
keyword message
numerator / denominator
operator message
alpha-numerical name and no arguments
discriminant sqrt
one or more alpha-numerical names each followed by $:; each keyword associated with an argument
letter from:'Donald' on:#(12 2 85)
Evolution of Software Languages 21
Message evaluation
6: Simula⇾Smalltalk
• The result of the evaluation of a method, consequence of the sending of a corresponding message, is an object
• Messages are bi-directional
sum <- 1 + 2 binds the integer object implementing 3 to sum
• The object returned by a method is not necessarily used
• Messages are 2nd class function calls
Evolution of Software Languages 22 6: Simula⇾Smalltalk
• Left to right for unary messages and operators
• Unary messages have precedence
D <- (b * b – (4 * a * c)) sqrt
• Parentheses are used for reversal of this rule
perimeter <- ((rectangle width) + (rectangle height)) * 2
Evolution of Software Languages 23
Expression evaluation2
6: Simula⇾Smalltalk
• in case of non–unary messages complex arguments have to be enclosed in parentheses
R width: x height y
R width: (x height y)
• operators have priority over non–unary messages
rectangle width: x * 2 height: y * 4
≠
Evolution of Software Languages 24
Cascading
6: Simula⇾Smalltalk
multiple successive messages to one object
turtle FD: 10; RT: 90; BK: 5
Evolution of Software Languages 25
Blocks
6: Simula⇾Smalltalk
• Expression of one or more sequential interactions enclosed by $[ and $] and separated by $.
• Blocks can be assigned to variables :
move <- [ turtle FD: 10. turtle RT: 90. turtle BK: 5 ]
• Does not imply the execution
• Execution occurs after sending the message value
move value
Evolution of Software Languages 26
Control structures1
6: Simula⇾Smalltalk
iteration
<integer> timesRepeat: <block>
4 timesRepeat [turtle FD: 50; RT: 90]
selection
<boolean expression> ifTrue: <block> ifFalse: <block>
x <– a > b ifTrue:[ a ] ifFalse: [ b ]
Evolution of Software Languages 27
Control structures2
6: Simula⇾Smalltalk
block arguments
= variable names with $: prefix appearing at the beginning of the block, terminated by $|
[:count :sum| [count < 10] whileTrue: [count <– count + 1. sum <– sum + array at: tel]. sum <– sum / count ] value: #(0 0)
i <– 1 . [i <= 10] whileTrue: [sum <– sum + (list at: i). i <– i + 1]
Evolution of Software Languages 28
Control structures2
6: Simula⇾Smalltalk
block arguments
= variable names with $: prefix appearing at the beginning of the block, terminated by $|
[:count :sum| [count < 10] whileTrue: [count <– count + 1. sum <– sum + array at: tel]. sum <– sum / count ] value: #(0 0)
i <– 1 . [i <= 10] whileTrue: [sum <– sum + (list at: i). i <– i + 1]
closures
Evolution of Software Languages 29
Applicative operations
6: Simula⇾Smalltalk
do: -message
collect: -message
sum <– 0 . #(1 2 3 4 5) do: [:sq | sum <– sum + (sq * sq)]
list <– #(1 2 3 4 5) collect: [:sq | sq * sq]
Evolution of Software Languages 30
Classes
6: Simula⇾Smalltalk
Objects
• For all elements in Smalltalk ( from constant to entire compiler )
• Interaction by way of messages that make functionality of the object available .
• The implementation is hidden
Each object is an instance of a class
• All objects of a class have the same interface
Evolution of Software Languages 31
Classes1
6: Simula⇾Smalltalk
• { instance variables } U { methods }
• Identified by a shared variable
- An object identifies its class
- Classes are manipulated within an expression
• A class is an object
• an instance of a class is created by sending it a
message
rt <– Rectangle new • Some classes accept additional messages
now <– Date today
Evolution of Software Languages 32
Protocol
6: Simula⇾Smalltalk
a class is implemented in 2 stages
• defines # and structure of accepted messages
• says what, not how
• is composed of message patterns
<message selector> <arguments>
selector to be used when sending the message
symbolic name(s) for the argument
Evolution of Software Languages 33
Message pattern
6: Simula⇾Smalltalk
rt <– Rectangle new.
rt lowerLeft: # (0 0) upperRight: # (10 20)
lowerLeft: lb upperRight: ra
a message pattern is compared ( " matched " ) to a message when sent, and expressions are bound to the symbolic names
message
message pattern
Evolution of Software Languages 34
Message implementation
6: Simula⇾Smalltalk
A method implements a message
• argument names refer to expressions within the message, expressions are evaluated one by one; read - only
• The return - value is stated in one of these two ways :
( 1 ) implicit, the receiver
( 2 ) explicit with arithmetic expressions, i.e. expression with prefix $^
Evolution of Software Languages 35
Variables
6: Simula⇾Smalltalk
• name of the class • instance variables • methods
remark : ±free syntax differentiation by way of fonts
a method has access to
( 1 ) instance ( 2 ) temporal ( 3 ) class ( 4 ) global ( 5 ) " pool "
Evolution of Software Languages 36
Instance variables
6: Simula⇾Smalltalk
• lower case initial
• exist for the total life time of the object
• are only visible for the implementation of the object
• represent the state of the object
Evolution of Software Languages 37
Temporary variables
6: Simula⇾Smalltalk
• lower case initial )
• only exist during the execution of a method
• are only visible for this method
• are being created / destroyed with sending of message
Evolution of Software Languages 38
Class variables
6: Simula⇾Smalltalk
• upper case initial
• identify each of the classes present ( mostly shared variables )
• visible everywhere
Evolution of Software Languages 39
Global variables
6: Simula⇾Smalltalk
• upper case initial
• instance of an object, beginning with upper case letter
• visible everywhere
Evolution of Software Languages 40
Pool variables
6: Simula⇾Smalltalk
• upper case initial
• shared " variable with limited visibility
• common to every instance of a subset of the { all classes }
Evolution of Software Languages 41
Primitive methods
6: Simula⇾Smalltalk
• most methods are implemented by sending messages to other objects
• some are directly interpreted by Smalltalk :
the primitive methods
• there are more or less a 100 " standard " primitive methods
Evolution of Software Languages 42
Named instance variables
6: Simula⇾Smalltalk
• added to the list of instance variables
• are referenced in message expressions making up the methods
• default initialisation "nil"
Evolution of Software Languages 43
Indexed instance variables1
6: Simula⇾Smalltalk
• added to the list implicitly
• there is only one indexed instance per object
• are indexed with the
at: and at:put:
messages • indexed with numbers from [ 1, … [
• 2 instances have = named i.v. but not necessary = # indexed i.v.
Evolution of Software Languages 44
Indexed instance variables2
6: Simula⇾Smalltalk
For instance in String:
at: index ( size < index ) ifTrue: [ ^ nil ] ifFalse: [ ^ self at: index ]
at: index put: value (size < index ) ifTrue: [ self error "overflow"] ifFalse: [ ^ self at: index put: value ]
Evolution of Software Languages 45
Indexed instance variables3
6: Simula⇾Smalltalk
• indexed classes ( = classes with indexed instance variables) being instantiated with
new: max
• if at: and at: put: are defined as messages upon an indexed class, then aggregates can be assigned
Evolution of Software Languages 46
Self reference
6: Simula⇾Smalltalk
• via the self pseudo variable.
• self refers to the receiver of the message that is being executed .
factorial
(self = 0) ifTrue: [ ^ 1 ]. (self < 0) ifTrue: [ self wrong: 'wrong' ] ifFalse: [ ^ self * (self - 1) factorial ]
Evolution of Software Languages 47
Subclasses
6: Simula⇾Smalltalk
• is derived from an existing class
• the instance variables are automatically copied • the list of instance variables may be extended • the methods, if not "overridden" are being copied
• " overriding" happens by introducing a homonym at the subclass level
Evolution of Software Languages 48
Class names
6: Simula⇾Smalltalk
• class-names are unique
• instance variable names are unique within a class definition
• method-names ( message pattern) are unique within a class definition
• unique within a range of superclasses
Evolution of Software Languages 49
Superclasses
6: Simula⇾Smalltalk
• a superclass of a class K = a class which K is a subclass of
• normally :for each class K there is one superclass
for each class K there are 0 or more subclasses
• this defines an hierarchical structure at the root of which we find a unique class that has no superclass: Object
Evolution of Software Languages 50
Superclass chain
6: Simula⇾Smalltalk
• consider a class K
• the series of classes, beginning at Object and ending at K such that any 2 succesive classes are each other's superclass / subclass is the superclass chain of K
• if a message M with pattern P is sent to an instance I of K, the first method encountered with pattern P in the superclass chain of K is executed
Evolution of Software Languages 51
Method lookup
6: Simula⇾Smalltalk
(1) M - pattern in K ---> corresponding method is executed
(2) M - pattern not in K
---> (a) K = Object ---> abort
(b) K <> Object ---> substitute super (K) for K and ---> (1)
Evolution of Software Languages 52
ZZZ
6: Simula⇾Smalltalk
self • refers to M's receiver ( = instance I of K )
• M's method lookup starts in K
• if delegation ---> superclass this remains the case
super • = to self
• M's method lookup starts with the superclass of the class containing the method that contains the message
Evolution of Software Languages 53
Abstract superclasses
6: Simula⇾Smalltalk
• only serve to be transformed in subclasses
• should "never" be instantiated
Evolution of Software Languages 54
Subclass framework
6: Simula⇾Smalltalk
subclassResponsibility
• standard message in Object
• self subclassResponsability generates an errormessage, and is used as implementation of a message in an abstract subclass, which should be overridden in a subclass
shouldNotImplement
• standard message in Object
• self shouldNotImplement generates an errormessage and is used as implementation of a method that is impossible to implement.
Evolution of Software Languages 55
Metaclasses1
6: Simula⇾Smalltalk
• classes are objects ---> each class is instance of a class, called metaclass
• Object is superclass of each class
Evolution of Software Languages 56
Metaclasses2
6: Simula⇾Smalltalk
the class CLASS is:
• an abstract superclass of all metaclasses
• subclass of Object
a class and its (meta)class
• are defined together
• distinction is made between " class methods " and "instance methods "
• used for for class instantiation
Evolution of Software Languages 57
Metaclasses3
6: Simula⇾Smalltalk
metaclasses inherit from superclasses with a restriction: there is a parallellism in sub / superclasses between metaclasses and classes
IF :class c1 instance of metaclass m1
class c2 instance of metaclass m2
c1 subclass of c2 m1 subclass of m2
THEN :
Evolution of Software Languages 58
Object interface1
6: Simula⇾Smalltalk
functionality:
class ---> receiver's class
isKindOf: aClass ---> true if aClass
(super*) = receiver's class
isMemberOf: aClass ---> true if aClass = receiver's class
respondsTo: aSymbol ---> true if aSymbol element is of the interface of the receiver's class
Evolution of Software Languages 59
Object interface2
6: Simula⇾Smalltalk
== anobject
= anobject
~ = anobject
~~ = anobject
hash
---> true if receiver and anobject = ---> true if receiver and anobject refer to the same components
---> unique integer reference of the receiver
---> true if receiver and anobject are not ==
---> true if receiver and anobject are not =
comparison:
Evolution of Software Languages 60
Object interface3
6: Simula⇾Smalltalk
copy :
copy ---> instance with equal instance-variable content or shared variable
shallowCopy ---> instance with shared instance variables
deepCopy ---> instance with copy of the instance variables
Evolution of Software Languages 61
Object interface4
6: Simula⇾Smalltalk
access:
at : index
at : index put : anobject
basicAt : index
basicAt : index put : anobject
size
basicSize
Evolution of Software Languages 62
Object interface5
6: Simula⇾Smalltalk
error handling:
doesNotUnderstand: aMessagestates that the receiver does not understand "aMessage"
error : aString statement of error identified by "aString" to receiver
primitiveFailed statement that systemprimitive is abused by receiver
shouldNotImplement
subClassResponsabilitysee before
Evolution of Software Languages 63
Dictionary framework1
6: Simula⇾Smalltalk
Object subclass: #AbstractDictionary instanceVariableNames: 'names values' classVariableNames: '' poolDictionaries: '' category: 'DemoDictionaries'
class methods
instantiation
new "instantiate new dictionary" | size | size := self minimalSize. ^ (super new ) initialize: size
private
minimalSize "implementation dependent initial size" self subclassResponsibility
instance methods statistics
size "dictionary size" self subclassResponsibility
Evolution of Software Languages 64
Dictionary framework2
6: Simula⇾Smalltalk
access
at: key "retrieve value corresponding to key" ^self at: key notFound: [ self error: 'key not found']
at: key notFound: block "retrieve value corresponding to key, with user error handling" | index | index := self indexAtKey: key. (index = 0) ifTrue: [ block value ] ifFalse: [ ^values at: index ]
at: key put: value "insert new key / value pair" self at: key put: value duplicate: [ self error: 'duplicate key' ]
Evolution of Software Languages 65
Dictionary framework3
6: Simula⇾Smalltalk
at: key put: value duplicate: block "insert new key / value pair with user error handling" | index | index <- self newIndexAtKey: key. (index = 0) ifTrue: [ block value ] ifFalse: [ values at: index put: value ]
at: key replace: value "replace value in existing pair" self at: key replace: value notFound: [self error: 'key not found' ]
at: key replace: value notFound: block "replace value in existing pair with user error handling" | index | index := self indexAtKey: key. (index = 0) ifTrue: [ block value ] ifFalse: [ values at: index put: value ]
Evolution of Software Languages 66
Dictionary framework4
6: Simula⇾Smalltalk
newIndexAtKey: key "locate index for new key in names" (( self indexAtKey: key) = 0) ifTrue: [ self extend . names at: names size put: key. ^ names size ] ifFalse: [ ^ 0 ]
extend "extend implementation by one pair" | oldNames oldValues newSize | oldNames := names. oldValues := values. newSize := names size + 1. names := Array new: newSize. values := Array new: newSize. (1 to: oldNames size) do: [ :index | names at: index put: ( oldNames at: index ). values at: index put: ( oldValues at: index ) ]
Evolution of Software Languages 67
Dictionary framework5
6: Simula⇾Smalltalk
AbstractDictionary subclass: #FastDictionary instanceVariableNames: 'size ' classVariableNames: '' poolDictionaries: '' category: 'DemoDictionaries'
class methods
instantiation
new "instantiate new fast dictionary" ^ (super new ) initializeSize
private
minimalSize "implementation dependent initial size" ^4
instance methods
statistics
size "dictionary size" ^size
private
Evolution of Software Languages 68
Dictionary framework6
6: Simula⇾Smalltalk
indexAtKey: key "locate index of key in names" | index | index := ( key hash \\ names size ) + 1 . [ ( names at: index ) = key ] whileFalse: [ (names at: index) isNil ifTrue: [ ^ 0 ] . index := ( index \\ names size ) + 1 ] . ^ index
newIndexAtKey: key "locate index for new key in names" | index | (size = names size) ifTrue: [ self extend ] . index := ( key hash \\ names size ) + 1 . [ ( names at: index ) = key ] whileFalse: [ (names at: index) isNil ifTrue: [ size := size + 1 . names at: index put: key . ^ index ] . index := ( index \\ names size ) + 1 ] . ^ 0
Evolution of Software Languages 69
Dictionary framework7
6: Simula⇾Smalltalk
extend "extend implementation by doubling the number of pairs" | oldNames oldValues newSize | oldNames := names. oldValues := values. newSize := names size * 2. names := Array new: newSize. values := Array new: newSize. size := 0 . (1 to: oldNames size) do: [ :index | self at: ( oldNames at: index ) put: ( oldValues at: index ) ]
initializeSize "set initial size to 0" size := 0
Evolution of Software Languages 70
Conduit framework1
6: Simula⇾Smalltalk
7
sourcesource
pipesink
join
pipe
Evolution of Software Languages 71
Conduit framework1
6: Simula⇾Smalltalk
Object subclass: #Conduit instanceVariableNames: 'name time capacity content ' classVariableNames: 'ConduitCollection ' poolDictionaries: '' category: 'Conduit-simulation'
instance methods
private
name: aName capacity: aCapacity "initialize a new Conduit" time := 0. content := 0. name := aName. capacity := aCapacity. self report: 'capacity:' with: capacity
Evolution of Software Languages 72
Conduit framework1
6: Simula⇾Smalltalk
Object subclass: #Conduit instanceVariableNames: 'name time capacity content ' classVariableNames: 'ConduitCollection ' poolDictionaries: '' category: 'Conduit-simulation'
instance methods
private
name: aName capacity: aCapacity "initialize a new Conduit" time := 0. content := 0. name := aName. capacity := aCapacity. self report: 'capacity:' with: capacity
reporting
error: aMessage "report error message" Transcript show: 't ='; tab. Transcript show: time printString; tab. Transcript show: name; tab. Transcript show: 'error:'; tab. Transcript show: aMessage; cr. self halt
report: aMessage with: aNumber "report status message" Transcript show: 't ='; tab. Transcript show: time printString; tab. Transcript show: name; tab. Transcript show: aMessage; tab. Transcript show: aNumber printString; cr
Evolution of Software Languages 73
Conduit framework1
6: Simula⇾Smalltalk
Object subclass: #Conduit instanceVariableNames: 'name time capacity content ' classVariableNames: 'ConduitCollection ' poolDictionaries: '' category: 'Conduit-simulation'
instance methods
private
name: aName capacity: aCapacity "initialize a new Conduit" time := 0. content := 0. name := aName. capacity := aCapacity. self report: 'capacity:' with: capacity
reporting
error: aMessage "report error message" Transcript show: 't ='; tab. Transcript show: time printString; tab. Transcript show: name; tab. Transcript show: 'error:'; tab. Transcript show: aMessage; cr. self halt
report: aMessage with: aNumber "report status message" Transcript show: 't ='; tab. Transcript show: time printString; tab. Transcript show: name; tab. Transcript show: aMessage; tab. Transcript show: aNumber printString; cr
processing
fill "instruct the conduit to fill itself" self subclassResponsibility
process "instruct the conduit to process itself" ^ self fill
tick "try to advance the clock" | flow | flow := self process. flow isNil ifFalse: [ content := content + flow. time := time + 1. self report: 'filled' with: flow. self report: 'contains' with: content ]
Evolution of Software Languages 74
Conduit framework1
6: Simula⇾Smalltalk
Object subclass: #Conduit instanceVariableNames: 'name time capacity content ' classVariableNames: 'ConduitCollection ' poolDictionaries: '' category: 'Conduit-simulation'
instance methods
private
name: aName capacity: aCapacity "initialize a new Conduit" time := 0. content := 0. name := aName. capacity := aCapacity. self report: 'capacity:' with: capacity
reporting
error: aMessage "report error message" Transcript show: 't ='; tab. Transcript show: time printString; tab. Transcript show: name; tab. Transcript show: 'error:'; tab. Transcript show: aMessage; cr. self halt
report: aMessage with: aNumber "report status message" Transcript show: 't ='; tab. Transcript show: time printString; tab. Transcript show: name; tab. Transcript show: aMessage; tab. Transcript show: aNumber printString; cr
processing
fill "instruct the conduit to fill itself" self subclassResponsibility
process "instruct the conduit to process itself" ^ self fill
tick "try to advance the clock" | flow | flow := self process. flow isNil ifFalse: [ content := content + flow. time := time + 1. self report: 'filled' with: flow. self report: 'contains' with: content ]
class methods
instance creation
name: aName capacity: aCapacity "instantiate a new Conduit" | conduit | conduit := super new name: aName capacity: aCapacity. ConduitCollection add: conduit. ^ conduit
new "disable message " self shouldNotImplement
simulation
run: aCount "perform simulation" aCount timesRepeat: [ ConduitCollection do: [ : conduit | conduit tick] ]
initialisation
initialize "initialise Conduit framework" Transcript clear; show: 'Conduit simulation'; cr. ConduitCollection := OrderedCollection new
Evolution of Software Languages 75
Conduit framework1
6: Simula⇾Smalltalk
Object subclass: #Conduit instanceVariableNames: 'name time capacity content ' classVariableNames: 'ConduitCollection ' poolDictionaries: '' category: 'Conduit-simulation'
instance methods
private
name: aName capacity: aCapacity "initialize a new Conduit" time := 0. content := 0. name := aName. capacity := aCapacity. self report: 'capacity:' with: capacity
reporting
error: aMessage "report error message" Transcript show: 't ='; tab. Transcript show: time printString; tab. Transcript show: name; tab. Transcript show: 'error:'; tab. Transcript show: aMessage; cr. self halt
report: aMessage with: aNumber "report status message" Transcript show: 't ='; tab. Transcript show: time printString; tab. Transcript show: name; tab. Transcript show: aMessage; tab. Transcript show: aNumber printString; cr
processing
fill "instruct the conduit to fill itself" self subclassResponsibility
process "instruct the conduit to process itself" ^ self fill
tick "try to advance the clock" | flow | flow := self process. flow isNil ifFalse: [ content := content + flow. time := time + 1. self report: 'filled' with: flow. self report: 'contains' with: content ]
class methods
instance creation
name: aName capacity: aCapacity "instantiate a new Conduit" | conduit | conduit := super new name: aName capacity: aCapacity. ConduitCollection add: conduit. ^ conduit
new "disable message " self shouldNotImplement
simulation
run: aCount "perform simulation" aCount timesRepeat: [ ConduitCollection do: [ : conduit | conduit tick] ]
initialisation
initialize "initialise Conduit framework" Transcript clear; show: 'Conduit simulation'; cr. ConduitCollection := OrderedCollection new
example
simulate "Conduit simulate" | source1 source2 pipe1 pipe2 pipe3 join1 sink1 | Conduit initialize. source1 := Source name: 'Source 1' capacity: 5 profile: #((10 1) (20 3) (40 1) (50 4) (80 1) (90 5)). pipe1 := Pipe name: 'Pipe 1' capacity: 4 inConduit: source1. source2 := Source name: 'Source 2' capacity: 4 profile: #((10 2) (20 4) (40 1) (50 2) (80 1) (90 4)). pipe2 := Pipe name: 'Pipe 2' capacity: 2 inConduit: source2. join1 := Join name: 'Join 1' capacity: 3 inConduit1: pipe1 inConduit2: pipe2 . pipe3 := Pipe name: 'Pipe 3' capacity: 3 inConduit: join1. sink1 := Sink name: 'Sink 1' capacity: 4 inConduit: pipe3. Conduit run: 50
Evolution of Software Languages 76
Conduit framework1
6: Simula⇾Smalltalk
Conduit subclass: #Sink instanceVariableNames: 'inConduit ' classVariableNames: '' poolDictionaries: '' category: 'Conduit-simulation'
instance methods
processing
fill "instruct the Sink to fill itself" ^ inConduit drain: capacity
private
inConduit: aDrainableConduit "initialize a new Sink" inConduit := aDrainableConduit
class methods
instance creation
name: aName capacity: aCapacity inConduit: aDrainableConduit "instantiate a new Source" ^ (super name: aName capacity: aCapacity) inConduit: aDrainableConduit
fill
capacity ~ section
Evolution of Software Languages 77
Conduit framework1
6: Simula⇾Smalltalk
Conduit subclass: #DrainableConduit instanceVariableNames: 'lastFlow ' classVariableNames: '' poolDictionaries: '' category: 'Conduit-simulation'
instance methods
processing
drain: maxFlow "drain the Conduit" | flow | lastFlow isNil ifFalse: [ lastFlow := nil. flow := self flush: maxFlow. content := content - flow. self report: 'drained' with: flow. ^flow ] ifTrue: [ self report: 'requested' with: maxFlow. ^ nil ]
Evolution of Software Languages 78
Conduit framework1
6: Simula⇾Smalltalk
Conduit subclass: #DrainableConduit instanceVariableNames: 'lastFlow ' classVariableNames: '' poolDictionaries: '' category: 'Conduit-simulation'
instance methods
processing
drain: maxFlow "drain the Conduit" | flow | lastFlow isNil ifFalse: [ lastFlow := nil. flow := self flush: maxFlow. content := content - flow. self report: 'drained' with: flow. ^flow ] ifTrue: [ self report: 'requested' with: maxFlow. ^ nil ]
flush: maxFlow "flush the Conduit" content > maxFlow ifTrue: [ ^ maxFlow ] ifFalse: [ ^ content ]
process "instruct the conduit to process itself" lastFlow isNil ifTrue: [ lastFlow := self fill ]. ^ lastFlow
Evolution of Software Languages 79
Conduit framework1
6: Simula⇾Smalltalk
DrainableConduit subclass: #Pipe instanceVariableNames: 'inConduit cells ' classVariableNames: 'PipeLength ' poolDictionaries: '' category: 'Conduit-simulation'
instance methods
private
inConduit: aDrainableConduit "specific initialisation" PipeLength isNil ifTrue: [ PipeLength := 10 ]. inConduit := aDrainableConduit. cells := (Array new: PipeLength) atAllPut: 0
drainfillcapacity ~ section
delay ~ length
Evolution of Software Languages
DrainableConduit subclass: #Pipe instanceVariableNames: 'inConduit cells ' classVariableNames: 'PipeLength ' poolDictionaries: '' category: 'Conduit-simulation'
instance methods
private
inConduit: aDrainableConduit "specific initialisation" PipeLength isNil ifTrue: [ PipeLength := 10 ]. inConduit := aDrainableConduit. cells := (Array new: PipeLength) atAllPut: 0
80
Conduit framework1
6: Simula⇾Smalltalk
processing
fill "instruct the Pipe to fill itself" | flow free used available | used := cells at: 1. flow := inConduit drain: capacity - used. flow isNil ifTrue: [ ^ nil ]. cells at: 1 put: used + flow. PipeLength to: 2 by: -1 do: [ : index | available := cells at: index - 1. used := cells at: index. free := capacity - used. available <= free ifTrue: [ cells at: index - 1 put: 0. cells at: index put: used + available ] ifFalse: [ cells at: index - 1 put: available - free. cells at: index put: capacity ] ]. ^ flow
Evolution of Software Languages
DrainableConduit subclass: #Pipe instanceVariableNames: 'inConduit cells ' classVariableNames: 'PipeLength ' poolDictionaries: '' category: 'Conduit-simulation'
instance methods
private
inConduit: aDrainableConduit "specific initialisation" PipeLength isNil ifTrue: [ PipeLength := 10 ]. inConduit := aDrainableConduit. cells := (Array new: PipeLength) atAllPut: 0
81
Conduit framework1
6: Simula⇾Smalltalk
processing
fill "instruct the Pipe to fill itself" | flow free used available | used := cells at: 1. flow := inConduit drain: capacity - used. flow isNil ifTrue: [ ^ nil ]. cells at: 1 put: used + flow. PipeLength to: 2 by: -1 do: [ : index | available := cells at: index - 1. used := cells at: index. free := capacity - used. available <= free ifTrue: [ cells at: index - 1 put: 0. cells at: index put: used + available ] ifFalse: [ cells at: index - 1 put: available - free. cells at: index put: capacity ] ]. ^ flow
flush: maxFlow "flush the Pipe" | available | available := cells at: PipeLength. available > maxFlow ifTrue: [ cells at: PipeLength put: (available - maxFlow). ^ maxFlow ] ifFalse: [ cells at: PipeLength put: 0. ^ available ]
Evolution of Software Languages
DrainableConduit subclass: #Pipe instanceVariableNames: 'inConduit cells ' classVariableNames: 'PipeLength ' poolDictionaries: '' category: 'Conduit-simulation'
instance methods
private
inConduit: aDrainableConduit "specific initialisation" PipeLength isNil ifTrue: [ PipeLength := 10 ]. inConduit := aDrainableConduit. cells := (Array new: PipeLength) atAllPut: 0
82
Conduit framework1
6: Simula⇾Smalltalk
processing
fill "instruct the Pipe to fill itself" | flow free used available | used := cells at: 1. flow := inConduit drain: capacity - used. flow isNil ifTrue: [ ^ nil ]. cells at: 1 put: used + flow. PipeLength to: 2 by: -1 do: [ : index | available := cells at: index - 1. used := cells at: index. free := capacity - used. available <= free ifTrue: [ cells at: index - 1 put: 0. cells at: index put: used + available ] ifFalse: [ cells at: index - 1 put: available - free. cells at: index put: capacity ] ]. ^ flow
flush: maxFlow "flush the Pipe" | available | available := cells at: PipeLength. available > maxFlow ifTrue: [ cells at: PipeLength put: (available - maxFlow). ^ maxFlow ] ifFalse: [ cells at: PipeLength put: 0. ^ available ]
class methods
instance creation
name: aName capacity: aCapacity inConduit: aDrainableConduit "instantiate a new Pipe" ^(super name: aName capacity: aCapacity) inConduit: aDrainableConduit
Evolution of Software Languages 83
Conduit framework1
6: Simula⇾Smalltalk
DrainableConduit subclass: #Join instanceVariableNames: 'inConduit1 inConduit2 flow1 flow2 ' classVariableNames: '' poolDictionaries: '' category: 'Conduit-simulation'
instance methods
processing
fill "instruct the Join to fill itself" | flow | flow1 isNil ifTrue: [ flow1 := inConduit1 drain: (capacity - content) // 2 ]. flow2 isNil ifTrue: [ flow2 := inConduit2 drain: (capacity - content + 1) // 2 ]. flow1 isNil | flow2 isNil ifTrue: [ ^ nil ] ifFalse: [ flow := flow1 + flow2. flow1 := nil. flow2 := nil. ^ flow ]
drain
delay ~ standard
fill fill
capacity ~ section
Evolution of Software Languages
DrainableConduit subclass: #Join instanceVariableNames: 'inConduit1 inConduit2 flow1 flow2 ' classVariableNames: '' poolDictionaries: '' category: 'Conduit-simulation'
instance methods
processing
fill "instruct the Join to fill itself" | flow | flow1 isNil ifTrue: [ flow1 := inConduit1 drain: (capacity - content) // 2 ]. flow2 isNil ifTrue: [ flow2 := inConduit2 drain: (capacity - content + 1) // 2 ]. flow1 isNil | flow2 isNil ifTrue: [ ^ nil ] ifFalse: [ flow := flow1 + flow2. flow1 := nil. flow2 := nil. ^ flow ]
84
Conduit framework1
6: Simula⇾Smalltalk
processing
fill "instruct the Pipe to fill itself" | flow free used available | used := cells at: 1. flow := inConduit drain: capacity - used. flow isNil ifTrue: [ ^ nil ]. cells at: 1 put: used + flow. PipeLength to: 2 by: -1 do: [ : index | available := cells at: index - 1. used := cells at: index. free := capacity - used. available <= free ifTrue: [ cells at: index - 1 put: 0. cells at: index put: used + available ] ifFalse: [ cells at: index - 1 put: available - free. cells at: index put: capacity ] ]. ^ flow
private
inConduit1: aDrainableConduit1 inConduit2: aDrainableConduit2 "initialize a new Join" inConduit1 := aDrainableConduit1. inConduit2 := aDrainableConduit2. flow1 := nil. flow2 := nil
class methods
instance creation
name: aName capacity: aCapacity inConduit1: aDrainableConduit1 inConduit2: aDrainableConduit2 "instantiate a new Join" ^ (super name: aName capacity: aCapacity) inConduit1: aDrainableConduit1 inConduit2: aDrainableConduit2
Evolution of Software Languages 85
Conduit framework1
6: Simula⇾Smalltalk
DrainableConduit subclass: #Source instanceVariableNames: 'sourceProfile produced ' classVariableNames: '' poolDictionaries: '' category: 'Conduit-simulation'
instance methods
processing
fill "instruct the Source to fill itself" | flow | flow := sourceProfile check: time. (content + flow) > capacity ifTrue: [ self report: 'overflow' with: content + flow - capacity. flow := capacity - content ]. produced := produced + flow. self report: 'produced' with: produced. ^ flow
capacity ~ volume
drain
fill
Evolution of Software Languages
DrainableConduit subclass: #Source instanceVariableNames: 'sourceProfile produced ' classVariableNames: '' poolDictionaries: '' category: 'Conduit-simulation'
instance methods
processing
fill "instruct the Source to fill itself" | flow | flow := sourceProfile check: time. (content + flow) > capacity ifTrue: [ self report: 'overflow' with: content + flow - capacity. flow := capacity - content ]. produced := produced + flow. self report: 'produced' with: produced. ^ flow
86
Conduit framework1
6: Simula⇾Smalltalk
private
profile: aSequence "specific initialisation" | item | produced := 0. sourceProfile := Profile new. 1 to: aSequence size do: [ : index | item := aSequence at: index. sourceProfile register: (item at: 1) with: (item at: 2) ]
Evolution of Software Languages
DrainableConduit subclass: #Source instanceVariableNames: 'sourceProfile produced ' classVariableNames: '' poolDictionaries: '' category: 'Conduit-simulation'
instance methods
processing
fill "instruct the Source to fill itself" | flow | flow := sourceProfile check: time. (content + flow) > capacity ifTrue: [ self report: 'overflow' with: content + flow - capacity. flow := capacity - content ]. produced := produced + flow. self report: 'produced' with: produced. ^ flow
87
Conduit framework1
6: Simula⇾Smalltalk
private
profile: aSequence "specific initialisation" | item | produced := 0. sourceProfile := Profile new. 1 to: aSequence size do: [ : index | item := aSequence at: index. sourceProfile register: (item at: 1) with: (item at: 2) ]
class methods
instance creation
name: aName capacity: aCapacity profile: aSequence "instantiate a new Source" ^ (super name: aName capacity: aCapacity) profile: aSequence Conduit initialize
Evolution of Software Languages 88
Conduit framework1
6: Simula⇾Smalltalk
Object subclass: #Profile instanceVariableNames: 'times flows top ' classVariableNames: 'MaxTable MaxTime ' poolDictionaries: '' category: 'Conduit-simulation'
instance methods
accessing
check: aTime "retrieve current flow" | time | top = 0 ifTrue: [ self error: 'Profile not initialized' ]. time := aTime rem: MaxTime. 1 to: top do: [ :index | (times at: index) >= time ifTrue: [ ^ flows at: index ] ]. ^ flows at: 1
configuration
register: aTime with: aFlow "set times and flows" top = MaxTable ifTrue: [ self error: 'Profile overflow' ]. top := top + 1. times at: top put: aTime. flows at: top put: aFlow
private
initProfile "initialize a new Profile" MaxTable isNil ifTrue: [ MaxTable := 10. MaxTime := 100 ]. top := 0. times := Array new: MaxTable. flows := Array new: MaxTable
class methods
instance creation
new "instantiate a new Profile " ^ super new initProfile
10 20
1
2
3
4
30 40 50 60 70 80 90
Evolution of Software Languages 89
Smalltalk goodies
6: Simula⇾Smalltalk
• Memory management with handles (become:)
• Garbage collection
• Integrated graphics (bitblt)
• Metaprogramming
• Processes
• Model view controller
• Collections
• ...
Evolution of Software Languages
• Memory management with handles (become:)
• Garbage collection
• Integrated graphics (bitblt)
• Metaprogramming
• Processes
• Model view controller
• Collections
• ...
90
Smalltalk goodies
6: Simula⇾Smalltalk
• No vararg (perform:)
• Closures ≠ methods
• Single image
• ...
BUT...
Evolution of Software Languages 91
Conclusion
6: Simula⇾Smalltalk
• Smalltalk is major milestone: less powerful than Lisp but much more accessible
• It made objects popular
• It made dynamic languages popular
• It made metaprogramming popular
• It made garbage collection popular
• It showed the way for GUI / IDE
• It enabled versioning and OO databases
• It led the way to Self, Java, ...
• It was/is a commercially viable platform
• And so many things more ...
Evolution of Software Languages 92
Assignment
6: Simula⇾Smalltalk
1. Make Squeak run (http://squeak.org)
2. Make Squeak run the Conduit simulation