express.scm 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  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. ;;;; Utilities for manipulating symbolic expressions
  21. (declare (usual-integrations))
  22. (define (operator exp) (car exp))
  23. (define (operands exp) (cdr exp))
  24. (define first-operand cadr)
  25. (define second-operand caddr)
  26. (define rest-operands cddr)
  27. (define (substitute new old expression)
  28. (define (sloop exp)
  29. (cond ((equal? old exp) new)
  30. ((pair? exp)
  31. (cons (sloop (car exp))
  32. (sloop (cdr exp))))
  33. ((vector? exp)
  34. ((vector-elementwise sloop) exp))
  35. (else exp)))
  36. (if (equal? new old) expression (sloop expression)))
  37. ;;; Abstract quantities are represented with a type-tagged property list,
  38. ;;; implemented as an alist.
  39. (define* ((has-property? property-name) abstract-quantity)
  40. (cond ((pair? abstract-quantity)
  41. (assq property-name (cdr abstract-quantity)))
  42. ((symbol? abstract-quantity)
  43. (if (eq? property-name 'expression)
  44. (list 'expression abstract-quantity)
  45. (error "Symbols have only EXPRESSION properties")))
  46. (else
  47. (error "Bad abstract quantity"))))
  48. (define* (get-property abstract-quantity property-name #:optional default)
  49. (cond ((pair? abstract-quantity)
  50. (let ((default (if (default-object? default) #f default))
  51. (v (assq property-name (cdr abstract-quantity))))
  52. (if v (cadr v) default)))
  53. ((symbol? abstract-quantity)
  54. (if (eq? property-name 'expression)
  55. abstract-quantity
  56. default))
  57. (else
  58. (error "Bad abstract quantity"))))
  59. (define (add-property! abstract-quantity property-name property-value)
  60. (if (pair? abstract-quantity)
  61. (set-cdr! (last-pair abstract-quantity)
  62. (list (list property-name property-value)))
  63. (error "Bad abstract quantity -- ADD-PROPERTY!")))
  64. ;;; An abstract quantity may be have a type-tagged expression.
  65. (define (make-numerical-literal expression)
  66. (make-literal '*number* expression))
  67. (define (make-real-literal expression)
  68. (let ((e (make-numerical-literal expression)))
  69. (add-property! e 'real #t)
  70. e))
  71. (define (make-literal type-tag expression)
  72. (list type-tag (list 'expression expression)))
  73. (define (make-combination type-tag operator operands)
  74. (make-literal type-tag (cons operator operands)))
  75. (define (expression-of abstract-quantity)
  76. (cond ((pair? abstract-quantity)
  77. (let ((v (assq 'expression (cdr abstract-quantity))))
  78. (if v
  79. (cadr v)
  80. (error "No expression for abstract quantity"
  81. abstract-quantity))))
  82. ((symbol? abstract-quantity)
  83. abstract-quantity)
  84. (else
  85. (error "Bad abstract quantity"))))
  86. ;;; In this system, expressions never contain vectors or matrices,
  87. ;;; they only contain constructions for them. Thus we need to be able
  88. ;;; to recognize the constructors:
  89. (define (down-maker? expr)
  90. (and (pair? expr)
  91. (eq? (car expr) down-constructor-name)))
  92. (define (up-maker? expr)
  93. (and (pair? expr)
  94. (eq? (car expr) up-constructor-name)))
  95. (define (vector-maker? expr)
  96. (and (pair? expr)
  97. (eq? (car expr) 'vector)))
  98. (define (quaternion-maker? expr)
  99. (and (pair? expr)
  100. (eq? (car expr) 'quaternion)))
  101. (define (matrix-by-rows-maker? expr)
  102. (and (pair? expr)
  103. (eq? (car expr) 'matrix-by-rows)))
  104. (define (matrix-by-columns-maker? expr)
  105. (and (pair? expr)
  106. (eq? (car expr) 'matrix-by-cols)))
  107. (define (matrix-maker? expr)
  108. (and (pair? expr)
  109. (or (eq? (car expr) 'matrix-by-rows)
  110. (eq? (car expr) 'matrix-by-cols))))
  111. (define (compound-data-constructor? expr)
  112. (and (pair? expr)
  113. (memq (car expr)
  114. '(list
  115. vector
  116. quaternion
  117. down
  118. up
  119. matrix-by-rows
  120. matrix-by-cols))))
  121. (define (expression expr)
  122. (define (exprlp expr)
  123. (cond ((number? expr)
  124. (if (and (inexact? expr) heuristic-number-canonicalizer)
  125. (heuristic-number-canonicalizer expr)
  126. expr))
  127. ((symbol? expr) expr)
  128. ((null? expr) expr)
  129. ((differential? expr)
  130. `(make-differential-quantity
  131. (list ,@(map (lambda (term)
  132. `(make-differential-term
  133. ',(differential-tags term)
  134. ,(exprlp (differential-coefficient term))))
  135. (differential-term-list expr)))))
  136. ((down? expr)
  137. (cons down-constructor-name
  138. (let lp ((i 0))
  139. (if (fix:= i (s:length expr))
  140. '()
  141. (cons (exprlp (s:ref expr i))
  142. (lp (fix:+ i 1)))))))
  143. ((up? expr) ;subsumes vector? below.
  144. (cons up-constructor-name
  145. (let lp ((i 0))
  146. (if (fix:= i (s:length expr))
  147. '()
  148. (cons (exprlp (s:ref expr i))
  149. (lp (fix:+ i 1)))))))
  150. #|
  151. ((vector? expr)
  152. (cons 'vector
  153. (vector->list
  154. ((vector-elementwise exprlp) expr))))
  155. |#
  156. ((quaternion? expr)
  157. (cons 'quaternion
  158. (vector->list
  159. ((vector-elementwise exprlp) (cadr expr)))))
  160. ((matrix? expr)
  161. `(matrix-by-rows
  162. ,@(map (lambda (r)
  163. (cons 'list (vector->list r)))
  164. (vector->list
  165. (matrix->array ((m:elementwise exprlp) expr))))))
  166. ((literal-number? expr)
  167. (exprlp (expression-of expr)))
  168. ((or (with-units? expr) (units? expr))
  169. (exprlp (with-si-units->expression expr)))
  170. ((pair? expr)
  171. (cond ((eq? (car expr) '???) expr)
  172. ((memq (car expr) abstract-type-tags)
  173. (exprlp (expression-of expr)))
  174. (else (safe-map exprlp expr))))
  175. ((abstract-function? expr)
  176. (exprlp (f:expression expr)))
  177. ((operator? expr)
  178. (exprlp (operator-name expr)))
  179. ((procedure? expr)
  180. (procedure-expression expr))
  181. ((undefined-value? expr)
  182. '*undefined-value*)
  183. ((boolean? expr)
  184. (if expr 'true 'false))
  185. (else (error "Bad expression" expr))))
  186. (exprlp expr))
  187. (define up-constructor-name 'up)
  188. (define down-constructor-name 'down)
  189. ;;; Finds a name, if any, of the given object in the given
  190. ;;; environments. If none, value is #f.
  191. (define* (object-name object #:rest environments)
  192. (let lp ((environments environments))
  193. (cond ((null? environments) #f)
  194. ((rlookup object (environment-bindings (car environments)))
  195. => car)
  196. (else (lp (cdr environments))))))
  197. ;;; FBE start: This is MIT Scheme. Replaced by procedure in (mit apply-hook).
  198. ;; (define (procedure-name f)
  199. ;; (let ((u2 (unsyntax (procedure-lambda f))))
  200. ;; (and (pair? u2)
  201. ;; (cond ((eq? (car u2) 'named-lambda) (caadr u2))
  202. ;; ((eq? (car u2) 'lambda) `(??? ,@(cadr u2)))
  203. ;; (else
  204. ;; (error "Unknown procedure type" f))))))
  205. ;;; FBE end
  206. (define (procedure-expression f)
  207. (or (eq-get f 'function-name)
  208. (procedure-name f)
  209. (object-name f
  210. user-generic-environment
  211. generic-environment
  212. ;;rule-environment ; FBE: now alias for 'scmutils-base-environment'
  213. numerical-environment
  214. scmutils-base-environment)
  215. '???))
  216. (define (generate-list-of-symbols base-symbol n)
  217. (generate-list n
  218. (lambda (i)
  219. (concatenate-names base-symbol
  220. (string->symbol (number->string i))))))
  221. #|
  222. (define (variables-in expr)
  223. (cond ((pair? expr)
  224. (reduce list-union
  225. '()
  226. (map variables-in expr)))
  227. ((symbol? expr) (list expr))
  228. (else '())))
  229. |#
  230. (define (variables-in expr)
  231. (let lp ((expr expr)
  232. (vars '())
  233. (cont (lambda (vars) vars)))
  234. (cond ((pair? expr)
  235. (lp (car expr)
  236. vars
  237. (lambda (vars)
  238. (lp (cdr expr)
  239. vars
  240. cont))))
  241. ((symbol? expr)
  242. (if (memq expr vars)
  243. (cont vars)
  244. (cont (cons expr vars))))
  245. (else (cont vars)))))
  246. (define (pair-up vars vals table)
  247. (cond ((null? vars)
  248. (cond ((null? vals) table)
  249. (else
  250. (error "Too many vals -- PAIR-UP"
  251. vars vals))))
  252. ((null? vals)
  253. (error "Too few vals -- PAIR-UP"
  254. vars vals))
  255. (else
  256. (cons (list (car vars) (car vals))
  257. (pair-up (cdr vars) (cdr vals)
  258. table)))))
  259. ;;; An evaluator for simple expressions
  260. (define (expression-walker environment)
  261. (define (walk expr)
  262. (cond ((number? expr) expr)
  263. ((symbol? expr)
  264. (lookup expr environment))
  265. ((pair? expr)
  266. (apply (walk (car expr))
  267. (map walk (cdr expr))))
  268. (else
  269. (error "Unknown expression type -- EXPRESSION-WALK"
  270. expr))))
  271. walk)
  272. (define (expr:< expr1 expr2)
  273. (cond ((null? expr1)
  274. (if (null? expr2) #f #t))
  275. ((null? expr2) #f)
  276. ((real? expr1)
  277. (if (real? expr2) (< expr1 expr2) #f))
  278. ((real? expr2) #f)
  279. ((symbol? expr1)
  280. (if (symbol? expr2)
  281. (variable<? expr1 expr2)
  282. #f))
  283. ((symbol? expr2) #f)
  284. ((pair? expr1)
  285. (cond ((pair? expr2)
  286. (cond ((fix:< (length expr1) (length expr2)) #t)
  287. ((expr:= (car expr1) (car expr2))
  288. (expr:< (cdr expr1) (cdr expr2)))
  289. ((expr:< (car expr1) (car expr2)) #t)
  290. (else #f)))
  291. (else #f)))
  292. ((pair? expr2) #f)
  293. ((vector? expr1)
  294. (cond ((vector? expr2)
  295. (cond ((fix:< (vector-length expr1)
  296. (vector-length expr2))
  297. #t)
  298. ((fix:= (vector-length expr1)
  299. (vector-length expr2))
  300. (let ((n (vector-length expr1)))
  301. (let lp ((i 0))
  302. (cond ((fix:= i n) #f)
  303. ((expr:< (vector-ref expr1 i)
  304. (vector-ref expr2 i))
  305. #t)
  306. ((expr:= (vector-ref expr1 i)
  307. (vector-ref expr2 i))
  308. (lp (fix:+ i 1)))
  309. (else #f)))))
  310. (else #f)))
  311. (else #f)))
  312. ((vector? expr2) #f)
  313. ((string? expr1)
  314. (if (string expr2)
  315. (string:<? expr1 expr2)
  316. #f))
  317. ((string? expr2) #f)
  318. (else
  319. (< (hash expr1) (hash expr2)))))
  320. (define expr:= equal?)