debug.scm 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey, Jonathan Rees, Mike Sperber, Martin Gasbichler,
  3. ; Marcus Crestani
  4. ; Commands for debugging.
  5. ; translate
  6. (define-command-syntax 'translate "<from> <to>"
  7. "establish file name translation"
  8. '(filename filename))
  9. (define translate set-translation!)
  10. ; preview -- show continuations
  11. (define (preview)
  12. (let ((cont (command-continuation)))
  13. (if cont
  14. (display-preview (continuation-preview cont)
  15. (command-output)))))
  16. (define (display-preview preview port)
  17. (for-each (lambda (info+pc)
  18. (if (not (fluid-let-continuation-info? (car info+pc)))
  19. (display-template-names (car info+pc) port)))
  20. preview))
  21. (define (display-template-names info port)
  22. (let ((names (debug-data-names info)))
  23. (display " " port)
  24. (if (null? names)
  25. (begin (display "unnamed " port)
  26. (write `(id ,(if (debug-data? info)
  27. (debug-data-uid info)
  28. info))
  29. port))
  30. (let loop ((names names))
  31. (if (car names)
  32. (write (car names) port)
  33. (display "unnamed" port))
  34. (if (and (not (null? (cdr names)))
  35. (cadr names))
  36. (begin (display " in " port)
  37. (loop (cdr names))))))
  38. (newline port)))
  39. (define fluid-let-continuation-info? ;Incestuous!
  40. (let ((id (let-fluid (make-fluid #f) #f
  41. (lambda ()
  42. (primitive-catch (lambda (k)
  43. (let ((template (continuation-template k)))
  44. (if template
  45. (template-id template)
  46. #f))))))))
  47. (lambda (info)
  48. (eqv? (if (debug-data? info)
  49. (debug-data-uid info)
  50. info)
  51. id))))
  52. (define-command-syntax 'preview ""
  53. "show pending continuations (stack trace)"
  54. '())
  55. ; Proceed
  56. (define (really-proceed vals)
  57. (let* ((level (command-level))
  58. (condition (command-level-condition level)))
  59. (if (ok-to-proceed? condition)
  60. (apply proceed-with-command-level (cadr (command-levels)) vals)
  61. (begin
  62. (write-line "No way to proceed from here." (command-output))
  63. (write condition (command-output))
  64. (newline (command-output))))))
  65. (define-command-syntax 'proceed "<exp>" "proceed after an interrupt or error"
  66. '(&rest expression))
  67. (define (proceed . exps)
  68. (really-proceed (map (lambda (exp)
  69. (eval exp (environment-for-commands)))
  70. exps)))
  71. ; Scrutinize the condition to ensure that it's safe to return from the
  72. ; call to RAISE.
  73. (define (ok-to-proceed? condition)
  74. (and condition
  75. (if (serious-condition? condition)
  76. (and (vm-exception? condition)
  77. (let ((opcode (vm-exception-opcode condition)))
  78. (or (= opcode (enum op global))
  79. (>= opcode (enum op eq?)))))
  80. #t)))
  81. (define (breakpoint . rest)
  82. (command-loop (conditions:condition (make-breakpoint-condition)
  83. (make-who-condition 'breakpoint)
  84. (make-irritants-condition rest))))
  85. (define-condition-type &breakpoint &condition
  86. make-breakpoint-condition breakpoint-condition?)
  87. ; push
  88. (define-command-syntax 'push "" "push command level" '())
  89. (define (push)
  90. (command-loop (if (command-level? (focus-object))
  91. (command-level-condition (focus-object))
  92. #f)))
  93. ; pop (same as ^D (= end-of-file))
  94. (define-command-syntax 'pop "" "pop command level" '())
  95. (define (pop)
  96. (pop-command-level))
  97. ; reset
  98. (define (reset . maybe-level)
  99. (if (null? maybe-level)
  100. (abort-to-command-level (top-command-level))
  101. (go-to-level (car maybe-level))))
  102. (define-command-syntax 'reset "[<number>]"
  103. "restart command level (default level is 0)"
  104. '(&opt expression))
  105. (define (go-to-level n)
  106. (let ((level (find-level n)))
  107. (if level
  108. (abort-to-command-level level)
  109. (write-line "invalid command level" (command-output)))))
  110. ; Old ,level command retained for compatibility.
  111. ; Has no help strings s it won't show up in the ,? list.
  112. (define-command-syntax 'level #f #f '(expression))
  113. (define level go-to-level)
  114. ; Find the Nth command level.
  115. (define (find-level n)
  116. (let ((levels (reverse (command-levels))))
  117. (if (and (integer? n)
  118. (>= n 0)
  119. (< n (length levels)))
  120. (list-ref levels n)
  121. #f)))
  122. ; resume
  123. ; Same as ,reset except that we don't restart the level.
  124. (define (resume . maybe-level)
  125. (let ((level (if (null? maybe-level)
  126. (top-command-level)
  127. (find-level (car maybe-level)))))
  128. (if level
  129. (begin
  130. (if (command-level-paused-thread level)
  131. (kill-paused-thread! level))
  132. (proceed-with-command-level level))
  133. (write-line "invalid command level" (command-output)))))
  134. (define-command-syntax 'resume "[<number>]"
  135. "resume specific command level (default is 0)"
  136. '(&opt expression))
  137. (define-command-syntax 'condition ""
  138. "select an object that describes the current error condition"
  139. '())
  140. (define (condition)
  141. (let ((c (command-level-condition (command-level))))
  142. (if c
  143. (set-command-results! (list c) #t)
  144. (write-line "no condition" (command-output)))))
  145. ; Toggling various boolean flags.
  146. (define-command-syntax 'set "<setting> [<on-or-off-or-literal-or-?>]"
  147. "set the value of a setting (? lists settings)"
  148. '(name &opt literal))
  149. (define-command-syntax 'unset "<setting>"
  150. "set boolean setting to off"
  151. '(name))
  152. (define (set name . maybe-value)
  153. (if (eq? name '?)
  154. (list-settings)
  155. (let* ((setting (lookup-setting name))
  156. (value (cond ((not setting)
  157. (assertion-violation 'set "setting not found" name))
  158. ((null? maybe-value)
  159. (if (setting-boolean? setting)
  160. #t
  161. (assertion-violation 'set "no value specified")))
  162. ((eq? (car maybe-value) '?)
  163. (if (setting-boolean? setting)
  164. (display (if (setting-value setting)
  165. "on, "
  166. "off, ")
  167. (command-output)))
  168. (setting-value setting))
  169. ((setting-boolean? setting)
  170. (case (car maybe-value)
  171. ((off) #f)
  172. ((on) #t)
  173. (else
  174. (assertion-violation
  175. 'set
  176. "invalid value for boolean setting; should be on or off"))))
  177. (else
  178. (car maybe-value))))
  179. (out (command-output)))
  180. (setting-set! setting value)
  181. (display (setting-doc setting) out)
  182. (if (not (setting-boolean? setting))
  183. (begin
  184. (display " is " (command-output))
  185. (write value (command-output))))
  186. (newline out))))
  187. (define (unset name)
  188. (let ((setting (lookup-setting name))
  189. (out (command-output)))
  190. (if (not setting)
  191. (assertion-violation 'unset "setting not found" name)
  192. (setting-set! setting #f))
  193. (display (setting-doc setting) out)
  194. (newline out)))
  195. ; The actual settings.
  196. (define (positive-integer? n)
  197. (and (integer? n)
  198. (exact? n)
  199. (positive? n)))
  200. (add-setting 'batch #t
  201. batch-mode?
  202. set-batch-mode?!
  203. "will not prompt and will exit on errors"
  204. "will prompt and will not exit on errors")
  205. (add-setting 'inline-values #t
  206. (lambda ()
  207. (package-integrate? (environment-for-commands)))
  208. (lambda (b)
  209. (set-package-integrate?! (environment-for-commands) b))
  210. "will compile some calls in line"
  211. "will not compile calls in line")
  212. (add-setting 'break-on-warnings #t
  213. break-on-warnings?
  214. set-break-on-warnings?!
  215. "will enter breakpoint on warnings"
  216. "will not enter breakpoint on warnings")
  217. (add-setting 'load-noisily #t
  218. load-noisily?
  219. set-load-noisily?!
  220. "will notify when loading modules and files"
  221. "will not notify when loading modules and files")
  222. ;(add-setting 'form-preferred #t
  223. ; form-preferred?
  224. ; set-form-preferred?!
  225. ; "commas are required before commands"
  226. ; "commas are not required before commands")
  227. (add-setting 'levels #t
  228. push-command-levels?
  229. set-push-command-levels?!
  230. "will push command level on errors"
  231. "will not push command level on errors")
  232. (add-setting 'inspector-menu-limit positive-integer?
  233. inspector-menu-limit
  234. set-inspector-menu-limit!
  235. "maximum number of menu entries in inspector")
  236. (add-setting 'inspector-writing-depth positive-integer?
  237. inspector-writing-depth
  238. set-inspector-writing-depth!
  239. "maximum writing depth in inspector")
  240. (add-setting 'inspector-writing-length positive-integer?
  241. inspector-writing-length
  242. set-inspector-writing-length!
  243. "maximum writing length in inspector")
  244. (add-setting 'condition-writing-length positive-integer?
  245. condition-writing-length
  246. set-condition-writing-length!
  247. "maximum writing length for conditions")
  248. (add-setting 'condition-writing-depth positive-integer?
  249. condition-writing-depth
  250. set-condition-writing-depth!
  251. "maximum writing depth for conditions")
  252. ; Old toggling commands retained for compatibility
  253. ; These have no help strings.
  254. (define (define-toggle-syntax name help)
  255. (define-command-syntax name #f #f '(&opt name)))
  256. (define (toggle-command name)
  257. (lambda maybe-value
  258. (set name (if (null? maybe-value)
  259. (if (setting-value (or (lookup-setting name)
  260. (assertion-violation 'toggle "setting not found" name)))
  261. 'off
  262. 'on)
  263. (car maybe-value)))))
  264. (define-toggle-syntax 'batch
  265. "enable/disable batch mode (no prompt, errors exit)")
  266. (define batch (toggle-command 'batch))
  267. (define-toggle-syntax 'bench
  268. "enable/disable inlining of primitives")
  269. (define bench (toggle-command 'inline-values))
  270. (define-toggle-syntax 'break-on-warnings
  271. "treat warnings as errors")
  272. (define break-on-warnings (toggle-command 'break-on-warnings))
  273. ;(define-toggle-syntax 'form-preferred
  274. ; "enable/disable form-preferred command processor mode")
  275. ;
  276. ;(define form-preferred (toggle-command 'form-preferred))
  277. (define-toggle-syntax 'levels
  278. "disable/enable command levels")
  279. (define levels (toggle-command 'levels))
  280. ; Flush debug data base
  281. (define-command-syntax 'flush "[<kind> ...]"
  282. "start forgetting debug information
  283. Kind should be one of: names maps files source tabulate
  284. location-names file-packages"
  285. '(&rest name))
  286. (define (flush . kinds)
  287. (cond ((null? kinds)
  288. (write-line "Flushing location names and tabulated debug info"
  289. (command-output))
  290. (flush-location-names)
  291. ((debug-flag-modifier 'table) (make-table)))
  292. (else
  293. (for-each (lambda (kind)
  294. (cond ((memq kind debug-flag-names)
  295. ((debug-flag-modifier kind)
  296. (if (eq? kind 'table) (make-table) #f)))
  297. ((eq? kind 'location-names)
  298. (flush-location-names))
  299. ((eq? kind 'file-packages)
  300. (forget-file-environments))
  301. (else
  302. (write-line "Unrecognized debug flag"
  303. (command-output)))))
  304. kinds))))
  305. ; Control retention of debugging information
  306. (define-command-syntax 'keep "[<kind> ...]"
  307. "start remembering debug information
  308. Kind should be one of: names maps files source tabulate"
  309. '(&rest name))
  310. (define (keep . kinds)
  311. (let ((port (command-output)))
  312. (if (null? kinds)
  313. (for-each (lambda (kind)
  314. (if (not (eq? kind 'table))
  315. (begin
  316. (display (if ((debug-flag-accessor kind))
  317. "+ " "- ")
  318. port)
  319. (display kind port)
  320. (newline port))))
  321. debug-flag-names)
  322. (for-each (lambda (kind)
  323. (if (and (memq kind debug-flag-names)
  324. (not (eq? kind 'table)))
  325. ((debug-flag-modifier kind) #t)
  326. (write-line "Unrecognized debug flag"
  327. port)))
  328. kinds))))
  329. ; Collect some garbage
  330. (define (collect)
  331. (let ((port (command-output))
  332. (available-before (available-memory))
  333. (heap-size-before (heap-size)))
  334. (primitives:collect)
  335. (let ((available-after (available-memory))
  336. (heap-size-after (heap-size)))
  337. (display "Before: " port)
  338. (write available-before port)
  339. (display " out of " port)
  340. (display heap-size-before port)
  341. (display" words available" port)
  342. (newline port)
  343. (display "After: " port)
  344. (write available-after port)
  345. (display " out of " port)
  346. (display heap-size-after port)
  347. (display " words available" port)
  348. (newline port))))
  349. (define (available-memory)
  350. (primitives:memory-status (enum memory-status-option available)
  351. #f))
  352. (define (heap-size)
  353. (primitives:memory-status (enum memory-status-option heap-size)
  354. #f))
  355. (define-command-syntax 'collect "" "invoke the garbage collector" '())
  356. ; Undefined (this is sort of pointless now that NOTING-UNDEFINED-VARIABLES
  357. ; exists)
  358. ;
  359. ;(define (show-undefined-variables)
  360. ; (let ((out (command-output))
  361. ; (undef (undefined-variables (environment-for-commands))))
  362. ; (if (not (null? undef))
  363. ; (begin (display "Undefined: " out)
  364. ; (write undef out)
  365. ; (newline out)))))
  366. ;
  367. ;(define-command-syntax 'undefined "" "list undefined variables"
  368. ; '() show-undefined-variables)
  369. ; Trace and untrace
  370. (define traced-procedures
  371. (user-context-accessor 'traced (lambda () '())))
  372. (define set-traced-procedures!
  373. (user-context-modifier 'traced))
  374. (define (trace . names)
  375. (if (null? names)
  376. (let ((port (command-output)))
  377. (write (map car (traced-procedures)) port)
  378. (newline port))
  379. (for-each trace-1 names)))
  380. (define-command-syntax 'trace "<name> ..."
  381. "trace calls to given procedure(s)"
  382. '(&rest name))
  383. (define (untrace . names)
  384. (if (null? names)
  385. (for-each untrace-1 (map car (traced-procedures)))
  386. (for-each untrace-1 names)))
  387. (define-command-syntax 'untrace "<name> ..." "stop tracing calls"
  388. '(&rest name))
  389. (add-setting 'trace-writing-depth positive-integer?
  390. trace-writing-depth
  391. set-trace-writing-depth!
  392. "writing depth for traces")
  393. ; Trace internals
  394. (define (trace-1 name)
  395. (let* ((env (environment-for-commands))
  396. (proc (environment-ref env name))
  397. (traced (make-traced proc name)))
  398. (set-traced-procedures!
  399. (cons (list name traced proc env)
  400. (traced-procedures)))
  401. (environment-define! env name traced))) ;was environment-set!
  402. ; Should be doing clookup's here -- avoid creating new locations
  403. (define (untrace-1 name)
  404. (let ((probe (assq name (traced-procedures))))
  405. (if probe
  406. (let* ((traced (cadr probe))
  407. (proc (caddr probe))
  408. (env (cadddr probe)))
  409. (if (eq? (environment-ref env name) traced)
  410. (environment-set! env name proc)
  411. (let ((out (command-output)))
  412. (display "Value of " out)
  413. (write name out)
  414. (display " changed since ,trace; not restoring it." out)
  415. (newline out)))
  416. (set-traced-procedures!
  417. (filter (lambda (x)
  418. (not (eq? (car x) name)))
  419. (traced-procedures))))
  420. (write-line "?" (command-output)))))
  421. (define (make-traced proc name)
  422. (lambda args
  423. (apply-traced proc name args)))
  424. (define (apply-traced proc name args)
  425. (let ((port (command-output)))
  426. (dynamic-wind
  427. (lambda ()
  428. (display "[" port))
  429. (lambda ()
  430. (let ((depth (trace-writing-depth)))
  431. (with-limited-output
  432. (lambda ()
  433. (display "Enter " port)
  434. (write-carefully (error-form name args) port)
  435. (newline port))
  436. depth depth)
  437. (call-with-values (lambda ()
  438. (apply proc args))
  439. (lambda results
  440. (with-limited-output
  441. (lambda ()
  442. (display " Leave " port)
  443. (write-carefully name port)
  444. (for-each (lambda (result)
  445. (display " " port)
  446. (write-carefully (value->expression result) port))
  447. results))
  448. depth
  449. (- depth 1))
  450. (apply values results)))))
  451. (lambda ()
  452. (display "]" port)
  453. (newline port)))))
  454. ; Timer stuff.
  455. (define (time command)
  456. (let ((thunk (if (eq? (car command) 'run)
  457. (eval `(lambda () ,(cadr command))
  458. (environment-for-commands))
  459. (lambda () (execute-command command))))
  460. (port (command-output)))
  461. (let ((start-run-time (run-time))
  462. (start-real-time (real-time)))
  463. (call-with-values thunk
  464. (lambda results
  465. (let ((stop-run-time (run-time))
  466. (stop-real-time (real-time)))
  467. (display "Run time: " port)
  468. (write-hundredths (- stop-run-time start-run-time) port)
  469. (display " seconds; Elapsed time: " port)
  470. (write-hundredths (- stop-real-time start-real-time) port)
  471. (display " seconds" port)
  472. (newline port)
  473. (set-command-results! results)))))))
  474. ; N is in milliseconds
  475. (define (write-hundredths n port)
  476. (let ((n (round (quotient n 10))))
  477. (write (quotient n 100) port)
  478. (write-char #\. port)
  479. (let ((r (remainder n 100)))
  480. (if (< r 10)
  481. (write-char #\0 port))
  482. (write r port))))
  483. ; Copied from rts/time.scm to avoid a dependency.
  484. (define (real-time)
  485. (primitives:time (enum time-option real-time) #f))
  486. (define (run-time)
  487. (primitives:time (enum time-option run-time) #f))
  488. (define-command-syntax 'time "<command>" "measure execution time"
  489. '(command))
  490. ; Support for stuffing things from Emacs.
  491. (define-command-syntax 'from-file #f #f ;"<filename>" "editor support"
  492. '(&opt filename))
  493. (define-command-syntax 'end #f #f
  494. '())
  495. (define (from-file . maybe-filename)
  496. (let* ((filename (if (null? maybe-filename) #f (car maybe-filename)))
  497. (env (let ((probe (if filename
  498. (get-file-environment filename)
  499. #f))
  500. (c (environment-for-commands)))
  501. (if (and probe (not (eq? probe c)))
  502. (let ((port (command-output)))
  503. (newline port)
  504. (display filename port)
  505. (display " => " port)
  506. (write probe port)
  507. (display " " port) ;dots follow
  508. probe)
  509. c)))
  510. (in (command-input))
  511. (forms (let recur ()
  512. (let ((command (read-command #f #t in)))
  513. (if (eof-object? command)
  514. '()
  515. (case (car command)
  516. ((end) '())
  517. ((#f run) (cons (cadr command) (recur)))
  518. (else
  519. (assertion-violation 'from-file
  520. "unusual command in ,from-file ... ,end"
  521. command))))))))
  522. (if (package? env)
  523. (with-interaction-environment env
  524. (lambda ()
  525. (noting-undefined-variables env
  526. (lambda ()
  527. (eval-from-file forms env (if (null? maybe-filename)
  528. #f
  529. (car maybe-filename)))))
  530. (newline (command-output))))
  531. (for-each (lambda (form) (eval form env)) ;Foo
  532. env))))
  533. ; Filename -> environment map.
  534. (define file-environments
  535. (user-context-accessor 'file-environments (lambda () '())))
  536. (define set-file-environments!
  537. (user-context-modifier 'file-environments))
  538. (define (forget-file-environments)
  539. (set-file-environments! '()))
  540. (define (note-file-environment! filename env)
  541. (if (maybe-user-context)
  542. (let* ((translated (filenames:translate filename))
  543. (envs (file-environments))
  544. (probe (or (assoc filename envs) ;What to do?
  545. (assoc translated envs))))
  546. (if probe
  547. (if (not (eq? env (weak-pointer-ref (cdr probe))))
  548. (let ((port (command-output)))
  549. (newline port)
  550. (display "Changing default package for file " port)
  551. (display filename port)
  552. (display " from" port)
  553. (newline port)
  554. (write (weak-pointer-ref (cdr probe)) port)
  555. (display " to " port)
  556. (write env port)
  557. (newline port)
  558. (set-cdr! probe (make-weak-pointer env))))
  559. (set-file-environments!
  560. (cons (cons filename (make-weak-pointer env))
  561. envs))))))
  562. ;; prints the default package of the given file if found
  563. (define-command-syntax 'show-default-package "<filename>"
  564. "shows the default package of the given file" '(filename))
  565. (define (show-default-package . name)
  566. (if (null? name)
  567. '?
  568. (begin
  569. (write (get-file-environment (car name)))
  570. (newline))))
  571. ; Temporary hack until we get default values for unhandled upcalls.
  572. ; This gets called during the building of, say scheme48.image, while
  573. ; there's still the REALLY-SIGNAL-CONDITION from EXCEPTIONS
  574. ; installed---so we make sure we get the right ones.
  575. (define (maybe-user-context)
  576. (call-with-current-continuation
  577. (lambda (exit)
  578. (with-handler (lambda (condition punt)
  579. (if (serious-condition? condition)
  580. (exit #f)
  581. (punt)))
  582. user-context))))
  583. (define (get-file-environment filename)
  584. (let ((probe (assoc filename (file-environments)))) ;translate ?
  585. (if probe
  586. (weak-pointer-ref (cdr probe))
  587. #f)))
  588. (fluid-cell-set! $note-file-package note-file-environment!)
  589. (define-command-syntax 'forget "<filename>"
  590. "forget file/package association"
  591. '(filename))
  592. (define (forget filename)
  593. (note-file-environment! filename #f))
  594. ; ,bound? <name>
  595. (define-command-syntax 'bound? "<name>"
  596. "display binding of name, if any"
  597. '(name))
  598. (define (bound? name)
  599. (let ((port (command-output))
  600. (probe (package-lookup (environment-for-commands) name)))
  601. (if probe
  602. (begin (display "Bound to " port)
  603. (cond ((binding? probe)
  604. (describe-binding probe port))
  605. (else
  606. (write probe port)
  607. (newline port)))
  608. (set-focus-object! probe))
  609. (write-line "Not bound" port))))
  610. (define (describe-binding binding port)
  611. (let ((type (binding-type binding))
  612. (location (binding-place binding))
  613. (static (binding-static binding)))
  614. (display (binding-type-description binding) port)
  615. (write-char #\space port)
  616. (write location port)
  617. (newline port)
  618. (display " Type " port)
  619. (write (type->sexp type #t) port)
  620. (newline port)
  621. (cond (static (display " Static " port)
  622. (write static port)
  623. (newline port)))))
  624. (define (binding-type-description binding)
  625. (let ((type (binding-type binding))
  626. (static (binding-static binding)))
  627. (cond ((variable-type? type) "mutable variable")
  628. ((eq? type undeclared-type) "unknown denotation")
  629. ((subtype? type syntax-type)
  630. (if (transform? static) "macro" "special operator"))
  631. ((primop? static) "primitive procedure")
  632. ((transform? static) "integrated procedure")
  633. (else "variable"))))
  634. ; ,expand <form>
  635. (define-command-syntax 'expand "[<form>]"
  636. "macro-expand a form"
  637. '(&opt expression))
  638. ; Doesn't work - the current syntax interface doesn't have anything that only
  639. ; expands once.
  640. ;(define-command-syntax 'expand-once "[<form>]"
  641. ; "macro-expand a form once"
  642. ; '(&opt expression))
  643. (define (expand . maybe-exp)
  644. (do-expand maybe-exp syntactic:expand-form))
  645. (define (expand-once . maybe-exp)
  646. (do-expand maybe-exp syntactic:expand))
  647. (define (do-expand maybe-exp expander)
  648. (let ((exp (if (null? maybe-exp)
  649. (focus-object)
  650. (car maybe-exp)))
  651. (env (package->environment (environment-for-commands))))
  652. (set-command-results!
  653. (list (schemify (expander exp env)
  654. env)))))