Re: [ssax-sxml] SXPath: high-level API modernization
Brought to you by:
oleg
From: David A. <da...@al...> - 2003-07-29 16:05:21
|
On Thu, Jul 24, 2003 at 04:25:32PM -0400, Kirill Lisovsky wrote: [...] > In accordance to XPath recommendation, the variable bindings consist of a > mapping from variable names to variable values. Current SXPath represents it as > a list of (key . value) pairs and convey it (and root) as additional parameters > for every location step function. > That is location step functions are > nodeset root var-bindings -> nodeset > procedures > [...] > > Just to avoid a possible name clash, we can use some non-XPath names for > non-XPath variables, like @root and so on. > > Placing extensively-used variables (like @root) at the beginning > of this list may be used to speed-up the look-up, but it is optional. I am not sure this contribution is going to be relevant, but I had a similar issue in my work. That is handling dynamic environment in performant and referentially-transparent way. It is "safer" performance-wise to use hash-tables (actually texmacs adaptative hash-tables) for variable look-up, but it may be preferrable in some context to use alists, or trees, to provide true referential transparence (thread safety). My contribution allows to separate this policy from the code using it. The useful public declarations are "environment", "environment-ref*" and "with-environment*". The macros "environment-ref" and "with-environment" are syntactic sugar. The SXPath part is some specialized functions I used to allow access to the parent node while traversing a tree. Examples of usage (from TeXmacs html import filter) are: ;; Initialization of environment (define (htmltm-as-serial root) (define (sub env) (htmltm-serial (htmltm-preserve-space? env) (htmltm env root))) (initialize-xpath (environment) root (cut initialize-htmltm <> sub))) ;; Descending the tree (define (htmltm-args env l) ;; Convert the content list of an HTML element. (append-map (lambda (x) (xpath-descend env x (cut htmltm <> x))) l)) ;; Accessing the environment (define (htmltm-br env a c) (if (sxhtml-list? (xpath-parent env)) '() '((format "next line")))) Here comes the library code. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Converter environments ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Environments are used by converters to accumulate dynamic state. ;; ;; By policy, an environment can only be mutated inside a bounded dynamic scope ;; (i.e. environment-set! must stay private). ;; ;; The intended semantics of environment is "functional operations on ;; hash-tables". However, for simplicity and efficiency a dynamic scoping ;; implementation is used. ;; ;; WARNING: environments are NOT continuation-correct. A continuation which ;; alters an environment is only garanteed to evaluate correctly _once_. ;; ;; WARNING: with-environment* does not restore the environment when it is ;; exited by stack unwinding (when an exception occurs). ;; ;; NOTE: a pure functional solution could be implemented using alists. If the ;; corner-case semantics of the hash-table based solution become problematic, ;; that should be the next thing to try. Since the list is not expected to grow ;; longer than a few dozen items, list lookup should not be a big problem. ;; Though a useful optimization may be adaptative ordering based on access ;; count. ;; Environment primitives (define (environment) (make-ahash-table)) (define-macro (environment-set!* env key val) ; must stay private `(ahash-set! ,env ,key ,val)) (define-macro (environment-remove! env key) ; must stay private `(ahash-remove! ,env ,key)) (define (environment-ref* env key) (let ((h (ahash-get-handle env key))) (if h (cdr h) ;; WARNING: guile-1.3.4 requires %S instead of ~S (texmacs-error "Unbound key in environment:" key)))) (define-macro (environment-ref env key) `(environment-ref* ,env (quote ,key))) (define (environment-binding env key) ;; If @key is bound in @env returns (list @key value). Otherwise, return #f. ;; Unlike hash-get-handle, the return value is not mutable. (let ((h (ahash-get-handle env key))) (list key (and (pair? h) (list (cdr h)))))) ;; Environment library (only use primitives) (define (environment-bind! env binding) ; must stay private ;; Restore a binding previously saved with environment-binding. (if (second binding) (environment-set!* env (first binding) (car (second binding))) (environment-remove! env (first binding)))) (define (with-environment* env bindings proc) (let ((saves '()) (result #f)) (for-each (lambda (b) (set-cons! saves (environment-binding env (first b))) (environment-set!* env (first b) (second b))) bindings) (set! result (proc env)) (for-each (lambda (b) (environment-bind! env b)) saves) result)) (define (list-of-length-2? x) (and (pair? x) (not (null? (cdr x))) (null? (cddr x)))) (define-macro (with-environment env bindings . body) (if (not (list? bindings)) ;; WARNING: guile-1.3.4 requires %s instead of ~A (syntax-error "Bindings are not a list: ~A" bindings)) `(with-environment* ,env (list ,@(map-in-order (lambda (b) (if (not (list-of-length-2? b)) ;; WARNING: guile-1.3.4 requires %s instead of ~A (syntax-error "Ill-formed binding: ~A" b)) `(list (quote ,(first b)) ,(second b))) bindings)) (lambda (,env) ,@body))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; XPath environment ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Currently, the xpath environment only stores the parent node. ;; Eventually, it should store an inverse list of ancestor nodes. (define (initialize-xpath env root proc) (with-environment* env `((xpath:root ,root) (xpath:parent #f) (xpath:current ,root)) proc)) (define (xpath-descend env child proc) (with-environment* env `((xpath:parent ,(xpath-current env)) (xpath:current ,child)) proc)) (define (xpath-root env) (environment-ref env xpath:root)) (define (xpath-parent env) (environment-ref env xpath:parent)) (define (xpath-current env) (environment-ref env xpath:current)) -- David Allouche | GNU TeXmacs -- Writing is a pleasure Free software engineer | http://www.texmacs.org http://ddaa.net | http://savannah.gnu.org/projects/texmacs da...@al... | all...@te... TeXmacs is NOT a LaTeX front-end and is unrelated to emacs. |