00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 package require Tcl 8.4
00012 package require snit
00013 package require struct::list
00014 package require struct::
00015
00016 snit = ::type ::treeql {
00017 variable nodes ;
00018 variable tree ;
00019 variable query ;
00020
00021
00022 ret treeObj () {
00023 return $tree
00024 }
00025
00026
00027
00028 ret apply (type cmd , type args) {
00029 set result {}
00030 foreach node $nodes {
00031 if {[catch {
00032 eval [list $tree] $cmd [list $node] $args
00033 } application]} {
00034 upvar ::errorInfo eo
00035 puts stderr "apply: $tree $cmd $node $args -> $application - $eo"
00036 } else {
00037 #puts stderr "Apply: $tree $cmd $node $args -> $application"
00038 foreach a $application {lappend result $a}
00039 }
00040 }
00041
00042 return $result
00043 }
00044
00045
00046
00047 ret filter (type cmd , type args) {
00048 set result {}
00049 foreach node $nodes {
00050 if {[catch {
00051 eval [list $tree] $cmd [list $node] $args
00052 } application]} {
00053 upvar ::errorInfo eo
00054 puts stderr "filter: $tree $cmd $node $args -> $application - $eo"
00055 } else {
00056 #puts stderr "Filter: $tree $cmd $node $args -> $application"
00057 if {$application != {}} {
00058 lappend result $application
00059 }
00060 }
00061 }
00062 return $result
00063 }
00064
00065
00066
00067 ret bool (type cmd , type args) {
00068
00069 #puts stderr "Bool: $tree $cmd - $args"
00070 #set result [::struct::list filter $nodes [list $tree $cmd {*}$args]]
00071 #puts stderr "Bool: $tree $cmd - $nodes - $args -> $result"
00072 #return $result
00073
00074 # replaced by tcllib's list filter
00075 set result {}
00076 foreach node $nodes {
00077 if {[catch {
00078 eval [list $tree] $cmd [list $node] $args
00079 } application]} {
00080 upvar ::errorInfo eo
00081 puts stderr "filter: $tree $cmd $node $args -> $application - $eo"
00082 } else {
00083 #puts stderr "bool: $tree $cmd $node $args -> $application - [$tree dump $node]"
00084 if {$application} {
00085 lappend result $node
00086 }
00087 }
00088 }
00089
00090 return $result
00091 }
00092
00093
00094 ret applyself (type cmd , type args) {
00095
00096 set result {}
00097 foreach node $nodes {
00098 if {[catch {
00099 eval [list $query] $cmd [list $node] $args
00100 } application]} {
00101 upvar ::errorInfo eo
00102 puts stderr "applyself: $tree $cmd $node $args -> $application - $eo"
00103 } else {
00104 if {[llength $application]} {
00105 foreach a $application {lappend result $a}
00106 }
00107 }
00108 }
00109
00110 return $result
00111 }
00112
00113
00114 ret mapself (type cmd , type args) {
00115
00116 set result {}
00117 foreach node $nodes {
00118 if {[catch {
00119 eval [list $query] $cmd [list $node] $args
00120 } application]} {
00121 upvar ::errorInfo eo
00122 puts stderr "mapself: $tree $cmd $node $args -> $application - $eo"
00123 } else {
00124 #puts stderr "Mapself: $query $cmd $node $args -> $application"
00125 lappend result $application
00126 }
00127 }
00128
00129 return $result
00130 }
00131
00132
00133 ret do_attr (type node , type op , type attr) {
00134 set attrv [$tree get $node $attr]
00135 #puts stderr "$self do_attr node:'$node' op:'$op' attr:'$attr' attrv:'$attrv'"
00136 return [eval [linsert $op end $attrv]]
00137 }
00138
00139
00140 ret stringP (type op , type attr , type args) {
00141 set n {}
00142 set map [$self mapself do_attr [linsert $op 0 string] $attr]
00143 foreach result $map node $nodes {
00144 #puts stderr "$self stringP $op $attr -> $result - $node"
00145 if {$result} {
00146 lappend n $node
00147 }
00148 }
00149 set nodes $n
00150 return $args
00151 }
00152
00153
00154 ret stringNP (type op , type attr , type args) {
00155 set n {}
00156 set map [$self mapself do_attr [linsert $op 0 string] $attr]
00157 foreach result $map node $nodes {
00158 if {!$result} {
00159 lappend n $node
00160 }
00161 }
00162 set nodes $n
00163 return $args
00164 }
00165
00166
00167 ret exprP (type op , type attr , type args) {
00168 set n {}
00169 set map [$self mapself do_attr [linsert $op 0 expr] $attr]
00170 foreach result $map node $nodes {
00171 if {$result} {
00172 lappend n $node
00173 }
00174 }
00175 set nodes $n
00176 return $args
00177 }
00178
00179
00180 ret exprNP (type op , type attr , type args) {
00181 set n {}
00182 set map [$self mapself do_attr [linsert $op 0 expr] $attr]
00183 foreach result $map node $nodes {
00184 if {!$result} {
00185 lappend n $node
00186 }
00187 }
00188 set nodes $n
00189 return $args
00190 }
00191
00192
00193 ret do_get (type node , type pattern) {
00194 set result {}
00195 foreach key [$tree keys $node $pattern] {
00196 set result [concat $result [$tree get $node $key]]
00197 }
00198 return $result
00199 }
00200
00201
00202 ret get (type pattern) {
00203 set nodes [$self mapself do_get $pattern]
00204 return {} ;# terminate query
00205 }
00206
00207
00208 ret attlist () {
00209 $self get *
00210 return {} ;# terminate query
00211 }
00212
00213
00214 ret attrs (type glob) {
00215 set nodes [$self apply keys $glob]
00216 return {} ;# terminate query
00217 }
00218
00219
00220
00221 ret do_ancestors (type node) {
00222 set ancestors {}
00223 set rootname [$tree rootname]
00224 while {$node ne $rootname} {
00225 lappend ancestors $node
00226 set node [$tree parent $node]
00227 }
00228 lappend ancestors $rootname
00229 return $ancestors
00230 }
00231
00232
00233 ret ancestors (type args) {
00234 set nodes [$self applyself do_ancestors]
00235 return $args
00236 }
00237
00238
00239
00240 ret do_rootpath (type node) {
00241 set ancestors {}
00242 set rootname [$tree rootname]
00243 while {$node ne $rootname} {
00244 lappend ancestors $node
00245 set node [$tree parent $node]
00246 }
00247 lappend ancestors $rootname
00248 return [::struct::list reverse $ancestors]
00249 }
00250
00251
00252 ret rootpath (type args) {
00253 set nodes [$self applyself do_rootpath]
00254 return $args
00255 }
00256
00257
00258 ret parent (type args) {
00259 set nodes [$self apply parent]
00260 return $args
00261 }
00262
00263
00264 ret children (type args) {
00265 set nodes [$self apply children]
00266 return $args
00267 }
00268
00269
00270 ret left (type args) {
00271 set nodes [$self apply previous]
00272 return $args
00273 }
00274
00275
00276 ret right (type args) {
00277 set nodes [$self apply next]
00278 return $args
00279 }
00280
00281
00282 ret do_previous* (type node) {
00283 if {$node == [$tree rootname]} {
00284 set children $node
00285 } else {
00286 set children [$tree children [$tree parent $node]]
00287 }
00288 set index [expr {[lsearch $children $node] - 1}]
00289 return [lrange $children 0 $index]
00290 }
00291
00292
00293 ret prev (type args) {
00294 set nodes [::struct::list reverse [$self applyself do_previous*]]
00295 return $args
00296 }
00297
00298
00299 ret esib (type args) {
00300 set nodes [$self applyself do_previous*]
00301 return $args
00302 }
00303
00304
00305 ret do_next* (type node) {
00306 if {$node == [$tree rootname]} {
00307 set children $node
00308 } else {
00309 set children [$tree children [$tree parent $node]]
00310 }
00311 set index [expr {[lsearch $children $node] + 1}]
00312 return [lrange $children $index end]
00313 }
00314
00315
00316 ret next (type args) {
00317 set nodes [$self applyself do_next*]
00318 return $args
00319 }
00320
00321
00322 ret root (type args) {
00323 set nodes [$tree rootname]
00324 return $args
00325 }
00326
00327
00328 ret do_subtree (type node) {
00329 set nodeset $node
00330 set children [$tree children $node]
00331 foreach child $children {
00332 foreach d [$self do_subtree $child] {lappend nodeset $d}
00333 }
00334 #puts stderr "do_subtree $node -> $nodeset"
00335 return $nodeset
00336 }
00337
00338
00339 ret descendants (type args) {
00340 set desc {}
00341 set nodeset {}
00342 foreach node $nodes {
00343 foreach d [lrange [$self do_subtree $node] 1 end] {lappend nodeset $d}
00344 }
00345 set nodes $nodeset
00346 return $args
00347 }
00348
00349
00350 ret subtree (type args) {
00351 set nodeset {}
00352 foreach node $nodes {
00353 foreach d [$self do_subtree $node] {lappend nodeset $d}
00354 }
00355 set nodes $nodeset
00356 return $args
00357 }
00358
00359
00360 ret tree (type args) {
00361 set nodes [$self do_subtree [$tree rootname]]
00362 return $args
00363 }
00364
00365
00366
00367
00368
00369
00370
00371
00372 ret forward (type args) {
00373 set nodes [$self applyself do_next*] ;# next siblings
00374 $self descendants ;# their proper descendants
00375 return $args
00376 }
00377
00378
00379 ret later (type args) {
00380 $self forward
00381 return $args
00382 }
00383
00384
00385 ret earlier (type args) {
00386 set nodes [$self applyself do_previous*] ;# all earlier siblings
00387 $self descendants ;# their proper descendants
00388 return $args
00389 }
00390
00391
00392
00393 ret backward (type args) {
00394 set nodes [$self applyself do_previous*] ;# all earlier siblings
00395 $self subtree ;# their subtrees
00396 set nodes [::struct::list reverse $nodes] ;# reverse order
00397 return $args
00398 }
00399
00400
00401 ret nodetype () {
00402 set nodes [$self apply get @type]
00403 return {} ;# terminate query
00404 }
00405
00406
00407 ret oftype (type t , type args) {
00408 return [eval [linsert $args 0 $self stringP [list equal -nocase $t] @type]]
00409 }
00410
00411
00412 ret nottype (type t , type args) {
00413 return [eval [linsert $args 0 $self stringNP [list equal -nocase $t] @type]]
00414 }
00415
00416
00417
00418 ret oftypes (type attrs , type args) {
00419 set n {}
00420 foreach result [$self mapself do_attr list @type] node $nodes {
00421 if {[lsearch $attrs $result] > -1} {
00422 #puts stderr "$self oftypes '$attrs' -> $result - $node"
00423 lappend n $node
00424 }
00425 }
00426 set nodes $n
00427 return $args
00428 }
00429
00430
00431 ret hasatt (type attr , type args) {
00432 set nodes [$self bool keyexists $attr]
00433 return $args
00434 }
00435
00436
00437 ret attval (type attname) {
00438 $self hasatt $attname ;# only nodes with attribute
00439 set nodes [$self apply get $attname] ;# get the attribute nodes
00440 return {} ;# terminate query
00441 }
00442
00443
00444 ret withatt (type attr , type value , type args) {
00445 $self hasatt $attr ;# only nodes with attribute
00446 return [eval [linsert $args 0 $self stringP [list equal -nocase $value] $attr]]
00447 }
00448
00449
00450 ret withatt! (type attr , type val , type args) {
00451 return [eval [linsert $args 0 $self stringP [list equal $val] $attr]]
00452 }
00453
00454
00455 ret attof (type attr , type vals , type args) {
00456
00457 set result {}
00458 foreach node $nodes {
00459 set x [string tolower [[$self treeObj] get $node $attr]]
00460 if {[lsearch $vals $x] != -1} {
00461 lappend result $node
00462 }
00463 }
00464
00465 set nodes $result
00466 return $args
00467 }
00468
00469
00470 ret attmatch (type attr , type match , type args) {
00471 $self stringP [linsert $match 0 match] $attr
00472 return $args
00473 }
00474
00475
00476 ret set (type attr , type val , type args) {
00477 $self apply set $attr $val
00478 return $args
00479 }
00480
00481
00482 ret unset (type attr , type args) {
00483 $self apply unset $attr
00484 return $args
00485 }
00486
00487
00488 ret string (type op , type attr) {
00489 set nodes [$self mapself do_attr [linsert $op 0 string] $attr]
00490 return {} ;# terminate query
00491 }
00492
00493
00494 ret unique (type args) {
00495 set all {}
00496 array set keys {}
00497 foreach node $nodes {
00498 if {![info exists keys($node)]} {
00499 set keys($node) 1
00500 lappend all $node
00501 }
00502 }
00503 set nodes $all
00504 return $args
00505 }
00506
00507
00508 ret and (type and , type args) {
00509 set nodes [::struct::set intersect $and $nodes]
00510 return $args
00511 }
00512
00513
00514 ret subquery (type args) {
00515 set org $nodes ;# save current node set
00516 set new [uplevel 1 [linsert $args 0 $query query]]
00517 set nodes $org ;# restore old node set
00518
00519 return $new
00520 }
00521
00522
00523 ret andq (type q , type args) {
00524 $self and [uplevel 1 [linsert $q 0 $self subquery]]
00525 return $args
00526 }
00527
00528
00529 ret or (type or , type args) {
00530 set nodes [::struct::set union $nodes $or]
00531 $self unique
00532 return $args
00533 }
00534
00535
00536 ret orq (type q , type args) {
00537 $self or [uplevel 1 [linsert $q 0 $self subquery]]
00538 return $args
00539 }
00540
00541
00542 ret not (type not , type args) {
00543 set nodes [::struct::set difference $nodes $not]
00544 return $args
00545 }
00546
00547
00548 ret notq (type q , type args) {
00549 $self not [uplevel 1 [linsert $q 0 $self subquery]]
00550 return $args
00551 }
00552
00553
00554 ret select (type args) {
00555 set nodes [lindex $nodes 0]
00556 return $args
00557 }
00558
00559
00560 ret transform (type q , type var , type body , type args) {
00561 upvar 1 $var iter
00562 set new {}
00563 foreach n [uplevel 1 [linsert $q 0 $self subquery]] {
00564 set iter $n
00565 switch -exact -- [catch {uplevel 1 $body} result] {
00566 0 {
00567 # ok
00568 lappend new $result
00569 }
00570 1 {
00571 # pass errors up
00572 return -code error $result
00573 }
00574 2 {
00575 # return
00576 set nodes $result
00577 return
00578 }
00579 3 {
00580 # break
00581 break
00582 }
00583 4 {
00584 # continue
00585 continue
00586 }
00587 }
00588 }
00589
00590 set nodes $new
00591
00592 return $args
00593 }
00594
00595
00596 ret map (type var , type body , type args) {
00597 upvar 1 $var iter
00598 set new {}
00599 foreach n $nodes {
00600 set iter $n
00601 switch -exact -- [catch {uplevel 1 $body} result] {
00602 0 {
00603 # ok
00604 lappend new $result
00605 }
00606 1 {
00607 # pass errors up
00608 return -code error $result
00609 }
00610 2 {
00611 # return
00612 set nodes $result
00613 return
00614 }
00615 3 {
00616 # break
00617 break
00618 }
00619 4 {
00620 # continue
00621 continue
00622 }
00623 }
00624 }
00625
00626 set nodes $new
00627
00628 return $args
00629 }
00630
00631
00632 ret foreach (type q , type var , type body , type args) {
00633 upvar 1 $var iter
00634 foreach n [uplevel 1 [linsert $q 0 $self subquery]] {
00635 set iter $n
00636 uplevel 1 $body
00637 }
00638 return $args
00639 }
00640
00641
00642 ret with (type q , type body , type args) {
00643 # save current node set, implied reset
00644 set org $nodes; set nodes {}
00645
00646 uplevel 1 [linsert $q 0 $self query]
00647 set result [uplevel 1 $body]
00648
00649 # restore old node set
00650 set new $nodes; set nodes $org
00651
00652 return $args
00653 }
00654
00655
00656 ret over (type var , type body , type args) {
00657 upvar 1 $var iter
00658 set result {}
00659 foreach n $nodes {
00660 set iter $n
00661 uplevel 1 $body
00662 }
00663 return $args
00664 }
00665
00666
00667 ret query (type args) {
00668 # iterate over the args, treating each as a method invocation
00669 while {$args != {}} {
00670 #puts stderr "query $self $args"
00671 set args [uplevel 1 [linsert $args 0 $query]]
00672 #puts stderr "-> $nodes"
00673 }
00674
00675 return $nodes
00676 }
00677
00678
00679 ret quote (type val , type args) {
00680 lappend nodes $val
00681 return $args
00682 }
00683
00684
00685 ret replace (type val , type args) {
00686 set nodes $val
00687 return $args
00688 }
00689
00690
00691 ret reset (type args) {
00692 set nodes {}
00693 return $args
00694 }
00695
00696
00697 ret delete (type args) {
00698
00699 foreach node $nodes {
00700 $tree cut $node
00701 }
00702
00703 set nodes {}
00704 return $args
00705 }
00706
00707
00708 ret result () {
00709 return $nodes
00710 }
00711
00712 constructor {args} {
00713 query = [from args -query ""]
00714 if {$query == ""} {
00715 query = $self
00716 }
00717
00718 nodes = [from args -nodes {}]
00719
00720 tree = [from args -tree ""]
00721
00722 uplevel 1 [linsert $args 0 $self query]
00723 }
00724
00725
00726
00727 ret discard (type args) {
00728 return [K [$self result] [$self destroy]]
00729 }
00730
00731 ret K (type x , type y) {
00732 set x
00733 }
00734 }
00735