opaque.scm 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. #| -*-Scheme-*-
  2. Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
  3. 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
  4. 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Massachusetts
  5. Institute of Technology
  6. This file is part of MIT/GNU Scheme.
  7. MIT/GNU Scheme is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11. MIT/GNU Scheme is distributed in the hope that it will be useful, but
  12. WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with MIT/GNU Scheme; if not, write to the Free Software
  17. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
  18. USA.
  19. |#
  20. (define *opaque-procedure-table* '())
  21. (define (make-opaque name #!optional function-type)
  22. (if (default-object? function-type)
  23. (set! function-type (default-function-type 1)))
  24. (cond ((assq name *opaque-procedure-table*)
  25. =>
  26. (lambda (entry)
  27. (let ((value (environment-lookup generic-environment name)))
  28. (if (and (not (literal-function? value))
  29. (or (not (eq? value (cadr entry)))
  30. (not (equal? function-type (caddr entry)))))
  31. (set-car! (cdr entry) value)
  32. (set-car! (cddr entry) function-type)))))
  33. ((environment-bound? generic-environment name)
  34. (set! *opaque-procedure-table*
  35. (cons (list name
  36. (environment-lookup generic-environment name)
  37. function-type)
  38. *opaque-procedure-table*)))
  39. (else (error "Cannot find procedure to opaqify" name)))
  40. (environment-define generic-environment
  41. name
  42. (literal-function name function-type))
  43. (environment-define numerical-environment
  44. name
  45. (cadr (assq name *opaque-procedure-table*)))
  46. name)
  47. (define (make-transparent name)
  48. (cond ((assq name *opaque-procedure-table*)
  49. =>
  50. (lambda (entry)
  51. (environment-assign! generic-environment name (cadr entry))))
  52. (else 'done)))
  53. (define (compile-opaque name)
  54. (cond ((assq name *opaque-procedure-table*)
  55. =>
  56. (lambda (entry)
  57. (let ((procedure (cadr entry))
  58. (function-type (caddr entry)))
  59. ;; Must use function type
  60. (let ((arity (procedure-arity procedure)))
  61. (if (not (eq? (car arity) (cdr arity)))
  62. (error "I don't know how to compile this kind of procedure"
  63. name))
  64. (let ((cproc
  65. (lambda->numerical-procedure
  66. (lambdafy (car arity)
  67. (lambda names
  68. (g:simplify (apply procedure names)))))))
  69. (environment-assign! numerical-environment name cproc))))))
  70. (else (error "No opaque definition for procedure" name))))
  71. #|
  72. ;;; For example ...
  73. Image saved on Friday October 1, 2004 at 4:11:23 PM
  74. Release 7.7.91.pre || Microcode 14.11 || Runtime 15.5
  75. SF 4.41 || LIAR 4.117 || Edwin 3.116
  76. ScmUtils Mechanics . Summer 2004
  77. ;You are in an interaction window of the Edwin editor.
  78. ;Type C-h for help. C-h m will describe some commands.
  79. (define (foo x) (- x))
  80. (make-opaque 'foo)
  81. (compile-opaque 'foo)
  82. (pp foo)
  83. #| (lambda (x) (literal-apply apply-hook (list x))) |#
  84. (pp (access foo numerical-environment))
  85. #| (lambda (x19) (&* -1 x19)) |#
  86. (define ((circle) state)
  87. (let ((t (ref state 0))
  88. (x (ref state 1))
  89. (y (ref state 2)))
  90. (up 1 y (foo x))))
  91. (define ((mon-xy win) state)
  92. (let ((t (ref state 0))
  93. (x (ref state 1))
  94. (y (ref state 2)))
  95. (plot-point win x y)))
  96. (define win (frame -2 2 -2 2))
  97. (begin (graphics-clear win)
  98. ((evolve circle) (up 0 1 0) (mon-xy win) .001 10))
  99. ;Value: #(10.000000000000728 -.8390715290764753 .5440211108893664)
  100. ;;; Works
  101. ;;; Just to test that we are really accessing the right foo...
  102. (set! (access foo numerical-environment))
  103. ;Value: #[compiled-procedure 17 (lambda) #xF #xADF75F]
  104. (begin (graphics-clear win)
  105. ((evolve circle) (up 0 1 0) (mon-xy win) .001 10))
  106. ;Anomalous microcode error unassigned-variable -- get a wizard.
  107. ;;; And I can restore it.
  108. (compile-opaque 'foo)
  109. (begin (graphics-clear win)
  110. ((evolve circle) (up 0 1 0) (mon-xy win) .001 10))
  111. ;Value: #(10.000000000000728 -.8390715290764753 .5440211108893664)
  112. |#
  113. #|
  114. ;;; No trouble with multiple input arguments
  115. (define (baz x y) (- x))
  116. (make-opaque 'baz (-> (X Real Real) Real))
  117. (compile-opaque 'baz)
  118. (pp baz)
  119. #| (lambda (x y) (literal-apply apply-hook (list x y))) |#
  120. (pp (access baz numerical-environment))
  121. #| (lambda (x6 x5) (&* -1 x6)) |#
  122. (define ((circ2) state)
  123. (let ((t (ref state 0))
  124. (x (ref state 1))
  125. (y (ref state 2)))
  126. (up 1 y (baz x y))))
  127. (define ((mon-xy win) state)
  128. (let ((t (ref state 0))
  129. (x (ref state 1))
  130. (y (ref state 2)))
  131. (plot-point win x y)))
  132. (define win (frame -2 2 -2 2))
  133. (begin (graphics-clear win)
  134. ((evolve circ2) (up 0 1 0) (mon-xy win) .001 10))
  135. ;Value: #(10.000000000000728 -.8390715290764753 .5440211108893664)
  136. |#
  137. #|
  138. ;;; Problem with structured values.
  139. (define ((circ1) state)
  140. (let ((t (ref state 0))
  141. (x (ref state 1))
  142. (y (ref state 2)))
  143. (bar x y)))
  144. (define (bar x y)
  145. (up 1 y (- x)))
  146. (begin (graphics-clear win)
  147. ((evolve circ1) (up 0 1 0) (mon-xy win) .001 10))
  148. ;Value: #(10.000000000000728 -.8390715290764753 .5440211108893664)
  149. ;;; Works without opacity, but opacity in compiling screws it up
  150. (define ((circ2) state)
  151. (let ((t (ref state 0))
  152. (x (ref state 1))
  153. (y (ref state 2)))
  154. (bar x y)))
  155. (make-opaque 'bar
  156. (-> (X Real Real)
  157. (UP Real Real Real)))
  158. (compile-opaque 'bar)
  159. (begin (graphics-clear win)
  160. ((evolve circ2) (up 0 1 0) (mon-xy win) .001 10))
  161. ;The object 3, passed as the third argument to subvector-move-left!,
  162. ; is not in the correct range.
  163. ;;; problem is (subvector-move-left! (quote #(#(1 0 -1))) 0 3 (quote #(0. 0. 0.)) 0)
  164. ;;; in (g y0 g$y0), where g is
  165. ;;; (named-lambda (lisptran-derivative y yprime)
  166. ;;; (subvector-move-left! (f y) 0 (vector-length y) yprime 0))
  167. ;;; Stopped inside compile-parametric at call to compiler
  168. ;;; Output of the state-procedure is already screwed up.
  169. (pp (state-procedure (list->vector state-var-names)))
  170. #((*vector*
  171. (expression (bar x1 x2))
  172. (literal-function #[apply-hook 41])
  173. (type-expression (UP Real Real Real))))
  174. (pp state-procedure)
  175. (lambda (fstate)
  176. (flatten
  177. (((access apply ()) parametric-sysder params) (unflatten fstate))))
  178. (where state-procedure)
  179. Environment created by the procedure: PARAMETRIC-FLAT-SYSDER
  180. Depth (relative to initial environment): 0
  181. has bindings:
  182. params = ()
  183. ;;; Parametic-sysder looks good
  184. (pp parametric-sysder)
  185. (named-lambda (circ2)
  186. (lambda (state)
  187. (let ((t (ref state 0)) (x (ref state 1)) (y (ref state 2)))
  188. (bar x y))))
  189. ;;; So problem is with flatten
  190. (pp flatten)
  191. (named-lambda (flatten state)
  192. (list->vector (ultra-flatten state)))
  193. (pp ultra-flatten)
  194. (named-lambda (ultra-flatten s)
  195. (if (structure? s)
  196. ((access apply ())
  197. append
  198. (map ultra-flatten (vector->list (s:->vector s))))
  199. (cons s ())))
  200. ;;; Analysis to follow.
  201. |#
  202. #|
  203. ;;; Things are even worse when we have structured components
  204. ;;; Work fine when acc is transparent, but fails when it is opaque.
  205. (define ((test) state)
  206. (let ((t (ref state 0))
  207. (q (ref state 1))
  208. (v (ref state 2)))
  209. (let ((x (ref q 0))
  210. (y (ref q 1))
  211. (vx (ref v 0))
  212. (vy (ref v 1)))
  213. (up 1
  214. (up vx vy)
  215. (acc x y)))))
  216. (define (acc x y)
  217. (up (* x y) (+ x y)))
  218. (make-opaque 'acc (-> (X Real Real) (UP Real Real)))
  219. (compile-opaque 'acc)
  220. ((evolve test)
  221. (up 0 (up 1 2) (up 3 4))
  222. (lambda (state)
  223. state)
  224. .1
  225. 1)
  226. ;;; At compilation entry point in compile-parametric:
  227. (pp lexp)
  228. (lambda (params)
  229. (let ()
  230. (lambda (state)
  231. (let ((x0 (vector-ref state 0)) (x1 (vector-ref state 1))
  232. (x2 (vector-ref state 2))
  233. (x3 (vector-ref state 3))
  234. (x4 (vector-ref state 4)))
  235. (vector 1 x3 x4 (acc x1 x2))))))
  236. |#
  237. #|
  238. ;;; Hmmm? maybe..., but probably not...
  239. (define (flatten s)
  240. (let ((exps '()))
  241. (define (flatten-helper s)
  242. (cond ((structure? s)
  243. (apply append (map flatten-helper (vector->list (s:->vector s)))))
  244. ((list? s)
  245. (cond ((assq (car s) *opaque-procedure-table*)
  246. =>
  247. (lambda (entry)
  248. (let ((expname (generate-uninterned-symbol)))
  249. (set! exps (cons (list expname s) exps))
  250. (let ((function-type (caddr entry)))
  251. (let ((range (type->range-type function-type)))
  252. (assert (or (eq? (car range) up-tag)
  253. (eq? (car range) down-tag)))
  254. (let lp ((stuff (cdr range)) (path '()))
  255. (cond ((null? stuff) '())
  256. ((symbol? stuff)
  257. `(ref expname ,@path))
  258. ((pair? stuff)
  259. ))))
  260. (else (list s))))
  261. (else (list s))))
  262. (let ((l (flatten-helper s)))
  263. ...)))
  264. |#
  265. #|
  266. (define ((test) state)
  267. (let ((t (ref state 0))
  268. (q (ref state 1))
  269. (v (ref state 2)))
  270. (let ((x (ref q 0))
  271. (y (ref q 1))
  272. (vx (ref v 0))
  273. (vy (ref v 1)))
  274. (acc x y
  275. (lambda (ax ay)
  276. (up 1
  277. (up vx vy)
  278. (up ax ay)))))))
  279. (define (acc x y cont)
  280. (cont (* x y) (+ x y)))
  281. (make-opaque 'acc
  282. (-> (X Real Real
  283. (-> (X Real Real)
  284. (UP Real
  285. (UP Real Real)
  286. (UP Real Real))))
  287. (UP Real
  288. (UP Real Real)
  289. (UP Real Real))))
  290. ((evolve test)
  291. (up 0 (up 1 2) (up 3 4))
  292. (lambda (state)
  293. state)
  294. .1
  295. 1)
  296. ;Value:
  297. #(1.0000000000000004
  298. #(9.64744500576115 9.101859747198148)
  299. #(25.802395793187287 12.616331310363636))
  300. ;;; To make sure that acc is really used:
  301. (pp (access acc numerical-environment))
  302. (named-lambda (acc x y cont)
  303. (cont (* x y) (+ x y)))
  304. (environment-assign! numerical-environment 'acc
  305. (lambda (x y cont)
  306. (cont (* x y) (+ x y))))
  307. ((evolve test)
  308. (up 0 (up 1 2) (up 3 4))
  309. (lambda (state)
  310. state)
  311. .1
  312. 1)
  313. ;Unbound variable: v
  314. ;To continue, call RESTART with an option number:
  315. ; (RESTART 3) => Specify a value to use instead of v.
  316. ; (RESTART 2) => Define v to a given value.
  317. ; (RESTART 1) => Return to read-eval-print level 1.
  318. ;Start debugger? (y or n):
  319. (make-transparent 'acc)
  320. ((evolve test)
  321. (up 0 (up 1 2) (up 3 4))
  322. (lambda (state)
  323. state)
  324. .1
  325. 1)
  326. ;Value:
  327. #(1.0000000000000004
  328. #(9.64744500576115 9.101859747198148)
  329. #(25.802395793187287 12.616331310363636))
  330. |#