tcleval: Little Sugar for Stooop object system:
it uses some internals of Stooop, but it is necessary coz stoop doesn't export a proc to tell the ancestors of a class. I need suggestions for this little sugar ^^.
#------------------------------------------------------------------------------
proc unknown {cmd args} {
if {[string index $cmd 0] == "@"} {
return [stooopSugar $cmd {*}$args]
} else {
error "unknown: $cmd $args"
}
}
proc stooopSugar {cmd args} {
set parts [split $cmd .]
set this [string range [lindex $parts 0] 1 end]
set method [lindex $parts 1]
set class [::stooop::classof $this]
# first check if it is a class method
if {[info procs ${class}::${method}] != ""} {
return [${class}::${method} $this {*}$args]
}
# now checks if it is a ancestor method
set baseClasses $::stooop::fullBases($class)
foreach class $baseClasses {
if {[info procs ${class}::${method}] != ""} {
${class}::${method} $this {*}$args
} else {
error "there is no suck method $method on class $class"
}
}
}
#------------------------------------------------------------------------------
Usage:
package require stooop 4 ;# load stooop package
namespace import stooop::* ;# and import class, new, ... commands
class shape { ;# base class definition
proc shape {this x y} { ;# base class constructor
set ($this,x) $x ;# data member initialization
set ($this,y) $y
}
proc ~shape {this} {} ;# base class destructor
# pure virtual draw: must be implemented in derived classes
virtual proc draw {this}
virtual proc rotate {this angle} {} ;# do nothing by default
}
proc shape::move {this x y} { ;# external member procedure definition
set ($this,x) $x
set ($this,y) $y
draw $this ;# shape::draw invokes derived class implementation
puts "and I moved to ($x,$y)"
}
class triangle { ;# class definition
proc triangle {this x y} shape {$x $y} { ;# derived from shape
# triangle constructor implementation
}
proc ~triangle {this} {}
proc draw {this} {
# triangle specific implementation
puts "i am a triangle!!!"
}
proc rotate {this angle} {
# triangle specific implementation
}
}
class circle {} ;# empty class definition, procedures are defined outside
proc circle::circle {this x y} shape {$x $y} { ;# derived from shape
# circle constructor implementation
}
proc circle::~circle {this} {}
proc circle::draw {this} {
# circle specific implementation
puts "I am a circle!!!"
}
# circle::rotate procedure is a noop, no need to overload
set s [new circle 20 20]
@$s.draw
@$s.move 10 20
set f [new triangle 10 20]
@$f.move 20 25