#cs(module lazy-xpath mzscheme
(require (lib "string.ss" "srfi/13"))
(require (planet "ssax.ss" ("lizorkin" "ssax.plt" 2 0)))
(require "sxml-tools.ss")
(require "sxpath-ext.ss")
(require "xpath-parser.ss")
(require "txpath.ss")
(require "xpath-ast.ss")
(require "xpath-context_xlink.ss")
(define (lazy:or . args)
(if (null? args) #f (or (car args) (apply lazy:or (cdr args)))))
(cond-expand
(gambit
(define-macro (_gid id)
(string->symbol (string-append "##" (symbol->string id))))
)
(chicken
(define-macro (chk:sys-structure?)
(string->symbol
(string-append (string (integer->char 3)) "sys" "structure?")))
)
(else
#t))
(define lazy:promise?
(cond-expand
(plt promise?)
(bigloo
procedure? )
(chicken
(lambda (p) ((chk:sys-structure?) p 'promise))
)
(gambit
(_gid promise?)
)
(else
(lambda (obj) #f) )))
(define (lazy:null? nodeset)
(cond
((null? nodeset) #t)
((not (null? (filter (lambda (node) (not (lazy:promise? node)))
nodeset)))
#f)
(else (let iter-promises ((nset nodeset))
(cond
((null? nset) #t)
((lazy:null? (as-nodeset (force (car nset))))
(iter-promises (cdr nset)))
(else #f))))))
(define (lazy:map func nodeset)
(cond
((null? nodeset) nodeset)
((lazy:promise? (car nodeset))
(list
(delay
(lazy:map func
(append (as-nodeset (force (car nodeset)))
(cdr nodeset))))))
(else (cons (func (car nodeset))
(lazy:map func (cdr nodeset))))))
(define (lazy:filter func nodeset)
(cond
((null? nodeset) nodeset)
((lazy:promise? (car nodeset))
(list
(delay
(lazy:filter func
(append (as-nodeset (force (car nodeset)))
(cdr nodeset))))))
((func (car nodeset))
(cons (car nodeset)
(lazy:filter func (cdr nodeset))))
(else (lazy:filter func (cdr nodeset)))))
(define (lazy:car nodeset)
(cond
((lazy:promise? (car nodeset))
(let ((nset-car (force (car nodeset))))
(lazy:car
((if (nodeset? nset-car) append cons)
nset-car (cdr nodeset)))))
(else
(car nodeset))))
(define (lazy:cdr nodeset)
(if
(lazy:promise? (car nodeset))
(let ((nset-car (force (car nodeset))))
(lazy:cdr
((if (nodeset? nset-car) append cons)
nset-car (cdr nodeset)))))
(cdr nodeset))
(define (lazy:length nodeset)
(cond
((null? nodeset) 0)
((lazy:promise? (car nodeset))
(let ((nset-car (force (car nodeset))))
(lazy:length
((if (nodeset? nset-car) append cons)
nset-car (cdr nodeset)))))
(else
(+ 1 (lazy:length (cdr nodeset))))))
(define (lazy:result->list nodeset)
(let iter-nset ((nset nodeset)
(res '()))
(cond
((null? nset) (reverse res))
((lazy:promise? (car nset))
(iter-nset (append (as-nodeset (force (car nset))) (cdr nset))
res))
(else (iter-nset (cdr nset)
(cons (car nset) res))))))
(define (lazy:node->sxml node)
(letrec
((force-nodeset
(lambda (nodeset)
(cond
((null? nodeset) nodeset)
((lazy:promise? (car nodeset))
(let ((nset-car (force (car nodeset))))
(force-nodeset
((if (nodeset? nset-car) append cons)
nset-car (cdr nodeset)))))
(else
(cons (lazy:node->sxml (car nodeset))
(force-nodeset (cdr nodeset))))))))
(if
(or (not (pair? node))
(null? ((sxml:descendant lazy:promise?) node)))
node (cons (car node) (force-nodeset (cdr node))))))
(define (lazy:reach-root contextset)
(letrec
((find-root
(lambda (src prev-result)
(let loop ((src src)
(res '())
(prev-result prev-result))
(cond
((null? src) (reverse res))
((lazy:promise? (car src))
(if
(null? res) (loop (append (as-nodeset (force (car src)))
(cdr src))
res prev-result)
(reverse
(cons (delay (find-root src prev-result))
res))))
(else (let ((rt (if (sxml:context? (car src))
(draft:list-last
(sxml:context->ancestors-u (car src)))
(car src))))
(loop (cdr src)
(if
(memq rt prev-result) res (cons rt res))
(cons rt prev-result)))))))))
(find-root contextset '())))
(define (lazy:contextset->nodeset obj)
(letrec
((iter-nset
(lambda (nset)
(cond
((null? nset) nset)
((lazy:promise? (car nset))
(list
(delay (iter-nset (append (as-nodeset (force (car nset)))
(cdr nset))))))
(else (cons
(sxml:context->node (car nset))
(iter-nset (cdr nset))))))))
(if
(nodeset? obj)
(iter-nset obj)
obj)))
(define (lazy:recover-contextset nodeset root-node num-anc)
(cond
((null? nodeset) '())
((lazy:promise? (car nodeset))
(delay (lazy:recover-contextset
(append (as-nodeset (force (car nodeset)))
(cdr nodeset))
root-node num-anc)))
(else (cons
(draft:smart-make-context
(car nodeset)
(((sxml:ancestor (lambda (x) #t)) root-node) (car nodeset))
num-anc)
(lazy:recover-contextset (cdr nodeset) root-node num-anc)))))
(define (lazy:find-proper-context nodeset context-set num-anc)
(let* ((descend (lazy:descendant-or-self sxml:node? num-anc))
(possible-ancestors
(map
cdr (map-union
(lambda (node)
(lazy:result->list (descend node)))
(map-union
sxml:context->ancestors
(lazy:result->list context-set))))))
(let iter-nset ((nodeset nodeset)
(res '())) (cond
((null? nodeset) (reverse res))
((lazy:promise? (car nodeset))
(if (null? res) (iter-nset (append (as-nodeset (force (car nodeset)))
(cdr nodeset))
res)
(reverse
(cons
(delay (iter-nset (append (as-nodeset (force (car nodeset)))
(cdr nodeset))
'()))
res))))
((sxml:context? (car nodeset)) (iter-nset (cdr nodeset)
(cons (car nodeset) res)))
((assq (car nodeset) possible-ancestors)
=> (lambda (ancestors)
(iter-nset (cdr nodeset)
(cons
(draft:make-context
(car ancestors) (cdr ancestors))
res))))
(else (iter-nset (cdr nodeset)
(cons (car nodeset) res)))))))
(define (lazy:output-siblings test-pred? siblings ancestors)
(letrec
((iterate-siblings
(lambda (src)
(let loop ((src src) (res '()))
(cond
((null? src) (reverse res))
((lazy:promise? (car src))
(reverse (cons
(delay
(iterate-siblings
(append (as-nodeset (force (car src))) (cdr src))))
res)))
(else (loop (cdr src)
(if (test-pred? (car src))
(cons
(if (null? ancestors) (car src)
(draft:make-context (car src) ancestors))
res)
res))))))))
(iterate-siblings siblings)))
(define (lazy:find-foll-siblings node nodeset)
(cond
((null? nodeset) '())
((lazy:promise? (car nodeset))
(lazy:find-foll-siblings
node
(append (as-nodeset (force (car nodeset)))
(cdr nodeset))))
((eq? node (car nodeset))
(cdr nodeset))
(else
(lazy:find-foll-siblings node (cdr nodeset)))))
(define (lazy:find-prec-siblings node nodeset)
(let loop ((nodeset nodeset)
(res '()))
(cond
((null? nodeset) '())
((lazy:promise? (car nodeset))
(loop
(append (as-nodeset (force (car nodeset)))
(cdr nodeset))
res))
((eq? node (car nodeset))
res)
(else
(loop (cdr nodeset)
(cons (car nodeset) res))))))
(define (lazy:ancestor test-pred? . num-ancestors)
(let* ((num-anc (if (null? num-ancestors) 0 (car num-ancestors))))
(lambda (node) (if
(sxml:context? node)
(let loop ((ancs-to-view (sxml:context->ancestors-u node))
(res '()))
(cond
((null? ancs-to-view) (reverse res) )
((test-pred? (car ancs-to-view)) (loop
(cdr ancs-to-view)
(cons
(draft:smart-make-context
(car ancs-to-view) (cdr ancs-to-view) num-anc)
res)))
(else (loop (cdr ancs-to-view) res))))
'() ))))
(define (lazy:ancestor-or-self test-pred? . num-ancestors)
(let ((num-anc (if (null? num-ancestors) 0 (car num-ancestors))))
(lambda (node) (cond
((sxml:context? node)
(let loop ((ancs-to-view (sxml:context->content-u node))
(res '()))
(cond
((null? ancs-to-view) (reverse res) )
((test-pred? (car ancs-to-view)) (loop
(cdr ancs-to-view)
(cons
(draft:smart-make-context
(car ancs-to-view) (cdr ancs-to-view) num-anc)
res)))
(else (loop (cdr ancs-to-view) res)))))
((test-pred? node) (list node))
(else
'())))))
(define (lazy:attribute test-pred? . num-ancestors)
(let ((num-anc (if (null? num-ancestors) 0 (car num-ancestors))))
(letrec
((find-attr-node
(lambda (nodeset)
(cond
((null? nodeset) #f)
((lazy:promise? (car nodeset))
(find-attr-node
(append (as-nodeset (force (car nodeset)))
(cdr nodeset))))
(((ntype?? '@) (car nodeset))
(car nodeset))
(else #f)))))
(lambda (node) (cond
((not (pair? node)) '()) ((sxml:context-u? node) (let ((attr-node (find-attr-node (sxml:context->node-u node))))
(if (not attr-node) '()
((lazy:child test-pred? num-anc)
(if (and num-anc (zero? num-anc))
attr-node
(draft:make-context
attr-node (sxml:context->content-u node)))))))
(else (let ((attr-node (find-attr-node node)))
(if (not attr-node) '()
((lazy:child test-pred? num-anc)
(if (and num-anc (zero? num-anc))
attr-node
(draft:make-context attr-node (list node))))))))))))
(define (lazy:child test-pred? . num-ancestors)
(let ((num-anc (if (null? num-ancestors) 0 (car num-ancestors))))
(lambda (node) (cond
((not (pair? node)) '())
((sxml:context-u? node) (let ((this (sxml:context->node-u node)))
(if
(or (not (pair? this))
(memq (car this) '(*PI* *COMMENT* *ENTITY*)))
'() (lazy:output-siblings
test-pred?
(cdr this) (draft:list-head (sxml:context->content-u node) num-anc)))))
((memq (car node) '(*PI* *COMMENT* *ENTITY*))
'())
(else
(lazy:output-siblings
test-pred?
(cdr node) (if (and num-anc (zero? num-anc))
'() (list node))))))))
(define (lazy:descendant test-pred? . num-ancestors)
(let* ((num-anc (if (null? num-ancestors) 0 (car num-ancestors)))
(child (lazy:child sxml:node? num-anc)))
(lambda (node) (let rpt ((res '())
(more (child node)))
(cond
((null? more) (reverse res))
((lazy:promise? (car more)) (reverse
(cons
(delay (rpt '()
(append (as-nodeset (force (car more)))
(cdr more))))
res)))
(else (rpt (if (test-pred? (sxml:context->node (car more)))
(cons (car more) res)
res)
(append (child (car more)) (cdr more)))))))))
(define (lazy:descendant-or-self test-pred? . num-ancestors)
(let* ((num-anc (if (null? num-ancestors) 0 (car num-ancestors)))
(child (lazy:child sxml:node? num-anc)))
(lambda (node) (let rpt ((res '())
(more (list node)))
(cond
((null? more) (reverse res))
((lazy:promise? (car more)) (reverse
(cons
(delay (rpt '()
(append (as-nodeset (force (car more)))
(cdr more))))
res)))
(else (rpt (if (test-pred? (sxml:context->node (car more)))
(cons (car more) res)
res)
(append (child (car more)) (cdr more)))))))))
(define (lazy:following test-pred? . num-ancestors)
(let* ((num-anc (if (null? num-ancestors) 0 (car num-ancestors)))
(descend (lazy:descendant-or-self test-pred? num-anc)))
(lambda (node) (if
(sxml:context? node)
(let loop ((curr-node (sxml:context->node-u node))
(ancs-to-view (sxml:context->ancestors-u node))
(foll-siblings '())
(descendants '())
(res '()))
(cond
((null? descendants) (cond
((null? foll-siblings) (if
(null? ancs-to-view) (reverse res)
(loop (car ancs-to-view)
(cdr ancs-to-view)
(lazy:find-foll-siblings
curr-node
(cdr (car ancs-to-view)))
'()
res)))
((lazy:promise? (car foll-siblings))
(reverse
(cons
(delay
(loop curr-node ancs-to-view
(append (as-nodeset (force (car foll-siblings)))
(cdr foll-siblings))
'() '()))
res)))
(else (loop curr-node ancs-to-view
(cdr foll-siblings)
(descend (draft:smart-make-context
(car foll-siblings)
ancs-to-view num-anc))
res))))
((lazy:promise? (car descendants)) (reverse
(cons
(delay
(loop curr-node ancs-to-view foll-siblings
(append (as-nodeset (force (car descendants)))
(cdr descendants))
'()))
res)))
(else (loop curr-node ancs-to-view foll-siblings
(cdr descendants) (cons (car descendants) res)))))
'() ))))
(define (lazy:following-sibling test-pred? . num-ancestors)
(let ((num-anc (if (null? num-ancestors) 0 (car num-ancestors))))
(lambda (node) (if
(and (sxml:context? node)
(not (null? (sxml:context->ancestors-u node))))
(lazy:output-siblings
test-pred?
(lazy:find-foll-siblings
(sxml:context->node-u node)
(cdr (car (sxml:context->ancestors-u node))))
(draft:list-head
(sxml:context->ancestors-u node) num-anc))
'() ))))
(define (lazy:namespace test-pred? . num-ancestors)
(let ((num-anc (if (null? num-ancestors) 0 (car num-ancestors))))
(lambda (node) (lazy:filter
(lambda (context)
(test-pred? (sxml:context->node context)))
((lazy:sxpath '(@@ *NAMESPACES* *) num-anc) node)))))
(define (lazy:parent test-pred? . num-ancestors)
(let ((num-anc (if (null? num-ancestors) 0 (car num-ancestors))))
(lambda (node) (if
(and (sxml:context? node)
(not (null? (sxml:context->ancestors-u node)))
(test-pred? (car (sxml:context->ancestors-u node))))
(draft:smart-make-context
(car (sxml:context->ancestors-u node))
(cdr (sxml:context->ancestors-u node))
num-anc)
'() ))))
(define (lazy:preceding test-pred? . num-ancestors)
(let* ((num-anc (if (null? num-ancestors) 0 (car num-ancestors)))
(descend (lazy:descendant-or-self test-pred? num-anc)))
(lambda (node) (if
(sxml:context? node)
(let loop ((curr-node (sxml:context->node-u node))
(ancs-to-view (sxml:context->ancestors-u node))
(prec-siblings '())
(descendants '())
(res '()))
(cond
((null? descendants) (cond
((null? prec-siblings) (if
(null? ancs-to-view) (reverse res)
(loop (car ancs-to-view)
(cdr ancs-to-view)
(lazy:find-prec-siblings
curr-node
(cdr (car ancs-to-view)))
descendants res)))
((lazy:promise? (car prec-siblings))
(reverse
(cons
(delay
(loop curr-node ancs-to-view
(append (as-nodeset (force (car prec-siblings)))
(cdr prec-siblings))
descendants '()))
res)))
(else (loop curr-node ancs-to-view
(cdr prec-siblings)
(reverse
(descend (draft:smart-make-context
(car prec-siblings)
ancs-to-view num-anc)))
res))))
((lazy:promise? (car descendants)) (reverse
(cons
(delay
(loop curr-node ancs-to-view prec-siblings
(append (reverse (as-nodeset (force (car descendants))))
(cdr descendants))
'()))
res)))
(else (loop curr-node ancs-to-view prec-siblings
(cdr descendants) (cons (car descendants) res)))))
'() ))))
(define (lazy:preceding-sibling test-pred? . num-ancestors)
(let ((num-anc (if (null? num-ancestors) 0 (car num-ancestors))))
(lambda (node) (if
(and (sxml:context? node)
(not (null? (sxml:context->ancestors-u node))))
(draft:siblings->context-set
((sxml:filter test-pred?)
(lazy:find-prec-siblings
(sxml:context->node-u node)
(cdr (car (sxml:context->ancestors-u node)))))
(draft:list-head
(sxml:context->ancestors-u node) num-anc))
'() ))))
(define (lazy:self test-pred? . num-ancestors)
(let ((num-anc (if (null? num-ancestors) 0 (car num-ancestors))))
(lambda (node) (if (sxml:context? node)
(if (test-pred? (sxml:context->node-u node))
(list (draft:smart-make-context
(sxml:context->node-u node)
(sxml:context->ancestors-u node)
num-anc))
'())
(if (test-pred? node) (list node) '())))))
(define (lazy:axis-consume-nodeset axis)
(letrec
((iterate-nodeset
(lambda (src candidates)
(let loop ((src src)
(candidates candidates)
(res '()))
(cond
((null? candidates) (cond
((null? src) (reverse res))
((lazy:promise? (car src))
(if
(null? res) (let ((src-car (as-nodeset (force (car src)))))
(cond
((null? src-car) (loop (cdr src) candidates res))
((lazy:promise? (car src-car)) (loop (append src-car (cdr src))
candidates
res))
(else (loop (append (cdr src-car) (cdr src))
(axis (car src-car)) res))))
(reverse (cons
(delay (iterate-nodeset src candidates))
res))))
(else (loop (cdr src)
(axis (car src)) res))))
((lazy:promise? (car candidates))
(if
(null? res) (let ((cand-car (as-nodeset (force (car candidates)))))
(cond
((null? cand-car) (loop src (cdr candidates) res))
((lazy:promise? (car cand-car)) (loop src
(append cand-car (cdr candidates))
res))
(else (loop src
(append (cdr cand-car) (cdr candidates))
(list (car cand-car)) ))))
(reverse (cons
(delay (iterate-nodeset src candidates))
res))))
(else (loop src (cdr candidates)
(cons (car candidates) res))))))))
(lambda (nodeset) (cond
((null? nodeset) '())
((and (pair? nodeset) (symbol? (car nodeset))) (axis nodeset))
(else (iterate-nodeset nodeset '()))))))
(define (lazy:string object)
(cond
((string? object) object)
((nodeset? object) (if (lazy:null? object)
""
(lazy:string-value (lazy:car object))))
((number? object)
(if (and (rational? object) (not (integer? object))) (number->string (exact->inexact object))
(number->string object)))
((boolean? object) (if object "true" "false"))
(else "")))
(define (lazy:boolean object)
(cond
((boolean? object) object)
((number? object) (not (= object 0)))
((string? object) (> (string-length object) 0))
((nodeset? object) (not (lazy:null? object)))
(else #f)))
(define (lazy:number obj)
(cond
((number? obj) obj)
((string? obj)
(let ((nmb (call-with-input-string obj read)))
(if (number? nmb)
nmb
0))) ((boolean? obj) (if obj 1 0))
((nodeset? obj) (lazy:number (lazy:string obj)))
(else 0)))
(define (lazy:string-value node)
(cond
((lazy:promise? node)
(let ((value (force node)))
(if (nodeset? value)
(apply string-append
(map lazy:string-value value))
(lazy:string-value value))))
((not (pair? node)) (if (string? node)
node ""))
((lazy:null? (cdr node)) "")
(else
(apply
string-append
(cons ""
(map
lazy:string-value
(let ((frst (lazy:car (cdr node))))
(if
(and (pair? frst) (eq? '@ (car frst))) (lazy:cdr (cdr node))
(cdr node)))))))))
(define (lazy:equality-cmp bool-op number-op string-op)
(lambda (obj1 obj2)
(cond
((and (not (nodeset? obj1)) (not (nodeset? obj2)))
(cond
((boolean? obj1) (bool-op obj1 (sxml:boolean obj2)))
((boolean? obj2) (bool-op (sxml:boolean obj1) obj2))
((number? obj1) (number-op obj1 (sxml:number obj2)))
((number? obj2) (number-op (sxml:number obj1) obj2))
(else (string-op obj1 obj2))))
((and (nodeset? obj1) (nodeset? obj2)) (let first ((str-set1 (lazy:map lazy:string-value obj1))
(str-set2 (lazy:map lazy:string-value obj2)))
(cond
((null? str-set1) #f)
((lazy:promise? (car str-set1)) (first (append (as-nodeset (force (car str-set1)))
(cdr str-set1))
str-set2))
((let second ((elem (car str-set1))
(set2 str-set2))
(cond
((null? set2) #f)
((lazy:promise? (car set2)) (second elem
(append (as-nodeset (force (car set2)))
(cdr set2))))
((string-op elem (car set2)) #t)
(else (second elem (cdr set2))))) #t)
(else
(first (cdr str-set1) str-set2)))))
(else (call-with-values
(lambda ()
(if (nodeset? obj1) (values obj1 obj2) (values obj2 obj1)))
(lambda (nset elem)
(cond
((boolean? elem) (bool-op elem (lazy:boolean nset)))
((number? elem)
(let loop ((nset
(lazy:map
(lambda (node) (lazy:number (lazy:string-value node)))
nset)))
(cond
((null? nset) #f)
((lazy:promise? (car nset)) (loop (append (as-nodeset (force (car nset)))
(cdr nset))))
((number-op elem (car nset)) #t)
(else (loop (cdr nset))))))
((string? elem)
(let loop ((nset (lazy:map lazy:string-value nset)))
(cond
((null? nset) #f)
((lazy:promise? (car nset)) (loop (append (as-nodeset (force (car nset)))
(cdr nset))))
((string-op elem (car nset)) #t)
(else (loop (cdr nset))))))
(else (cerr "Unknown datatype: " elem nl)
#f))))))))
(define lazy:equal? (lazy:equality-cmp eq? = string=?))
(define lazy:not-equal?
(lazy:equality-cmp
(lambda (bool1 bool2) (not (eq? bool1 bool2)))
(lambda (num1 num2) (not (= num1 num2)))
(lambda (str1 str2) (not (string=? str1 str2)))))
(define (lazy:relational-cmp op)
(lambda (obj1 obj2)
(cond
((not (or (nodeset? obj1) (nodeset? obj2))) (op (lazy:number obj1) (lazy:number obj2)))
((boolean? obj1) (op (lazy:number obj1) (lazy:number (lazy:boolean obj2))))
((boolean? obj2) (op (lazy:number (lazy:boolean obj1)) (lazy:number obj2)))
((or (null? obj1) (null? obj2)) #f)
(else (op
(cond
((nodeset? obj1) (let ((nset1 (lazy:map
(lambda (node) (lazy:number (lazy:string-value node)))
obj1)))
(let first ((num1 (car nset1))
(nset1 (cdr nset1)))
(cond
((null? nset1) num1)
((lazy:promise? (car nset1)) (first num1
(apply (as-nodeset (force (car nset1)))
(cdr nset1))))
((op num1 (car nset1)) (first num1 (cdr nset1)))
(else (first (car nset1) (cdr nset1)))))))
((string? obj1) (sxml:number obj1))
(else obj1))
(cond
((nodeset? obj2) (let ((nset2 (lazy:map
(lambda (node) (lazy:number (lazy:string-value node)))
obj2)))
(let second ((num2 (car nset2))
(nset2 (cdr nset2)))
(cond
((null? nset2) num2)
((lazy:promise? (car nset2)) (second num2
(apply (as-nodeset (force (car nset2)))
(cdr nset2))))
((op num2 (car nset2)) (second (car nset2) (cdr nset2)))
(else (second num2 (cdr nset2)))))))
((string? obj2) (sxml:number obj2))
(else obj2)))))))
(define (lazy:core-last num-anc)
(lambda (nodeset position+size var-binding)
(cdr position+size)))
(define (lazy:core-position num-anc)
(lambda (nodeset position+size var-binding)
(car position+size)))
(define (lazy:core-count num-anc arg-func)
(lambda (nodeset position+size var-binding)
(let ((res (arg-func nodeset position+size var-binding)))
(cond
((nodeset? res) (lazy:length res))
(else
(sxml:xpointer-runtime-error
"count() function - an argument is not a nodeset")
0)))))
(define (lazy:core-id num-anc arg-func)
(lambda (nodeset position+size var-binding)
(let* ((root-node (list (lazy:car
(lazy:reach-root nodeset))))
(id-nset ((sxml:child (ntype?? 'id-index))
((sxml:child (ntype?? '@@)) root-node))))
(if
(null? id-nset) '() (let ((res ((sxml:id (cdar id-nset)) (lazy:result->list
(lazy:contextset->nodeset
(arg-func nodeset position+size var-binding))))))
(if (and num-anc (zero? num-anc)) res
(lazy:recover-contextset res root-node num-anc)))))))
(define (lazy:core-local-name num-anc . arg-func) (if (null? arg-func) (lambda (nodeset position+size var-binding)
(let ((nodeset (lazy:contextset->nodeset nodeset)))
(cond
((lazy:null? nodeset) "")
((not (pair? (lazy:car nodeset))) "") (else
(let ((name (symbol->string (car (lazy:car nodeset)))))
(cond
((string-rindex name #\:)
=> (lambda (pos)
(substring name (+ pos 1) (string-length name))))
(else name)))))))
(let ((func (car arg-func)))
(lambda (nodeset position+size var-binding)
(let ((obj
(lazy:contextset->nodeset
(func nodeset position+size var-binding))))
(cond
((null? obj) "") ((not (nodeset? obj))
(sxml:xpointer-runtime-error
"NAME function - an argument is not a nodeset")
"")
((not (pair? (lazy:car obj))) "") (else
(let ((name (symbol->string (car (lazy:car obj)))))
(cond
((string-rindex name #\:)
=> (lambda (pos)
(substring
name (+ pos 1) (string-length name))))
(else name))))))))))
(define (lazy:core-namespace-uri num-anc . arg-func) (if (null? arg-func) (lambda (nodeset position+size var-binding)
(let ((nodeset (lazy:contextset->nodeset nodeset)))
(cond
((lazy:null? nodeset) "")
((not (pair? (lazy:car nodeset))) "") (else
(let ((name (symbol->string (car (lazy:car nodeset)))))
(cond
((string-rindex name #\:)
=> (lambda (pos)
(substring name 0 pos)))
(else "")))))))
(let ((func (car arg-func)))
(lambda (nodeset position+size var-binding)
(let ((obj
(lazy:contextset->nodeset
(func nodeset position+size var-binding))))
(cond
((lazy:null? obj) "") ((not (nodeset? obj))
(sxml:xpointer-runtime-error
"NAME function - an argument is not a nodeset")
"")
((not (pair? (lazy:car obj))) "") (else
(let ((name (symbol->string (car (lazy:car obj)))))
(cond
((string-rindex name #\:)
=> (lambda (pos)
(substring name 0 pos)))
(else ""))))))))))
(define (lazy:core-name num-anc . arg-func) (if (null? arg-func) (lambda (nodeset position+size var-binding)
(let ((nodeset (lazy:contextset->nodeset nodeset)))
(cond
((lazy:null? nodeset) "")
((not (pair? (lazy:car nodeset))) "") (else
(symbol->string (car (lazy:car nodeset)))))))
(let ((func (car arg-func)))
(lambda (nodeset position+size var-binding)
(let ((obj
(lazy:contextset->nodeset
(func nodeset position+size var-binding))))
(cond
((lazy:null? obj) "") ((not (nodeset? obj))
(sxml:xpointer-runtime-error
"NAME function - an argument is not a nodeset")
"")
((not (pair? (lazy:car obj))) "") (else
(symbol->string (car (lazy:car obj))))))))))
(define (lazy:core-string num-anc . arg-func) (if (null? arg-func) (lambda (nodeset position+size var-binding)
(lazy:string
(lazy:contextset->nodeset nodeset)))
(let ((func (car arg-func)))
(lambda (nodeset position+size var-binding)
(lazy:string
(lazy:contextset->nodeset
(func nodeset position+size var-binding)))))))
(define (lazy:core-concat num-anc . arg-func-lst)
(lambda (nodeset position+size var-binding)
(apply
string-append
(map
(lambda (f)
(lazy:string
(lazy:contextset->nodeset
(f nodeset position+size var-binding))))
arg-func-lst))))
(define (lazy:core-starts-with num-anc arg-func1 arg-func2)
(lambda (nodeset position+size var-binding)
(let ((str1 (lazy:string
(lazy:contextset->nodeset
(arg-func1 nodeset position+size var-binding))))
(str2 (lazy:string
(lazy:contextset->nodeset
(arg-func2 nodeset position+size var-binding)))))
(string-prefix? str2 str1))))
(define (lazy:core-contains num-anc arg-func1 arg-func2)
(lambda (nodeset position+size var-binding)
(let ((str1 (lazy:string
(lazy:contextset->nodeset
(arg-func1 nodeset position+size var-binding))))
(str2 (lazy:string
(lazy:contextset->nodeset
(arg-func2 nodeset position+size var-binding)))))
(if (substring? str2 str1) #t #f) )))
(define (lazy:core-substring-before num-anc arg-func1 arg-func2)
(lambda (nodeset position+size var-binding)
(let* ((str1 (lazy:string
(lazy:contextset->nodeset
(arg-func1 nodeset position+size var-binding))))
(str2 (lazy:string
(lazy:contextset->nodeset
(arg-func2 nodeset position+size var-binding))))
(pos (substring? str2 str1)))
(if (not pos) ""
(substring str1 0 pos)))))
(define (lazy:core-substring-after num-anc arg-func1 arg-func2)
(lambda (nodeset position+size var-binding)
(let* ((str1 (lazy:string
(lazy:contextset->nodeset
(arg-func1 nodeset position+size var-binding))))
(str2 (lazy:string
(lazy:contextset->nodeset
(arg-func2 nodeset position+size var-binding))))
(pos (substring? str2 str1)))
(if
(not pos) ""
(substring
str1 (+ pos (string-length str2)) (string-length str1))))))
(define (lazy:core-substring num-anc arg-func1 arg-func2 . arg-func3)
(if (null? arg-func3) (lambda (nodeset position+size var-binding)
(let ((str (lazy:string
(lazy:contextset->nodeset
(arg-func1 nodeset position+size var-binding))))
(num1 (lazy:number
(lazy:contextset->nodeset
(arg-func2 nodeset position+size var-binding)))))
(let ((len (string-length str))
(start (- (inexact->exact (round num1)) 1)))
(if (> start len)
""
(substring str (if (< start 0) 0 start) len)))))
(let ((arg-func3 (car arg-func3)))
(lambda (nodeset position+size var-binding)
(let ((str (lazy:string
(lazy:contextset->nodeset
(arg-func1 nodeset position+size var-binding))))
(num1 (lazy:number
(lazy:contextset->nodeset
(arg-func2 nodeset position+size var-binding))))
(num2 (lazy:number
(lazy:contextset->nodeset
(arg-func3 nodeset position+size var-binding)))))
(let* ((len (string-length str))
(start (- (inexact->exact (round num1)) 1))
(fin (+ start (inexact->exact (round num2)))))
(if (or (> start len) (< fin 0) (< fin start))
""
(substring str
(if (< start 0) 0 start)
(if (> fin len) len fin)))))))))
(define (lazy:core-string-length num-anc . arg-func) (if (null? arg-func) (lambda (nodeset position+size var-binding)
(string-length
(lazy:string (lazy:contextset->nodeset nodeset))))
(let ((func (car arg-func)))
(lambda (nodeset position+size var-binding)
(string-length
(lazy:string
(lazy:contextset->nodeset
(func nodeset position+size var-binding))))))))
(define (lazy:core-normalize-space num-anc . arg-func) (if (null? arg-func) (lambda (nodeset position+size var-binding)
(let rpt ((src (string-split
(lazy:string (lazy:contextset->nodeset nodeset))
sxml:whitespace))
(res '()))
(cond
((null? src)
(apply string-append (reverse res)))
((= (string-length (car src)) 0) (rpt (cdr src) res))
((null? res)
(rpt (cdr src) (cons (car src) res)))
(else
(rpt (cdr src) (cons (car src) (cons " " res)))))))
(let ((func (car arg-func)))
(lambda (nodeset position+size var-binding)
(let rpt ((src (string-split
(lazy:string
(lazy:contextset->nodeset
(func nodeset position+size var-binding)))
sxml:whitespace))
(res '()))
(cond
((null? src)
(apply string-append (reverse res)))
((= (string-length (car src)) 0) (rpt (cdr src) res))
((null? res)
(rpt (cdr src) (cons (car src) res)))
(else
(rpt (cdr src) (cons (car src) (cons " " res))))))))))
(define (lazy:core-translate num-anc arg-func1 arg-func2 arg-func3)
(lambda (nodeset position+size var-binding)
(let ((str1 (lazy:string
(lazy:contextset->nodeset
(arg-func1 nodeset position+size var-binding))))
(str2 (lazy:string
(lazy:contextset->nodeset
(arg-func2 nodeset position+size var-binding))))
(str3 (lazy:string
(lazy:contextset->nodeset
(arg-func3 nodeset position+size var-binding)))))
(let ((alist
(let while ((lst2 (string->list str2))
(lst3 (string->list str3))
(alist '()))
(cond
((null? lst2) (reverse alist))
((null? lst3)
(append
(reverse alist)
(map
(lambda (ch) (cons ch #f))
lst2)))
(else
(while
(cdr lst2)
(cdr lst3)
(cons (cons (car lst2) (car lst3)) alist)))))))
(let rpt ((lst1 (string->list str1))
(res '()))
(cond
((null? lst1) (list->string (reverse res)))
((assoc (car lst1) alist)
=> (lambda (pair)
(if (cdr pair)
(rpt (cdr lst1) (cons (cdr pair) res))
(rpt (cdr lst1) res))))
(else
(rpt (cdr lst1) (cons (car lst1) res)))))))))
(define (lazy:core-boolean num-anc arg-func)
(lambda (nodeset position+size var-binding)
(lazy:boolean
(arg-func nodeset position+size var-binding))))
(define (lazy:core-not num-anc arg-func)
(lambda (nodeset position+size var-binding)
(not (lazy:boolean
(arg-func nodeset position+size var-binding)))))
(define (lazy:core-true num-anc)
(lambda (nodeset position+size var-binding) #t))
(define (lazy:core-false num-anc)
(lambda (nodeset position+size var-binding) #f))
(define (lazy:core-lang num-anc arg-func)
(lambda (nodeset position+size var-binding)
(let ((arg (lazy:string
(lazy:contextset->nodeset
(arg-func nodeset position+size var-binding))))
(lng
((lazy:child (ntype?? '*text*))
((lazy:attribute (ntype?? 'xml:lang))
((lazy:ancestor-or-self (lambda (x) #t))
(lazy:car nodeset) )))))
(and (not (null? lng))
(or (string-ci=? arg (lazy:car lng))
(string-prefix-ci? (string-append arg "-") (lazy:car lng)))))))
(define (lazy:core-number num-anc . arg-func) (if (null? arg-func) (lambda (nodeset position+size var-binding)
(lazy:number (lazy:contextset->nodeset nodeset)))
(let ((func (car arg-func)))
(lambda (nodeset position+size var-binding)
(lazy:number
(lazy:contextset->nodeset
(func nodeset position+size var-binding)))))))
(define (lazy:core-sum num-anc arg-func)
(lambda (nodeset position+size var-binding)
(let ((res (arg-func nodeset position+size var-binding)))
(cond
((nodeset? res)
(apply +
(map
(lambda (node)
(lazy:number
(lazy:string-value (sxml:context->node node))))
(lazy:result->list res))))
(else
(sxml:xpointer-runtime-error
"SUM function - an argument is not a nodeset")
0)))))
(define (lazy:core-floor num-anc arg-func)
(lambda (nodeset position+size var-binding)
(inexact->exact
(floor (lazy:number
(lazy:contextset->nodeset
(arg-func nodeset position+size var-binding)))))))
(define (lazy:core-ceiling num-anc arg-func)
(lambda (nodeset position+size var-binding)
(inexact->exact
(ceiling (lazy:number
(lazy:contextset->nodeset
(arg-func nodeset position+size var-binding)))))))
(define (lazy:core-round num-anc arg-func)
(lambda (nodeset position+size var-binding)
(inexact->exact
(round (lazy:number
(lazy:contextset->nodeset
(arg-func nodeset position+size var-binding)))))))
(define (lazy:ast-axis-specifier op num-anc)
(if
(not (eq? (car op) 'axis-specifier))
(draft:signal-semantic-error "not an AxisSpecifier - " op)
(case (caadr op) ((ancestor)
(cons lazy:ancestor #f))
((ancestor-or-self)
(cons lazy:ancestor-or-self #f))
((attribute)
(cons lazy:attribute (draft:na-minus-nneg num-anc 1)))
((child)
(cons lazy:child (draft:na-minus-nneg num-anc 1)))
((descendant)
(cons lazy:descendant (draft:na-minus-nneg num-anc 1)))
((descendant-or-self)
(cons lazy:descendant-or-self num-anc))
((following)
(cons lazy:following #f))
((following-sibling)
(cons lazy:following-sibling (draft:na-max num-anc 1)))
((namespace)
(cons lazy:namespace (draft:na-minus-nneg num-anc 1)))
((parent)
(cons lazy:parent (draft:na+ num-anc 1)))
((preceding)
(cons lazy:preceding #f))
((preceding-sibling)
(cons lazy:preceding-sibling (draft:na-max num-anc 1)))
((self)
(cons lazy:self num-anc))
(else
(draft:signal-semantic-error "unknown AxisName - " op)))))
(define (lazy:ast-location-path op num-anc)
(case (car op)
((absolute-location-path)
(lazy:ast-absolute-location-path op num-anc))
((relative-location-path)
(lazy:ast-relative-location-path op num-anc))
(else
(draft:signal-semantic-error "improper LocationPath - " op))))
(define (lazy:ast-absolute-location-path op num-anc)
(cond
((not (eq? (car op) 'absolute-location-path))
(draft:signal-semantic-error "not an AbsoluteLocationPath - " op))
((null? (cdr op)) (list
(lambda (nodeset position+size var-binding)
(lazy:reach-root nodeset))
#f #f ))
(else
(and-let*
((steps-res (lazy:ast-step-list (cdr op) num-anc)))
(list
(if
(null? (cdar steps-res)) (let ((step-impl (caar steps-res)))
(lambda (nodeset position+size var-binding)
(step-impl
(lazy:reach-root nodeset) position+size var-binding)))
(let ((converters (car steps-res)))
(lambda (nodeset position+size var-binding)
(let rpt ((nset (lazy:reach-root nodeset))
(fs converters))
(if (null? fs)
nset
(rpt ((car fs) nset position+size var-binding)
(cdr fs)))))))
#f #f )))))
(define (lazy:ast-relative-location-path op num-anc)
(if
(not (eq? (car op) 'relative-location-path))
(draft:signal-semantic-error "not a RelativeLocationPath - " op)
(and-let*
((steps-res (lazy:ast-step-list (cdr op) num-anc)))
(list
(if
(null? (cdar steps-res)) (caar steps-res)
(let ((converters (car steps-res)))
(lambda (nodeset position+size var-binding)
(let rpt ((nset nodeset)
(fs converters))
(if (null? fs)
nset
(rpt ((car fs) nset position+size var-binding)
(cdr fs)))))))
(cadr steps-res) #f ))))
(define (lazy:ast-step op num-anc)
(cond
((eq? (car op) 'range-to)
(draft:signal-semantic-error "range-to function not implemented"))
((eq? (car op) 'filter-expr)
(lazy:ast-filter-expr op num-anc))
((eq? (car op) 'lambda-step) (let ((proc (cadr op)))
(list
(if
(and num-anc (zero? num-anc)) (lambda (nodeset position+size var-binding)
(proc (lazy:contextset->nodeset (as-nodeset nodeset))
var-binding))
(lambda (nodeset position+size var-binding)
(lazy:find-proper-context
(proc (lazy:contextset->nodeset (as-nodeset nodeset))
var-binding)
(as-nodeset nodeset)
num-anc)))
num-anc #f )))
((eq? (car op) 'step)
(if
(null? (cdddr op)) (and-let*
((axis-lst (lazy:ast-axis-specifier (cadr op) num-anc))
(ntest (draft:ast-node-test (caddr op))))
(let ((axis
(lazy:axis-consume-nodeset
((car axis-lst) ntest num-anc))))
(list
(lambda (nodeset position+size var-binding)
(axis nodeset))
(cdr axis-lst) #f )))
(and-let*
((preds-res (lazy:ast-predicate-list (cdddr op) 0))
(axis-lst (lazy:ast-axis-specifier
(cadr op) (draft:na-max num-anc (cadr preds-res))))
(ntest (draft:ast-node-test (caddr op))))
(let ((axis ((car axis-lst)
ntest (draft:na-max num-anc (cadr preds-res))))
(pred-impl-lst (car preds-res)))
(list
(lambda (nodeset position+size var-binding)
(let iter-src ((src nodeset)
(candidates '())
(res '()))
(cond
((null? candidates) (cond
((null? src) (reverse res))
((lazy:promise? (car src))
(if
(null? res) (iter-src (append (as-nodeset (force (car src)))
(cdr src))
candidates
res)
(reverse (cons
(delay (iter-src src candidates '()))
res))))
(else (iter-src
(cdr src)
(let iter-preds ((nset (axis (car src)))
(preds pred-impl-lst))
(if
(null? preds)
nset
(iter-preds
((car preds) nset position+size var-binding)
(cdr preds))))
res))))
((lazy:promise? (car candidates))
(if
(null? res) (iter-src src
(append (as-nodeset (force (car candidates)))
(cdr candidates))
res)
(reverse (cons
(delay (iter-src src candidates '()))
res))))
(else (iter-src src (cdr candidates)
(cons (car candidates) res))))))
(cdr axis-lst) #f )))))
(else
(draft:signal-semantic-error "not a Step - " op))))
(define (lazy:ast-step-list step-lst num-anc)
(let loop ((steps-to-view (reverse step-lst))
(res-lst '())
(num-anc num-anc))
(if
(null? steps-to-view) (list res-lst num-anc)
(and-let*
((step-res (lazy:ast-step (car steps-to-view) num-anc)))
(loop
(cdr steps-to-view)
(cons (car step-res) res-lst)
(cadr step-res))))))
(define (lazy:ast-predicate op num-anc)
(if
(not (eq? (car op) 'predicate))
(draft:signal-semantic-error "not an Predicate - " op)
(and-let*
((expr-res (lazy:ast-expr (cadr op) 0)))
(let ((pred (car expr-res)))
(list
(if
(caddr expr-res) (lambda (nodeset position+size var-binding)
(if
(null? nodeset) nodeset (let ((size (lazy:length nodeset)))
(let loop ((nset nodeset)
(res '())
(pos 1))
(cond
((null? nset)
(reverse res))
((lazy:promise? (car nset))
(loop (append (as-nodeset (force (car nset)))
(cdr nset))
res pos))
(else (let ((value (pred (list (car nset))
(cons pos size)
var-binding)))
(loop (cdr nset)
(if (if (number? value)
(= value pos)
(lazy:boolean value))
(cons (car nset) res)
res)
(+ pos 1)))))))))
(lambda (nodeset position+size var-binding)
(if
(null? nodeset) nodeset (let loop ((nset nodeset)
(res '())
(pos 1))
(cond
((null? nset)
(reverse res))
((lazy:promise? (car nset))
(reverse
(cons
(delay (loop
(append (as-nodeset (force (car nset)))
(cdr nset))
'() pos))
res)))
(else (let ((value (pred (list (car nset))
(cons pos 1) var-binding)))
(loop (cdr nset)
(if (if (number? value)
(= value pos)
(lazy:boolean value))
(cons (car nset) res)
res)
(+ pos 1)))))))))
(cadr expr-res) (caddr expr-res) )))))
(define (lazy:ast-predicate-list op-lst num-anc)
(let ((pred-res-lst
(map
(lambda (op) (lazy:ast-predicate op 0))
op-lst)))
(if
(member #f pred-res-lst) #f
(list
(map car pred-res-lst)
(apply draft:na-max (map cadr pred-res-lst))))))
(define (lazy:ast-expr op num-anc)
(case (car op)
((or)
(lazy:ast-or-expr op num-anc))
((and)
(lazy:ast-and-expr op num-anc))
((= !=)
(lazy:ast-equality-expr op num-anc))
((< > <= >=)
(lazy:ast-relational-expr op num-anc))
((+ -)
(lazy:ast-additive-expr op num-anc))
((* div mod)
(lazy:ast-multiplicative-expr op num-anc))
((union-expr)
(lazy:ast-union-expr op num-anc))
((path-expr)
(lazy:ast-path-expr op num-anc))
((filter-expr)
(lazy:ast-filter-expr op num-anc))
((variable-reference)
(lazy:ast-variable-reference op num-anc))
((literal)
(lazy:ast-literal op num-anc))
((number)
(lazy:ast-number op num-anc))
((function-call)
(lazy:ast-function-call op num-anc))
((absolute-location-path)
(lazy:ast-absolute-location-path op num-anc))
((relative-location-path)
(lazy:ast-relative-location-path op num-anc))
(else
(draft:signal-semantic-error "unknown Expr - " op))))
(define (lazy:ast-or-expr op num-anc)
(let ((expr-res-lst
(map
(lambda (expr) (lazy:ast-expr expr 0))
(cdr op))))
(if
(member #f expr-res-lst) #f
(let ((expr-impls (map car expr-res-lst)))
(list
(lambda (nodeset position+size var-binding)
(let rpt ((fs expr-impls))
(cond
((null? fs) #f)
((lazy:boolean ((car fs) nodeset position+size var-binding)) #t)
(else (rpt (cdr fs))))))
(apply draft:na-max (map cadr expr-res-lst)) (apply lazy:or (map caddr expr-res-lst)) )))))
(define (lazy:ast-and-expr op num-anc)
(let ((expr-res-lst
(map
(lambda (expr) (lazy:ast-expr expr 0))
(cdr op))))
(if
(member #f expr-res-lst) #f
(let ((expr-impls (map car expr-res-lst)))
(list
(lambda (nodeset position+size var-binding)
(let rpt ((fs expr-impls))
(cond
((null? fs) #t)
((not
(lazy:boolean ((car fs) nodeset position+size var-binding)))
#f)
(else (rpt (cdr fs))))))
(apply draft:na-max (map cadr expr-res-lst)) (apply lazy:or (map caddr expr-res-lst)) )))))
(define (lazy:ast-equality-expr op num-anc)
(and-let*
((left-lst (lazy:ast-expr (cadr op) 0))
(right-lst (lazy:ast-expr (caddr op) 0)))
(let ((cmp-op (cadr (assq (car op) `((= ,lazy:equal?)
(!= ,lazy:not-equal?)))))
(left (car left-lst))
(right (car right-lst)))
(list
(lambda (nodeset position+size var-binding)
(cmp-op
(lazy:contextset->nodeset
(left nodeset position+size var-binding))
(lazy:contextset->nodeset
(right nodeset position+size var-binding))))
(draft:na-max (cadr left-lst) (cadr right-lst)) (or (caddr left-lst) (caddr right-lst)) ))))
(define (lazy:ast-relational-expr op num-anc)
(and-let*
((left-lst (lazy:ast-expr (cadr op) 0))
(right-lst (lazy:ast-expr (caddr op) 0)))
(let ((cmp-op
(lazy:relational-cmp
(cadr (assq (car op) `((< ,<) (> ,>) (<= ,<=) (>= ,>=))))))
(left (car left-lst))
(right (car right-lst)))
(list
(lambda (nodeset position+size var-binding)
(cmp-op
(lazy:contextset->nodeset
(left nodeset position+size var-binding))
(lazy:contextset->nodeset
(right nodeset position+size var-binding))))
(draft:na-max (cadr left-lst) (cadr right-lst)) (or (caddr left-lst) (caddr right-lst)) ))))
(define (lazy:ast-additive-expr op num-anc)
(let ((expr-res-lst
(map
(lambda (expr) (lazy:ast-expr expr 0))
(cdr op))))
(if
(member #f expr-res-lst) #f
(let ((add-op (cadr (assq (car op) `((+ ,+) (- ,-)))))
(expr-impls (map car expr-res-lst)))
(list
(lambda (nodeset position+size var-binding)
(apply
add-op
(map
(lambda (expr)
(lazy:number
(lazy:contextset->nodeset
(expr nodeset position+size var-binding))))
expr-impls)))
(apply draft:na-max (map cadr expr-res-lst)) (apply lazy:or (map caddr expr-res-lst)) )))))
(define (lazy:ast-multiplicative-expr op num-anc)
(and-let*
((left-lst (lazy:ast-expr (cadr op) 0))
(right-lst (lazy:ast-expr (caddr op) 0)))
(let ((mul-op
(cadr (assq (car op) `((* ,*) (div ,/) (mod ,remainder)))))
(left (car left-lst))
(right (car right-lst)))
(list
(lambda (nodeset position+size var-binding)
(mul-op
(lazy:number
(lazy:contextset->nodeset
(left nodeset position+size var-binding)))
(lazy:number
(lazy:contextset->nodeset
(right nodeset position+size var-binding)))))
(draft:na-max (cadr left-lst) (cadr right-lst)) (or (caddr left-lst) (caddr right-lst)) ))))
(define (lazy:ast-union-expr op num-anc)
(let ((expr-res-lst
(map
(lambda (expr) (lazy:ast-expr expr 0))
(cdr op))))
(if
(member #f expr-res-lst) #f
(let ((expr-impls (map car expr-res-lst)))
(list
(lambda (nodeset position+size var-binding)
(let iter-operands ((fs expr-impls)
(candidates '())
(res '()))
(cond
((null? candidates)
(if
(null? fs) (reverse res)
(iter-operands
(cdr fs)
(let ((nset ((car fs) nodeset position+size var-binding)))
(cond
((not (nodeset? nset))
(sxml:xpointer-runtime-error
"expected - nodeset instead of " nset)
'())
(else nset)))
res)))
((lazy:promise? (car candidates))
(if
(null? res) (iter-operands
fs
(append (as-nodeset (force (car candidates)))
(cdr candidates))
res)
(reverse
(cons
(delay (iter-operands
fs
(append (as-nodeset (force (car candidates)))
(cdr candidates))
'()))
res))))
(else (iter-operands
fs (cdr candidates) (cons (car candidates) res))))))
(apply draft:na-max (map cadr expr-res-lst))
(apply lazy:or (map caddr expr-res-lst)) )))))
(define (lazy:ast-path-expr op num-anc)
(and-let*
((steps-res (lazy:ast-step-list (cddr op) num-anc))
(filter-lst (lazy:ast-filter-expr (cadr op) (cadr steps-res))))
(let ((init-impl (car filter-lst))
(converters (car steps-res)))
(list
(lambda (nodeset position+size var-binding)
(let ((nset
(init-impl nodeset position+size var-binding)))
(let rpt ((nset
(cond
((nodeset? nset) nset)
(else
(sxml:xpointer-runtime-error
"expected - nodeset instead of " nset)
'())))
(fs converters))
(if (null? fs)
nset
(rpt ((car fs) nset position+size var-binding)
(cdr fs))))))
(cadr filter-lst) (caddr filter-lst) ))))
(define (lazy:ast-filter-expr op num-anc)
(cond
((not (eq? (car op) 'filter-expr))
(draft:signal-semantic-error "not an FilterExpr - " op))
((not (eq? (caadr op) 'primary-expr))
(draft:signal-semantic-error "not an PrimaryExpr - " (cadr op)))
((null? (cddr op)) (lazy:ast-expr (cadadr op) num-anc))
(else (and-let*
((preds-res (lazy:ast-predicate-list (cddr op) 0))
(expr-lst (lazy:ast-expr
(cadadr op) (draft:na-max num-anc (cadr preds-res)))))
(let ((expr-impl (car expr-lst))
(pred-impl-lst (car preds-res)))
(list
(lambda (nodeset position+size var-binding)
(let ((prim-res (expr-impl nodeset position+size var-binding)))
(let iter-preds ((nset
(if
(nodeset? prim-res)
prim-res
(begin
(sxml:xpointer-runtime-error
"expected - nodeset instead of " prim-res)
'())))
(preds pred-impl-lst))
(if
(null? preds)
nset
(iter-preds
((car preds) nset position+size var-binding)
(cdr preds))))))
(cadr expr-lst) #f ))))))
(define (lazy:ast-variable-reference op num-anc)
(let ((name (string->symbol (cadr op))))
(list
(lambda (nodeset position+size var-binding)
(cond
((assoc name var-binding)
=> cdr)
(else
(sxml:xpointer-runtime-error "unbound variable - " name)
'())))
0 #f )))
(define (lazy:ast-literal op num-anc)
(let ((literal (cadr op)))
(list
(lambda (nodeset position+size var-binding) literal)
0 #f)))
(define (lazy:ast-number op num-anc)
(let ((number (cadr op)))
(list
(lambda (nodeset position+size var-binding) number)
0 #f)))
(define (lazy:ast-function-call op num-anc)
(let ((core-alist
`((last 0 0 0 ,lazy:core-last #t)
(position 0 0 0 ,lazy:core-position #f)
(count 1 1 0 ,lazy:core-count #f)
(id 1 1 #f ,lazy:core-id #f)
(local-name 0 1 0 ,lazy:core-local-name #f)
(namespace-uri 0 1 0 ,lazy:core-namespace-uri #f)
(name 0 1 0 ,lazy:core-name #f)
(string 0 1 0 ,lazy:core-string #f)
(concat 2 -1 0 ,lazy:core-concat #f)
(starts-with 2 2 0 ,lazy:core-starts-with #f)
(contains 2 2 0 ,lazy:core-contains #f)
(substring-before 2 2 0 ,lazy:core-substring-before #f)
(substring-after 2 2 0 ,lazy:core-substring-after #f)
(substring 2 3 0 ,lazy:core-substring #f)
(string-length 0 1 0 ,lazy:core-string-length #f)
(normalize-space 0 1 0 ,lazy:core-normalize-space #f)
(translate 3 3 0 ,lazy:core-translate #f)
(boolean 1 1 0 ,lazy:core-boolean #f)
(not 1 1 0 ,lazy:core-not #f)
(true 0 0 0 ,lazy:core-true #f)
(false 0 0 0 ,lazy:core-false #f)
(lang 1 1 #f ,lazy:core-lang #f)
(number 0 1 0 ,lazy:core-number #f)
(sum 1 1 0 ,lazy:core-sum #f)
(floor 1 1 0 ,lazy:core-floor #f)
(ceiling 1 1 0 ,lazy:core-ceiling #f)
(round 1 1 0 ,lazy:core-round #f))))
(cond
((not (eq? (caadr op) 'function-name))
(draft:signal-semantic-error "not an FunctionName - " (cadr op)))
((assq (string->symbol (cadadr op)) core-alist)
=> (lambda (description) (cond
((< (length (cddr op)) (cadr description))
(draft:signal-semantic-error
"too few arguments for the Core Function call - "
(cadadr op)))
((and (>= (caddr description) 0)
(> (length (cddr op)) (caddr description)))
(draft:signal-semantic-error
"too many arguments for the Core Function call - "
(cadadr op)))
(else (and-let*
((args-impl (lazy:ast-function-arguments (cddr op))))
(list
(apply (list-ref description 4) num-anc args-impl)
(list-ref description 3)
(list-ref description 5) ))))))
(else (draft:signal-semantic-error
"function call to an unknown function - " (cadadr op))))))
(define (lazy:ast-function-arguments op-lst)
(let ((arg-res-lst
(map
(lambda (op)
(if
(not (eq? (car op) 'argument))
(draft:signal-semantic-error "not an Argument - " op)
(lazy:ast-expr (cadr op) 0)))
op-lst)))
(if
(member #f arg-res-lst) #f
(map car arg-res-lst))))
(define (lazy:api-helper grammar-parser ast-parser)
(lambda (xpath-string . ns+na)
(call-with-values
(lambda () (draft:arglist->ns+na ns+na))
(lambda (ns-binding num-anc)
(and-let*
((ast (grammar-parser xpath-string ns-binding))
(impl-lst (ast-parser ast num-anc)))
(let ((query-impl (car impl-lst)))
(lambda (node . var-binding)
(let ((query-res
(query-impl
(as-nodeset node) (cons 1 1)
(if (null? var-binding) var-binding (car var-binding)))))
(if
(and num-anc (zero? num-anc) (nodeset? query-res))
(lazy:map sxml:context->node query-res)
query-res)))))))))
(define lazy:txpath (lazy:api-helper txp:xpath->ast lazy:ast-location-path))
(define lazy:xpath-expr (lazy:api-helper txp:expr->ast lazy:ast-expr))
(define lazy:sxpath (lazy:api-helper txp:sxpath->ast lazy:ast-expr))
(provide (all-defined)))