snit83.tcl
来自「Linux下的MSN聊天程序源码」· TCL 代码 · 共 1,971 行 · 第 1/5 页
TCL
1,971 行
# Handle hierarchical case. if {[llength $method] > 1} { set prefix {} set tokens $method while {[llength $tokens] > 1} { lappend prefix [lindex $tokens 0] set tokens [lrange $tokens 1 end] if {![catch {set methodInfo($prefix)} result]} { # Prefix is known. If it's not a prefix, throw an # error. if {[lindex $result 0] == 0} { error "$errRoot, \"$prefix\" has no submethods." } } set methodInfo($prefix) [list 1] } }}# Defines a typemethod method.proc ::snit::Comp.statement.typemethod {method arglist body} { variable compile variable typemethodInfo # FIRST, check the typemethod name against previously defined # typemethods. Comp.CheckMethodName $method 0 ::snit::typemethodInfo \ "Error in \"typemethod [list $method]...\"" CheckArgs "typemethod $method" $arglist # First, add magic reference to type. set arglist [concat type $arglist] # Next, add typevariable declarations to body: set body "%TVARDECS%\n$body" # Next, save the definition script if {[llength $method] == 1} { set typemethodInfo($method) {0 "%t::Snit_typemethod%m %t" ""} Mappend compile(defs) { proc %TYPE%::Snit_typemethod%METHOD% %ARGLIST% %BODY% } %METHOD% $method %ARGLIST% [list $arglist] %BODY% [list $body] } else { set typemethodInfo($method) {0 "%t::Snit_htypemethod%j %t" ""} Mappend compile(defs) { proc %TYPE%::Snit_htypemethod%JMETHOD% %ARGLIST% %BODY% } %JMETHOD% [join $method _] \ %ARGLIST% [list $arglist] %BODY% [list $body] }}# Defines a type constructor.proc ::snit::Comp.statement.typeconstructor {body} { variable compile if {"" != $compile(typeconstructor)} { error "too many typeconstructors" } set compile(typeconstructor) $body}# Defines a static proc in the type's namespace.proc ::snit::Comp.statement.proc {proc arglist body} { variable compile # If "ns" is defined, the proc can see instance variables. if {[lsearch -exact $arglist selfns] != -1} { # Next, add instance variable declarations to body: set body "%IVARDECS%\n$body" } # The proc can always see typevariables. set body "%TVARDECS%\n$body" append compile(defs) " # Proc $proc proc [list %TYPE%::$proc $arglist $body] "}# Defines a static variable in the type's namespace.proc ::snit::Comp.statement.typevariable {name args} { variable compile set errRoot "Error in \"typevariable $name...\"" set len [llength $args] if {$len > 2 || ($len == 2 && ![string equal [lindex $args 0] "-array"])} { error "$errRoot, too many initializers" } if {[lsearch -exact $compile(varnames) $name] != -1} { error "$errRoot, \"$name\" is already an instance variable" } lappend compile(typevarnames) $name if {$len == 1} { append compile(typevars) \ "\n\t [list ::variable $name [lindex $args 0]]" } elseif {$len == 2} { append compile(typevars) \ "\n\t [list ::variable $name]" append compile(typevars) \ "\n\t [list array set $name [lindex $args 1]]" } else { append compile(typevars) \ "\n\t [list ::variable $name]" } append compile(tvprocdec) "\n\t typevariable ${name}"}# Defines an instance variable; the definition will go in the# type's create typemethod.proc ::snit::Comp.statement.variable {name args} { variable compile set errRoot "Error in \"variable $name...\"" set len [llength $args] if {$len > 2 || ($len == 2 && ![string equal [lindex $args 0] "-array"])} { error "$errRoot, too many initializers" } if {[lsearch -exact $compile(typevarnames) $name] != -1} { error "$errRoot, \"$name\" is already a typevariable" } lappend compile(varnames) $name if {$len == 1} { append compile(instancevars) \ "\nset \${selfns}::$name [list [lindex $args 0]]\n" } elseif {$len == 2} { append compile(instancevars) \ "\narray set \${selfns}::$name [list [lindex $args 1]]\n" } append compile(ivprocdec) "\n\t " Mappend compile(ivprocdec) {::variable ${selfns}::%N} %N $name}# Defines a typecomponent, and handles component options.## component The logical name of the delegate# args options.proc ::snit::Comp.statement.typecomponent {component args} { variable compile set errRoot "Error in \"typecomponent $component...\"" # FIRST, define the component Comp.DefineTypecomponent $component $errRoot # NEXT, handle the options. set publicMethod "" set inheritFlag 0 foreach {opt val} $args { switch -exact -- $opt { -public { set publicMethod $val } -inherit { set inheritFlag $val if {![string is boolean $inheritFlag]} { error "typecomponent $component -inherit: expected boolean value, got \"$val\"" } } default { error "typecomponent $component: Invalid option \"$opt\"" } } } # NEXT, if -public specified, define the method. if {![string equal $publicMethod ""]} { Comp.statement.delegate typemethod [list $publicMethod *] to $component } # NEXT, if "-inherit 1" is specified, delegate typemethod * to # this component. if {$inheritFlag} { Comp.statement.delegate typemethod "*" to $component }}# Defines a name to be a typecomponent## The name becomes a typevariable; in addition, it gets a# write trace so that when it is set, all of the component mechanisms# get updated.## component The component nameproc ::snit::Comp.DefineTypecomponent {component {errRoot "Error"}} { variable compile if {[lsearch -exact $compile(varnames) $component] != -1} { error "$errRoot, \"$component\" is already an instance variable" } if {[lsearch -exact $compile(typecomponents) $component] == -1} { # Remember we've done this. lappend compile(typecomponents) $component # Make it a type variable with no initial value Comp.statement.typevariable $component "" # Add a write trace to do the component thing. Mappend compile(typevars) { trace variable %COMP% w \ [list ::snit::RT.TypecomponentTrace [list %TYPE%] %COMP%] } %TYPE% $compile(type) %COMP% $component }}# Defines a component, and handles component options.## component The logical name of the delegate# args options.## TBD: Ideally, it should be possible to call this statement multiple# times, possibly changing the option values. To do that, I'd need# to cache the option values and not act on them until *after* I'd# read the entire type definition.proc ::snit::Comp.statement.component {component args} { variable compile set errRoot "Error in \"component $component...\"" # FIRST, define the component Comp.DefineComponent $component $errRoot # NEXT, handle the options. set publicMethod "" set inheritFlag 0 foreach {opt val} $args { switch -exact -- $opt { -public { set publicMethod $val } -inherit { set inheritFlag $val if {![string is boolean $inheritFlag]} { error "component $component -inherit: expected boolean value, got \"$val\"" } } default { error "component $component: Invalid option \"$opt\"" } } } # NEXT, if -public specified, define the method. if {![string equal $publicMethod ""]} { Comp.statement.delegate method [list $publicMethod *] to $component } # NEXT, if -inherit is specified, delegate method/option * to # this component. if {$inheritFlag} { Comp.statement.delegate method "*" to $component Comp.statement.delegate option "*" to $component }}# Defines a name to be a component## The name becomes an instance variable; in addition, it gets a# write trace so that when it is set, all of the component mechanisms# get updated.## component The component nameproc ::snit::Comp.DefineComponent {component {errRoot "Error"}} { variable compile if {[lsearch -exact $compile(typevarnames) $component] != -1} { error "$errRoot, \"$component\" is already a typevariable" } if {[lsearch -exact $compile(components) $component] == -1} { # Remember we've done this. lappend compile(components) $component # Make it an instance variable with no initial value Comp.statement.variable $component "" # Add a write trace to do the component thing. Mappend compile(instancevars) { trace variable ${selfns}::%COMP% w \ [list ::snit::RT.ComponentTrace [list %TYPE%] $selfns %COMP%] } %TYPE% $compile(type) %COMP% $component }}# Creates a delegated method, typemethod, or option.proc ::snit::Comp.statement.delegate {what name args} { # FIRST, dispatch to correct handler. switch $what { typemethod { Comp.DelegatedTypemethod $name $args } method { Comp.DelegatedMethod $name $args } option { Comp.DelegatedOption $name $args } default { error "Error in \"delegate $what $name...\", \"$what\"?" } } if {([llength $args] % 2) != 0} { error "Error in \"delegate $what $name...\", invalid syntax" }}# Creates a delegated typemethod delegating it to a particular# typecomponent or an arbitrary command.## method The name of the method# arglist Delegation optionsproc ::snit::Comp.DelegatedTypemethod {method arglist} { variable compile variable typemethodInfo set errRoot "Error in \"delegate typemethod [list $method]...\"" # Next, parse the delegation options. set component "" set target "" set exceptions {} set pattern "" set methodTail [lindex $method end] foreach {opt value} $arglist { switch -exact $opt { to { set component $value } as { set target $value } except { set exceptions $value } using { set pattern $value } default { error "$errRoot, unknown delegation option \"$opt\"" } } } if {[string equal $component ""] && [string equal $pattern ""]} { error "$errRoot, missing \"to\"" } if {[string equal $methodTail "*"] && ![string equal $target ""]} { error "$errRoot, cannot specify \"as\" with \"*\"" } if {![string equal $methodTail "*"] && ![string equal $exceptions ""]} { error "$errRoot, can only specify \"except\" with \"*\"" } if {![string equal $pattern ""] && ![string equal $target ""]} { error "$errRoot, cannot specify both \"as\" and \"using\"" } foreach token [lrange $method 1 end-1] { if {[string equal $token "*"]} { error "$errRoot, \"*\" must be the last token." } } # NEXT, define the component if {![string equal $component ""]} { Comp.DefineTypecomponent $component $errRoot } # NEXT, define the pattern. if {[string equal $pattern ""]} { if {[string equal $methodTail "*"]} { set pattern "%c %m"
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?