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