2 //metadoc nil description nil is a singleton object that is used as a placeholder and to mean false in Io.")
5 //doc nil clone returns self since nil is a singleton.
8 //doc nil and(expression) Returns nil without evaluating expression.
11 elseif := Object getSlot("if")
13 //doc nil then(expression) Returns nil without evaluating expression.
16 //doc nil else(expression) Returns nil without evaluating expression.
17 setSlot("else", method(v, v))
19 //doc nil or(anObject) Returns anObject if anObject is not nil. Otherwise returns nil.
20 setSlot("or", method(v, if(v, v, nil)))
22 //doc nil print Prints 'nil'. Returns self.
23 print := method(write("nil"))
25 setSlot("==", method(v, self isIdenticalTo(v)))
26 setSlot("!=", method(v, self isIdenticalTo(v) not))
28 //doc nil isNil Returns Lobby.
31 //doc nil ifNil(expression) Evaluates message.
36 // if(a
== 1) then(b
) elseif(b
== c
) then(d
) else(f
)
37 // (a
== 1) ifTrue(b
) ifFalse(c
)
40 //doc true
then Evaluates the argument
and returns nil
.
41 then := Object getSlot("evalArgAndReturnNil")
43 //doc true
elseif Does not eval argument
and returns true
.
46 //doc true
else Does not eval argument
and returns true
.
49 //doc true
ifTrue Evaluates the argument
and returns
self.
50 ifTrue := Object getSlot("evalArgAndReturnSelf")
52 //doc true
ifFalse Does not eval argument
and returns true
.
55 //doc true
and Evaluates the argument
and returns the result
.
56 setSlot("and", Object getSlot("evalArg"))
58 //doc true
or Does not eval argument
and returns true
.
61 //doc true asString Returns true
.
64 //doc true asSimpleString Returns true
.
65 asSimpleString
:= "true"
67 //doc true not Does not eval argument
and returns false
.
70 //doc true
clone Returns
self.
77 ifFalse := Object getSlot("evalArgAndReturnSelf")
78 elseif := Object getSlot("if")
79 else := Object getSlot("evalArgAndReturnNil")
81 setSlot("or", Object getSlot("evalArg"))
85 asSimpleString
:= "false"
94 ifNonNil
:= Object getSlot("thisContext")
95 ifNil := Object getSlot("evalArgAndReturnSelf")
97 ifNilEval
:= Object getSlot("evalArg")
98 ifNonNilEval
:= Object getSlot("thisContext")
102 asSimpleString
:= type
104 setSlot("and", false
)
105 setSlot("or", Object getSlot("evalArg"))
112 // I think non
-local returns can eliminate all this stopStatus stuff
115 relayStopStatus
:= method(
116 ss
:= stopStatus(r
:= call
evalArgAt(0))
117 call
sender call
setStopStatus(ss
)
121 resetStopStatus
:= method(
122 setStopStatus(Normal
)
132 return := method(arg
,
133 call
setStopStatus(Return
)
138 Eol
appendProto(Normal
)
139 Continue
appendProto(Normal
) do(
143 Break
appendProto(Normal
) do(
148 Return
appendProto(Normal
) do(
152 return := method(arg
,
153 call
setStopStatus(Return
)
154 call
sender call
setStopStatus(Return
)
164 ifNil := Object getSlot("thisContext")
165 ifNonNil
:= Object getSlot("evalArgAndReturnSelf")
167 ifNonNilEval
:= Object getSlot("evalArg")
168 ifNilEval
:= Object getSlot("thisContext")
170 setSlot("and", Object getSlot("evalArg"))
175 makeFirstCharacterLowercase
:= method(
176 if(self size
> 0, self atPut(0, self at(0) asLowercase
))
179 makeFirstCharacterUppercase
:= method(
180 if(self size
> 0, self atPut(0, self at(0) asUppercase
))
183 slicesBetween
:= method(startSeq
, endSeq
,
186 while (startIndex
:= self findSeq(startSeq
, lastIndex
),
187 endIndex
:= self findSeq(endSeq
, startIndex
+ startSeq size
)
188 endIndex
ifNil(break)
189 chunks
append(self slice(startIndex
+ startSeq size
, endIndex
))
190 lastIndex
:= endIndex
+ endSeq size
198 getSlot("self") hasLocalSlot(n
) or(getSlot("self") ancestorWithSlot(n
) != nil
)
201 //doc
Object list(...) Returns a
List containing the arguments
.
202 list := method(call
message argsEvaluatedIn(call
sender))
204 //doc
Object ..(arg
) .. is an alias
for: method(arg
, self asString
append(arg asString
))
205 setSlot("..", method(arg
, getSlot("self") asString
.. arg asString
))
207 Map addKeysAndValues
:= method(keys
, values
, keys
foreach(i
, k
, self atPut(k
, values
at(i
))); self)
209 slotDescriptionMap
:= method(
210 slotNames := getSlot("self") slotNames sort
211 slotDescs
:= slotNames map(name
, getSlot("self") getSlot(name
) asSimpleString
)
212 Map clone addKeysAndValues(slotNames, slotDescs
)
215 apropos
:= method(keyword
,
216 Protos Core
foreachSlot(name
, p
,
217 slotDescriptions
:= getSlot("p") slotDescriptionMap ?
select(k
, v
, k asMutable lowercase
containsSeq(keyword
))
219 if(slotDescriptions
and slotDescriptions size
> 0,
221 slotDescriptions keys sortInPlace
foreach(k
,
222 s
appendSeq(" ", k
alignLeft(16), " = ", slotDescriptions
at(k
), "\n")
232 slotSummary
:= method(keyword
,
233 if(getSlot("self") type == "Block" and getSlot("self") == getSlot("Block"),
234 return getSlot("self") asSimpleString
237 s
appendSeq(" ", getSlot("self") asSimpleString
, ":\n")
238 slotDescriptions
:= slotDescriptionMap
240 slotDescriptions
= slotDescriptions
select(k
, v
, k asMutable lowercase
containsSeq(keyword
))
242 slotDescriptions keys sortInPlace
foreach(k
,
243 s
appendSeq(" ", k
alignLeft(16), " = ", slotDescriptions
at(k
), "\n")
248 asString
:= getSlot("slotSummary")
250 asSimpleString
:= method(getSlot("self") type .. "_" .. getSlot("self") uniqueHexId
)
252 /*doc Object newSlot(slotName, aValue)
253 Creates a getter and setter for the slot with the name slotName
254 and sets it's default the value aValue. Returns self. For example,
255 newSlot("foo", 1) would create slot named foo with the value 1 as well as a setter method setFoo().
258 newSlot
:= method(name
, value
, doc
,
259 getSlot("self") setSlot(name
, getSlot("value"))
260 getSlot("self") setSlot("set" .. name asCapitalized
,
261 doString("method(" .. name
.. " = call evalArgAt(0); self)"))
262 //if(doc
, getSlot("self") docSlot(name
, doc
))
266 //doc
Object launchFile(pathString
) Eval file at pathString as
if from the command line in it
's folder.
268 launchFile := method(path, args,
269 args ifNil(args = List clone)
270 Lobby launchPath := path pathComponent
271 Directory setCurrentWorkingDirectory(Lobby launchPath)
272 System launchScript = path
276 //doc Object println Same as print, but also prints a new line. Returns self.
277 println := method(getSlot("self") print; write("\n"); self)
279 /*doc Object ?(aMessage)
280 description: Sends the message aMessage to the receiver if it can respond to it. Example:
282 MyObject test // performs test
283 MyObject ?test // performs test if MyObject has a slot named test
285 The search for the slot only follows the receivers proto chain.
291 if (self getSlot(m name) != nil,
292 call relayStopStatus(m doInContext(self, call sender))
299 //doc Object ancestors Returns a list of all of the receiver's ancestors as found by recursively following the protos links
.
301 ancestors
:= method(a
,
302 if(a
, if(a
detect(x
, x
isIdenticalTo(self)), return a
), a
= List clone)
304 self protos
foreach(ancestors(a
))
308 //doc
Object isKindOf(anObject
) Returns true
if anObject is in the receiver
's ancestors.
310 isKindOf := method(anObject, getSlot("self") ancestors contains(getSlot("anObject")))
312 /*doc Object super(aMessage)
313 Sends the message aMessage to the receiver's
proto with the context of
self. Example
:
315 self test(1, 2) // performs
test(1, 2) on
self
316 super(test(1, 2)) // performs
test(1, 2) on
self proto but with the context of
self
320 setSlot("super", method(
321 senderSlotContext
:= call
sender call slotContext
323 m
ifNil(Exception raise("Object super requires an argument"))
324 senderSlotContext
ifNil(Exception raise("Object super called outside of block context"))
326 ancestor
:= senderSlotContext
ancestorWithSlot(slotName
)
329 ancestor
= senderSlotContext
ancestorWithSlot(slotName
)
331 if(ancestor
isIdenticalTo(senderSlotContext
), Exception raise("Object super slot " .. slotName
.. " not found"))
332 b
:= ancestor
getSlot(slotName
)
333 if(getSlot("b") isActivatable
== false
,
336 getSlot("b") performOn(call
sender call target
, call
sender, m
, ancestor
)
341 Send the message used to activate the current method to the Object's proto.
344 Dog := Mammal clone do(
350 calling Dog init will send an init method to Mammal, but using the Dog's context.
353 setSlot("resend", method(
354 senderSlotContext
:= call
sender call slotContext
355 senderSlotContext
ifNil(Exception raise("Object resend called outside of block context"))
356 m
:= call
sender call
message
358 ancestor
:= senderSlotContext
ancestorWithSlot(slotName
)
360 if(ancestor
isIdenticalTo(nil
),
362 ancestor
= senderSlotContext
ancestorWithSlot(slotName
)
365 if(ancestor
isIdenticalTo(senderSlotContext
),
366 Exception raise("Object resend slot " .. slotName
.. " not found")
369 b
:= ancestor
getSlot(slotName
)
370 if(getSlot("b") != nil
,
371 getSlot("b") performOn(call
sender getSlot("self"), call
sender call
sender, m
, ancestor
)
378 //doc
Object list(...) Returns a
List containing the arguments
.
379 list := method(call
message argsEvaluatedIn(call
sender))
381 Object print := method(write(getSlot("self") asString
); getSlot("self"))
383 //doc
Object println Same as
print, but also prints a new line
. Returns
self.
384 println
:= method(getSlot("self") print; write("\n"); getSlot("self"))
386 //doc
Object in(aList
) Same as
: aList
contains(self)
387 in
:= method(aList
, aList
contains(self))
389 uniqueHexId
:= method("0x" .. getSlot("self") uniqueId asString
toBase(16))
392 if(call argCount
== 1,
394 self setSlot(call
message name
, nil
)
397 args
:= getSlot("m") message next arguments
398 args
atPut(1, call
argAt(0) clone)
399 getSlot("m") message next
setArguments(args
)
403 name
:= call
evalArgAt(0)
404 m
:= ("self setSlot(\"" .. name
.. "\", " .. call
argAt(1) code
.. ")") asMessage
405 self setSlot(name
, method() setMessage(m
))
410 foreachSlot
:= method(
411 self slotNames sort
foreach(n
,
412 call
sender setSlot(call
message argAt(0) name
, n
)
413 call
sender setSlot(call
message argAt(1) name
, getSlot("self") getSlot(n
))
414 r
:= call
relayStopStatus(call
evalArgAt(2))
415 if(call stopStatus isReturn
, return getSlot("r"))
416 if(call stopStatus stopLooping
,
423 /*doc Object switch(<key1>, <expression1>, <key2>, <expression2>, ...)
424 Execute an expression depending on the value of the caller. (This is an equivalent to C switch/case)
426 hour := Date hour switch(
436 for(couple
, 0, call argCount
- 2, 2,
437 if(call
evalArgAt(couple
) == self,
438 return call
relayStopStatus(call
evalArgAt(couple
+ 1))
441 if(call argCount isOdd
,
442 call
relayStopStatus(call
evalArgAt(call argCount
- 1))
448 //doc
Object isLaunchScript Returns true
if the current file was run on the command line
. Io
's version of Python's __file__
== "__main__"
449 isLaunchScript
:= method(
450 call
message label
== System launchScript
453 /*doc Object doRelativeFile(pathString)
454 Evaluates the File in the context of the receiver. Returns the result.
455 pathString is relative to the file calling doRelativeFile. (Duplicate of relativeDoFile)
457 doRelativeFile
:= method(path
,
458 self doFile(Path
with(call
message label pathComponent
, path
))
461 /*doc Object relativeDoFile(pathString)
462 Evaluates the File in the context of the receiver. Returns the result.
463 pathString is relative to the file calling doRelativeFile. (Duplicate of doRelativeFile)
465 relativeDoFile
:= getSlot("doRelativeFile")