pacman.scm 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey, Jonathan Rees, Mike Sperber, Robert Ransom,
  3. ; Marcus Crestani, Sebastian Rheinnecker
  4. ; PACkage-manipulation comMANds
  5. (add-sentinel! package-system-sentinel)
  6. (define (set-environment-for-commands! p)
  7. (set-interaction-environment! p)
  8. ;; (set-command-level-env! (command-level) p)
  9. )
  10. (define user-environment
  11. (user-context-accessor 'user-environment interaction-environment))
  12. (define set-user-environment!
  13. (user-context-modifier 'user-environment))
  14. (define-command-syntax 'in "<struct> [<command>]"
  15. "go to package, or execute single command in package"
  16. '(name &opt command))
  17. (define (in name . maybe-command)
  18. (if (and (not (null? maybe-command))
  19. (command-just-evaluates-symbol? (car maybe-command)))
  20. (set-command-results! (list (environment-ref (really-get-package name)
  21. (cadr (car maybe-command)))))
  22. (in-package (get-package name) maybe-command)))
  23. (define (command-just-evaluates-symbol? command)
  24. (and (pair? command)
  25. (eq? (car command) 'run)
  26. (symbol? (cadr command))))
  27. (define-command-syntax 'new-package "[<struct> ...]" "make and enter a new package"
  28. '(&rest expression))
  29. (define (new-package . maybe-opens)
  30. (let* ((opens-thunk
  31. (if (pair? maybe-opens)
  32. list
  33. (lambda ()
  34. (list (get-structure 'scheme)))))
  35. (p (make-package opens-thunk
  36. (lambda () '())
  37. #t ;unstable?
  38. (get-syntactic-tower (user-environment))
  39. "" ;file containing DEFINE-STRUCTURE form
  40. '() ;clauses
  41. #f ;uid
  42. #f))) ;name
  43. (set-package-integrate?! p
  44. (package-integrate? (environment-for-commands)))
  45. (set-environment-for-commands! p)
  46. (for-each open maybe-opens)))
  47. (define (get-syntactic-tower env) ;Returns promise of (eval . env)
  48. (comp-env-macro-eval (if (package? env)
  49. (package->environment env)
  50. env))) ;Mumble
  51. ; load-package
  52. (define-command-syntax 'load-package "<struct>" "load package's source code"
  53. '(name))
  54. (define (load-package name)
  55. (quietly-ensure-loaded (get-structure name)))
  56. (define-command-syntax 'reload-package "<struct>" "load package's source code again"
  57. '(name))
  58. (define (reload-package name)
  59. (let ((s (get-structure name)))
  60. (if (not (package-unstable? (structure-package s)))
  61. (assertion-violation 'reload-package "read-only structure" s))
  62. (set-package-loaded?! (structure-package s) #f)
  63. (quietly-ensure-loaded s)))
  64. (define-command-syntax 'structure "<name> <interface>"
  65. "create new structure over the current package"
  66. '(name expression))
  67. (define (structure name interface-expression)
  68. (let* ((c (config-package))
  69. (p (environment-for-commands))
  70. (s (make-structure p
  71. (lambda ()
  72. (eval interface-expression c))
  73. name)))
  74. ;; (check-structure s)
  75. (environment-define! c name s)))
  76. (define-command-syntax 'open "<struct> ..." "open a structure"
  77. '(&rest expression))
  78. (define (open . specs)
  79. (for-each (lambda (spec)
  80. (let* ((c (config-package))
  81. (thunk (lambda ()
  82. (eval spec c)))
  83. (probe (thunk)))
  84. (if (structure? probe)
  85. (if (ensure-loaded-query probe)
  86. (package-open! (environment-for-commands) thunk)
  87. (assertion-violation 'open "structure not loaded" spec))
  88. (assertion-violation 'open "not a structure" spec))))
  89. specs))
  90. (define (ensure-loaded-query struct)
  91. (let ((p (structure-package struct)))
  92. (cond ((or (package-loaded? p)
  93. (and (null? (package-clauses p))
  94. (every (lambda (struct)
  95. (package-loaded? (structure-package struct)))
  96. (package-opens p))))
  97. #t)
  98. ((or (batch-mode?)
  99. (not (ask-before-loading?))
  100. (y-or-n? (if (structure-name struct)
  101. (string-append "Load structure "
  102. (symbol->string
  103. (structure-name struct)))
  104. "Load structure")
  105. #f))
  106. (quietly-ensure-loaded struct)
  107. #t)
  108. (else #f))))
  109. ; Loading or asking is controlled by the user context.
  110. (define ask-before-loading?
  111. (user-context-accessor 'ask-before-loading?
  112. (lambda () #f)))
  113. (define set-ask-before-loading?!
  114. (user-context-modifier 'ask-before-loading?))
  115. (add-setting 'ask-before-loading #t
  116. ask-before-loading?
  117. set-ask-before-loading?!
  118. "will ask before loading modules"
  119. "will not ask before loading modules")
  120. (define-command-syntax 'for-syntax "[<command>]"
  121. "go to current package's package for syntax"
  122. '(&opt command))
  123. (define (for-syntax . maybe-command)
  124. (in-package (cdr (force (get-syntactic-tower (environment-for-commands))))
  125. maybe-command))
  126. ; ,user goes to the user initial environment.
  127. (define-command-syntax 'user "[<command>]" "go to user package"
  128. '(&opt command))
  129. (define (user . maybe-command)
  130. (in-package (user-environment) maybe-command))
  131. (define-command-syntax 'user-package-is "[<struct>]"
  132. "designate user package (for ,user command)"
  133. '(&opt name))
  134. (define (user-package-is . name-option)
  135. (set-user-environment! (if (null? name-option)
  136. (environment-for-commands)
  137. (get-package (car name-option)))))
  138. (define set-user-environment!
  139. (user-context-modifier 'user-environment))
  140. ; Configuration package (should there be ,load-config as well?)
  141. (define-command-syntax 'config "[<command>]" "go to configuration package"
  142. '(&opt command))
  143. (define (config . maybe-command)
  144. (in-package (config-package) maybe-command))
  145. (define-command-syntax 'config-package-is "<struct>"
  146. "designate configuration package"
  147. '(name))
  148. (define (config-package-is name)
  149. (set-config-package! (get-package name)))
  150. ; ,exec goes to the exec initial environment.
  151. (define-command-syntax 'exec "[<command>]" "go to command execution package"
  152. '(&opt command))
  153. (define (exec . maybe-command)
  154. (in-package (user-command-environment) maybe-command))
  155. ; ,undefine foo removes definition of foo from current package.
  156. (define-command-syntax 'undefine "<name>" "remove definition"
  157. '(name))
  158. (define (undefine name)
  159. (package-undefine! (interaction-environment) name))
  160. ; ,set-reader changes the reader of the current package.
  161. (define-command-syntax 'set-reader "<reader>" "sets the current reader"
  162. '(expression))
  163. (define (set-reader reader-expression)
  164. (let* ((p (environment-for-commands))
  165. (r (eval reader-expression p)))
  166. (set-reader! p r)
  167. (set-package-reader! p r)))
  168. ; --------------------
  169. ; Auxiliaries for package commands
  170. (define (in-package p maybe-command)
  171. (if (null? maybe-command)
  172. (set-environment-for-commands! p)
  173. (with-interaction-environment p
  174. (lambda ()
  175. (let ((command (car maybe-command)))
  176. (if (procedure? command)
  177. (command)
  178. (execute-command (car maybe-command))))))))
  179. (define (quietly-ensure-loaded s)
  180. (if (load-noisily?)
  181. (ensure-loaded s)
  182. (silently (lambda ()
  183. (ensure-loaded s)))))
  184. ; The initial value used to be user-environment, but that required that the
  185. ; user context be created and initialized separately.
  186. (define config-package
  187. (user-context-accessor 'config-package interaction-environment))
  188. (define set-config-package!
  189. (user-context-modifier 'config-package))
  190. (define (get-package name)
  191. (let ((p (really-get-package name)))
  192. (if (package-unstable? p)
  193. p
  194. (assertion-violation 'get-package "read-only structure" p))))
  195. (define (really-get-package name)
  196. (let ((s (get-structure name)))
  197. (ensure-loaded-query s)
  198. (structure-package s)))
  199. (define (get-structure name)
  200. (let ((thing (environment-ref (config-package) name)))
  201. (cond ((structure? thing) thing)
  202. (else (assertion-violation 'get-structure "not a structure" name thing)))))
  203. ; Main entry point, with package setup.
  204. (define (new-command-processor info commands built-in . meta-structs)
  205. ;; Argument to ,build command
  206. (lambda (arg)
  207. (call-with-values (lambda ()
  208. (make-user-envs commands built-in meta-structs))
  209. (lambda (env init-thunk)
  210. (with-interaction-environment
  211. env
  212. (lambda ()
  213. (start-command-processor arg
  214. (lambda ()
  215. (greet-user info))
  216. init-thunk)))))))
  217. (define (make-user-envs commands built-in meta-structs)
  218. (let* ((tower (make-syntactic-tower
  219. eval
  220. (list (*structure-ref built-in 'scheme))
  221. 'user))
  222. (user (make-user-package built-in tower))
  223. (config-package (make-config-package 'config
  224. tower
  225. built-in
  226. meta-structs))
  227. (exec-package (make-exec-package commands tower built-in)))
  228. (values
  229. user
  230. (lambda ()
  231. (set-user-environment! user)
  232. (set-config-package! config-package)
  233. (set-user-command-environment! exec-package)))))
  234. ; User package
  235. (define (make-user-package built-in tower)
  236. (let* ((scheme-structure (*structure-ref built-in 'scheme))
  237. (user
  238. (make-simple-package (list scheme-structure)
  239. #t ;unstable?
  240. tower
  241. 'user)))
  242. (set-package-integrate?! user #f)
  243. user))
  244. ; Configuration package
  245. (define (make-config-package name tower built-in meta-structs)
  246. (let* ((module-system (*structure-ref built-in 'module-system))
  247. (config
  248. (make-simple-package (cons module-system
  249. (append meta-structs
  250. (list built-in)))
  251. #t ;unstable?
  252. tower
  253. name)))
  254. (set-syntactic-tower-maker!
  255. config
  256. (lambda (clauses id)
  257. (if (null? clauses)
  258. tower ;?
  259. (delay (let ((p (eval `(a-package ((for-syntax ,id)) ,@clauses)
  260. config)))
  261. (quietly-ensure-loaded (make-structure
  262. p
  263. (lambda ()
  264. (make-simple-interface #f '()))
  265. 'for-syntax))
  266. (cons eval p))))))
  267. (set-reader! config read)
  268. config))
  269. ; Exec package
  270. (define (make-exec-package commands tower built-in)
  271. (make-simple-package (list commands
  272. ;; we want the `load' from `usual-commands'
  273. (make-modified-structure (*structure-ref built-in 'scheme)
  274. '((hide load))))
  275. #t ;unstable?
  276. tower
  277. 'exec))
  278. ; for prompt string
  279. (define-method &environment-id-string ((env :package))
  280. (if (eq? env (user-environment))
  281. ""
  282. (if (symbol? (package-name env))
  283. (symbol->string (package-name env))
  284. (number->string (package-uid env)))))
  285. (define user-environment
  286. (user-context-accessor 'user-environment interaction-environment))
  287. ; This is only used by misc/remote.scm, which I don't know if anyone uses.
  288. ;
  289. ; Extract a package-specific evaluator from a package. Eventually, it
  290. ; would be nice if load, eval-from-file, eval-scanned-forms, and
  291. ; perhaps other things were also generic over different kinds of
  292. ; environments.
  293. ;
  294. ;(define funny-name/evaluator (string->symbol ".evaluator."))
  295. ;
  296. ;(define (set-package-evaluator! p evaluator)
  297. ; (package-define-funny! p funny-name/evaluator evaluator))
  298. ;
  299. ;(define (package-evaluator p)
  300. ; (or (get-funny (package->environment p) funny-name/evaluator) eval))
  301. ;
  302. ;(define-method &evaluate (form (env :package))
  303. ; ((package-evaluator env) form env))
  304. ; Show information about packages
  305. ;; prints known packages
  306. (define-command-syntax 'show-known-packages ""
  307. "shows all known packages" '())
  308. (define (show-known-packages)
  309. (for-each (lambda (entry)
  310. (write entry)
  311. (newline))
  312. (filter symbol? (table->entry-list package-name-table))))
  313. ;; prints exported names
  314. (define-command-syntax 'show-interface "<struct> ..."
  315. "shows exported names of the given structures" '(&rest form))
  316. (define (show-interface . structs)
  317. (if (null? structs)
  318. '?
  319. (let ((names '()))
  320. (for-each
  321. (lambda (struct)
  322. (let ((probe (and (package-lookup (config-package) struct)
  323. (eval struct (config-package)))))
  324. (if (structure? probe)
  325. (begin
  326. (for-each-declaration
  327. (lambda (name package-name type)
  328. (if (not (assq name names)) ; compound signatures...
  329. (set! names (cons (cons name type)
  330. names))))
  331. (structure-interface probe))
  332. (for-each (lambda (pair)
  333. (let ((name (car pair))
  334. (type (cdr pair)))
  335. (write name)
  336. (write-char #\space)
  337. (write (careful-type->sexp type))
  338. (newline)))
  339. names))
  340. (begin
  341. (display "[")
  342. (write struct)
  343. (display " not found]")
  344. (write-char #\space)
  345. (newline)))))
  346. structs))))
  347. (define (careful-type->sexp thing)
  348. (cond ((not thing) 'undefined)
  349. ((or (symbol? thing)
  350. (null? thing)
  351. (number? thing))
  352. thing) ;?
  353. ((pair? thing) ;e.g. (variable #{Type :value})
  354. (cons (careful-type->sexp (car thing))
  355. (careful-type->sexp (cdr thing))))
  356. (else
  357. (type->sexp thing #t))))