Download presentation
Presentation is loading. Please wait.
Published byKristian Leonard Modified over 9 years ago
1
CS 598 Scripting Languages Design and Implementation 8. Self
2
Introduction From Wikipedia – Self is an object-oriented programming language based on the concept of prototypes. Self was a dialect of Smalltalk, being dynamically typed and using just-in-time compilation (JIT) as well as the prototype-based approach to objects: it was first used as an experimental test system for language design in the 1980s and 1990s. In 2006, Self was still being developed as part of the Klein project, which was a Self virtual machine written fully in Self. The latest version is 4.5.0 released in January 2014. 2
3
Main characteristics Resembles Smalltak with a few “significant simplification. No classes. – New objects are created by cloning other objects or by using primitive methods like _AddSlots – No “is a” (what class it is) nor “kind of”. Only “inherits from”. – Multiple inheritance No variables, but slots containing objects. SELF objects access their state information by sending messages to “ self ” self as the receiver of a nessage is typically implicit. 3
4
Objects Objects are just a (possibly empty) collection of slots Slots contain references to objects. When a slot is found in a message lookup, the objects is evaluated. An object can represent: – A value – A method – A parent. A collection of slots where to continue the search for method names. In this case, the name of the slot ends in * 4
5
Data objects Read-only and read-write slots Objects can be defined syntactically as follows: –(|slot1 = 1. slot2 <- 0. slot3|) The assignment operator = indicates that the initial value of the object is constant and cannot be changed. The assignment operator <- sign indicates an object whose value can be changed. No assignment operator defaults to “ <- nil ” Different slots are separated by. 5
6
Example 1 In a shell type: _AddSlots: (|prototypes*=()|). prototypes _AddSlots: (|ob3= (|s1=0. s2<-0. s3. s4<-nil|)|) ob3 s2: 7. ob3 s2 6
7
Example 1 _AddSlots: (|prototypes*=()|). Send message _AddSlots with parameter (|prototypes*=()|) to self (the shell). This creates a new slot in the shell containing (),an empty object. 7
8
Example 1 prototypes _AddSlots: (|ob3= (|s1=0. s2<-0. s3. s4<-nil|)|) Send the prototypes message to self. This returns the object created above. The name of all slots are names of methods. These return themselves. Then ob3 is added to the object prototypes 8
9
Example 1 prototypes _AddSlots: (|ob3= (|s1=0. s2<-0. s3. s4<-nil|)|) ob3 s2: 7. prototypes ob3 s2 The message ob3 returns the object itself. Since is not in the shell, it is sought in the slots that serve as links which include prototypes*. It is also equivalent to say prototypes ob3, but prototypes is not necessary. Since s2 is assigned with <-, there are two methods associated with the slot. Read s2 and write s2: We say that s2 is an assignable data slot or a read/write variable On the other hand s1 is a read-only variable 9
10
Methods To create a method, we can again use _AddSlots. ob3 _AddSlots: (|s5: p1 S6: p2 =(|temp| temp: p1-p2. (temp-p2)+s3)|) ob3 s5:10 S6: 20 -25 (since s3 is 5) An equivalent form to the above is: ob3 _AddSlots: (|s5: S6: p2 =(|:p1. :p2. temp| temp: p1-p2. (temp-p2)+s3)|) 10 Continuation names are capitalized. Hence no need for cascading.
11
Perent slots A unary slot name followed by an asterisk denotes a parent slot. They are used during message lookup Otehrwise they are like any other slot and can be reassigned for dynamic inheritance. 11
12
Message lookup The function send(rec, sel, args) is defined as follows: Input: – rec, the receiver of the message – sel, the message selector – args, the actual arguments Output: – res, the result object 12 Algorithm if begins_with_underscore(sel) then invoke_primitive(rec, sel, args) “primitive call” else M ← lookup(rec, sel, Ø) “do the lookup” case | M | = 0: error: message not understood | M | = 1: res ← eval(rec, M, args) | M | > 1: error: ambiguous message send end return res
13
Message lookup (cont.) Input: – obj, the object being searched for matching slots – sel, the message selector – V, the set of objects already visited along this path Output: – M, the set of matching slots Algorithm: if obj ε V then M ← Ø “cycle detection” else M ← {s ∊ obj | s.name = sel} “try local slots” if M = Ø then M ← parent_lookup(obj, sel, V) “try parent slots” end return M 13 parent_lookup(obj, sel, V): P ← {s ∊ obj | s.isParent} “all parents” M ← ⋃ lookup(s.contents, sel, V ⋃ {obj}) s ∊ P “recursively search parents” return M
14
Searching for method names The search for objects is carried out following lexical scope. So, temp is the one declared in the method. It we use self temp instead, the search will start in the surrounding object ( ob3 ). The same applies to blocks. 14
15
resend It is also possible to apply resend. This will initiate the search in the parents (equivalent to super in Smalltalk-80) The syntax is resend. It is also possible to specify which parent. IN this case is replace with the parent name: –. 15
16
Undirected resend lookup undirected_resend(rec, smh, sel, args) is defined as follows: Input: – rec, the receiver of the message – smh, the sending method holder – sel, the message selector args, the actual arguments Output: – res, the result object 16 Algorithm M ← parent_lookup(smh, sel, Ø) “do the lookup” case | M | = 0: error: message not understood | M | = 1: res ← eval(rec, M, args) | M | > 1: error: ambiguous message send end return res
17
Directed resend lookup directed_resend(rec, smh, del, sel, args) is defined as follows: Input: – rec, the receiver of the message – smh, the sending method holder – del, the name of the delegatee – sel, the message selector – args, the actual arguments Output: – res, the result object 17 Algorithm D ← {s ∊ smh | s.name = del} “find delegatee” if | D | = 0 then error: missing delegatee “one or none” M ← lookup(smh.del, sel, Ø) “do the lookup” case | M | = 0: error: message not understood | M | = 1: res ← eval(rec, M, args) | M | > 1: error: ambiguous message send end return res
18
Organization of the self world The lobby is the context in which the parser evaluates new objects. It is the receiver of all messages sent to self by expressions in the script being parsed. E.g list in the following is evaluated in the context of the lobby _AddSlots: ( | newObject = ( | entries <- list copy... | ) | ) 18
19
Organization of the self world For convenience, the lobby’s namespace is broken into three pieces, implemented as separate objects rooted at the lobby: traits – objects that encapsulate shared behavior. Typically, each prototype object has an associated traits object of the same name that describes the shared part of its behavior. globals – prototypical objects and one-of-a-kind objects (“oddballs”) mixins – small, parentless bundles of behavior designed to be “mixed into” some other object 19
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.