progfun.scm 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. ;;; progfun.scm -- functions dealing with BRL programs
  2. ;;; Copyright (C) 1999, 2000 Bruce R. Lewis and Eaton Vance Management
  3. ;;; See the file COPYING for license terms.
  4. ;;;;; Part I: NAL
  5. ;;;
  6. ;;; nal - named-argument lambda
  7. ;;; A nal is a list whose first element is a procedure,
  8. ;;; and whose remaining elements are symbols naming the
  9. ;;; second and subsequent arguments to the procedure.
  10. ;;; The first argument is brl-context, explained later.
  11. ;;;
  12. #|
  13. (define brl-nal-proc car)
  14. (define brl-nal-args cdr)
  15. ;
  16. ; Take a list of expressions (including the inputs expr)
  17. ; and create a nal from it.
  18. ;
  19. (define (brl-make-nal l)
  20. (let ((ins (brl-template-inputs l)))
  21. (cons (eval
  22. (make <pair-with-position>
  23. (as <pair-with-position> l)
  24. 'lambda
  25. (list (cons 'brl-context ins)
  26. `(letrec-syntax
  27. ((brl-out
  28. (syntax-rules (brl-content-type!
  29. brl-http-header!
  30. brl-set-cont!
  31. brl-set-endproc!
  32. brl-set-outport!
  33. define define-syntax
  34. set! set-car! set-cdr!
  35. silent sql-statement-close
  36. string-fill! string-set!
  37. vector-fill! vector-set!
  38. write)
  39. ((brl-out (brl-content-type! expr ...))
  40. (brl-content-type! expr ...))
  41. ((brl-out (brl-http-header! expr ...))
  42. (brl-http-header! expr ...))
  43. ((brl-out (brl-set-cont! expr ...))
  44. (brl-set-cont! expr ...))
  45. ((brl-out (brl-set-endproc! expr ...))
  46. (brl-set-endproc! expr ...))
  47. ((brl-out (brl-set-outport! expr ...))
  48. (brl-set-outport! expr ...))
  49. ((brl-out (define expr ...)) (define expr ...))
  50. ((brl-out (define-syntax expr ...))
  51. (define-syntax expr ...))
  52. ((brl-out (set! expr ...)) (set! expr ...))
  53. ((brl-out (set! expr ...)) (set! expr ...))
  54. ((brl-out (set-car! expr ...)) (set-car! expr ...))
  55. ((brl-out (set-cdr! expr ...)) (set-cdr! expr ...))
  56. ((brl-out (silent expr ...)) (begin expr ...))
  57. ((brl-out (sql-statement-close expr ...))
  58. (sql-statement-close expr ...))
  59. ((brl-out (string-fill! expr ...))
  60. (string-fill! expr ...))
  61. ((brl-out (string-set! expr ...))
  62. (string-set! expr ...))
  63. ((brl-out (vector-fill! expr ...))
  64. (vector-fill! expr ...))
  65. ((brl-out (vector-set! expr ...))
  66. (vector-set! expr ...))
  67. ((brl-out (write expr ...)) (write expr ...))
  68. ((brl-out expr) (display expr (brl-context-outport
  69. brl-context)))
  70. ((brl-out expr1 expr2 ...) (begin
  71. (brl-out expr1)
  72. (brl-out expr2 ...)))))
  73. (brl
  74. (syntax-rules ()
  75. ((brl expr ...)
  76. (begin (brl-out expr ...) ""))))
  77. (brl-when
  78. (syntax-rules ()
  79. ((brl-when pred expr ...)
  80. (if pred (brl expr ...) ""))))
  81. (brl-unless
  82. (syntax-rules ()
  83. ((brl-unless pred expr ...)
  84. (if pred "" (brl expr ...)))))
  85. (paste
  86. (syntax-rules ()
  87. ((paste relative-uri)
  88. (brl-paste brl-context relative-uri))))
  89. (cgi
  90. (syntax-rules ()
  91. ((cgi var) ((; constant-fold ;FIXME
  92. brl-sv-req-string-retriever
  93. (quote var))
  94. (brl-context-sv-req brl-context))))))
  95. ,(cons 'brl (brl-template-inputs-delete! l l))))))
  96. ins)))
  97. |#
  98. (define-syntax brl
  99. (syntax-rules () ((brl expr ...) (values-append expr ...))))
  100. #|
  101. ;;; brl-context - a list with at least two elements
  102. (define brl-context-outport car) ; an output port
  103. (define brl-context-ctin cadr) ; a continuation
  104. (define brl-context-endproc caddr) ; a procedure or #f
  105. ; optional elements
  106. (define brl-context-bindings cadddr) ; list of input symbols and values
  107. (define (brl-context-sv c) (list-ref c 4)) ; Servlet
  108. (define (brl-context-sv-req c) (list-ref c 5)) ; Servlet HTTP request
  109. (define (brl-context-sv-rsp c) (list-ref c 6)) ; Servlet HTTP response
  110. (define (brl-context-content-type c) (list-ref c 7)) ; Servlet HTTP response
  111. ; deprecated
  112. (define (brl-context-type c)
  113. (if (instance? (list-ref c 4) <javax.servlet.Servlet>)
  114. 'servlet
  115. 'non-servlet))
  116. (define brl-set-outport! set-car!)
  117. (define (brl-continue c) ((brl-context-ctin c)))
  118. (define (brl-set-cont! c ctin) (set-car! (cdr c) ctin))
  119. (define (brl-set-endproc! c proc) (set-car! (cddr c) proc))
  120. (define (brl-content-type! c type)
  121. (set-car! (cdddr (cddddr c)) type))
  122. ; Add to the existing endproc for a BRL context
  123. (define (brl-prepend-endproc! c newproc)
  124. (let ((oldproc (brl-context-endproc c)))
  125. (brl-set-endproc!
  126. c
  127. (if (procedure? oldproc)
  128. (lambda () (newproc) (oldproc))
  129. newproc))))
  130. ; Find a binding value
  131. (define (brl-binding-get ctxt var)
  132. (let loop ((input-list (brl-context-bindings ctxt)))
  133. (if (null? input-list)
  134. #f
  135. (if (eq? var (caar input-list))
  136. (cdar input-list)
  137. (loop (cdr input-list))))))
  138. |#
  139. ;;;;; Part II: functions to read BRL template files
  140. #|
  141. (define brl-read (make <gnu.brl.read>))
  142. (define brl-readall (make <gnu.brl.readall>))
  143. |#
  144. ;
  145. ; A BRL template may have an expr (inputs a b c ...) to ease compilation
  146. ; This is never the 1st exp in the template.
  147. ;
  148. #|
  149. (define (brl-template-inputs l)
  150. (if (null? l)
  151. '()
  152. (if (and (list? (car l))
  153. (eq? 'inputs (caar l)))
  154. (cdar l)
  155. (brl-template-inputs (cdr l)))))
  156. (define (brl-template-inputs-delete! l start)
  157. (letrec ((delete-subsequent
  158. (lambda (lst)
  159. (if (or (not (pair? lst))
  160. (not (pair? (cdr lst))))
  161. start
  162. (if (and (pair? (cadr lst))
  163. (eq? 'inputs (caadr lst)))
  164. (begin
  165. (set-cdr! lst (cddr lst))
  166. start)
  167. (delete-subsequent (cdr lst)))))))
  168. (cond
  169. ((null? l) l)
  170. ((and (pair? l) (pair? (car l)) (eq? 'inputs (caar l)))
  171. (cdr l))
  172. (else (delete-subsequent l)))))
  173. (define (brl-read-nal p)
  174. (brl-make-nal (brl-readall p)))
  175. (define (brl-load fname)
  176. (call-with-input-file fname brl-read-nal))
  177. (define (brl-result nal args partial-context)
  178. (let ((full-context (cons #f (cons #f (cons #f partial-context)))))
  179. (call-with-output-string
  180. (lambda (p)
  181. (try-finally
  182. (call-with-current-continuation
  183. (lambda (ctin)
  184. (brl-set-outport! full-context p)
  185. (brl-set-cont! full-context ctin)
  186. (apply (car nal) (cons full-context args))))
  187. (let ((endproc (brl-context-endproc full-context)))
  188. (if (procedure? endproc) (endproc))))))))
  189. ;;;;; Part III: binding sets
  190. (define (brl-binding-make name val) (cons name val))
  191. (define (brl-binding-add bset b)
  192. (let ((existing (assq (car b) bset)))
  193. (if existing
  194. (begin
  195. (set-cdr! existing
  196. ((if (list? (cdr existing))
  197. cons
  198. list) (cdr b) (cdr existing)))
  199. bset)
  200. (cons b bset))))
  201. (define (brl-bindings bset blist)
  202. (if (null? blist)
  203. bset
  204. (brl-bindings (brl-binding-add bset (car blist))
  205. (cdr blist))))
  206. (define (brl-apply nal bset partial-context)
  207. (brl-result
  208. nal
  209. (map (lambda (sym)
  210. (let ((binding (assq sym bset)))
  211. (if binding
  212. (cdr binding)
  213. '())))
  214. (cdr nal))
  215. partial-context))
  216. |#
  217. ;
  218. ; Generic hash table interface
  219. ;
  220. (define (brl-hash)
  221. (make <java.util.Hashtable>))
  222. (define (brl-hash? obj)
  223. (instance? obj <java.util.Dictionary>))
  224. (define (brl-hash-size hh :: <java.util.Dictionary>)
  225. (make <integer> (invoke hh 'size)))
  226. (define (brl-hash-put! hh :: <java.util.Dictionary> key val)
  227. (invoke hh 'put key val))
  228. (define (brl-hash-get hh :: <java.util.Dictionary> key)
  229. (let ((result (invoke hh 'get key)))
  230. (if (eq? #!null result)
  231. #f ; as assoc does
  232. result)))
  233. (define (brl-hash-remove! hh :: <java.util.Dictionary> key)
  234. (invoke hh 'remove key))
  235. (define (brl-hash-keys hh :: <java.util.Dictionary>)
  236. (letrec ((enum (lambda (ee :: <java.util.Enumeration>)
  237. (if (invoke ee 'hasMoreElements)
  238. (let ((nxt (invoke ee 'nextElement)))
  239. (cons nxt (enum ee)))
  240. '()))))
  241. (enum (invoke hh 'keys))))
  242. (define (brl-hash-contains-key? hh :: <java.util.Hashtable> key)
  243. (invoke hh 'containsKey key))
  244. #|
  245. ;
  246. ; Cache of NALs, implemented as a hash table
  247. ; with filenames as keys, and (cons NAL file-modtime) as values
  248. ;
  249. (define brl-nal-cache (brl-hash))
  250. ; Get nal from cache, creating if needed
  251. (define (brl-nal-cache-get fname)
  252. (let ((cached (brl-hash-get brl-nal-cache fname))
  253. (new-modtime (file-last-modified fname)))
  254. (if (or (not cached)
  255. (not (= new-modtime (cdr cached))))
  256. (let ((new-nal (brl-load fname)))
  257. (brl-hash-put! brl-nal-cache fname (cons new-nal new-modtime))
  258. new-nal)
  259. (car cached))))
  260. (define (brl-handle-2.23 fname blist partial-context)
  261. (let ((nal (brl-nal-cache-get fname)))
  262. (brl-apply
  263. nal
  264. (brl-bindings '() blist)
  265. (cons blist partial-context))))
  266. |#
  267. #|
  268. (define (brl-paste ctxt relative-uri)
  269. (let ((sv :: <gnu.brl.brlsv> (brl-context-sv ctxt))
  270. (req :: <javax.servlet.http.HttpServletRequest>
  271. (brl-context-sv-req ctxt)))
  272. (let ((nal
  273. (brl-nal-cache-get
  274. (invoke sv 'getPertinentFile
  275. req
  276. (invoke sv 'getRelativeURI req relative-uri)))))
  277. (if (null? (cdr nal))
  278. ((car nal) ctxt)
  279. (apply (car nal)
  280. (cons ctxt (map (lambda (var)
  281. (or (brl-binding-get ctxt var) '()))
  282. (cdr nal))))))))
  283. |#
  284. #|
  285. ; Backwards compatibility
  286. (define (brl-handle-request fname blist . partial-context)
  287. (brl-handle-2.23 fname blist partial-context))
  288. |#
  289. (define (file-last-modified fname)
  290. (kawa-convert
  291. ((primitive-virtual-method <java.io.File>
  292. "lastModified" <long> ())
  293. ((primitive-constructor <java.io.File> (<String>))
  294. fname))))
  295. ; Misc
  296. #|
  297. (define (brl-implementation-version)
  298. (make <string> (as <java.lang.String>
  299. (static-field <gnu.brl.Version> 'release_string))))
  300. |#
  301. (define brl-random (make <gnu.brl.random>))
  302. (define brl-typeable-chars
  303. ; Letters/numbers, excepting o, 0, 1, l
  304. (list->vector (string->list "abcdefghijkmnpqrstuvwxyz23456789")))
  305. (define brl-typeable-count (vector-length brl-typeable-chars))
  306. (define (brl-random-typeable len)
  307. (let ((retval (make-string len)))
  308. (let loop ((i 0))
  309. (if (>= i len)
  310. retval
  311. (begin
  312. (string-set!
  313. retval i (vector-ref brl-typeable-chars
  314. (brl-random brl-typeable-count)))
  315. (loop (+ 1 i)))))))