Differences to Io: - explicit self paramter for methods to avoid setSlot/updateSlot confusion - not everything is an object (let (set-prototype make-prototype) nil
(w/uniq bound-meth
(def make-prototype ((o prototype nil))
(annotate 'prototype (list (table) prototype)))
(defcall prototype ((table prototype) slot)
(aif table.slot it
prototype it.slot))
(def set-prototype (table slot value)
(let (table proto) rep.table
(= table.slot value)))
(def method (fun)
(annotate bound-meth fun))
(defcall proto-object (self message . args)
(let selfobj (annotate 'proto-object self)
(aif self.message
(if (isa it bound-meth) (apply rep.it selfobj args)
it)
(apply selfobj 'forward message args))))
(= root-object
(annotate 'proto-object
(make-prototype:obj forward
(method:fn (self message . args)
(prn self!name " cannot handle " message))
clone
(method:fn (self)
(annotate 'proto-object (make-prototype rep.self)))
set
(method:fn (self slot val)
(set-prototype rep.self slot val))
get
(method:fn (self slot) (rep.self slot))
print
(method:fn (self) (let (tab proto) (rep:rep self) prn.tab))
name
'proto-object)))))
(root-object 'set 'with
(method:fn (self . args)
(let new self!clone
(map (fn ((k v)) (new 'set k v)) pair.args)
new)))
;try it ((= shouter (root-object 'clone)) 'set 'print
(method:fn (self) (prn:upcase (self 'message))))
((shouter 'with 'message "hello world") 'print)
|