pacman.scm 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. ; Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees. See file COPYING.
  2. ; PACkage-manipulation comMANds
  3. (add-sentinel! package-system-sentinel)
  4. (define (set-environment-for-commands! p)
  5. (set-interaction-environment! p)
  6. ;; (set-command-level-env! (command-level) p)
  7. )
  8. (define user-environment
  9. (user-context-accessor 'user-environment interaction-environment))
  10. (define set-user-environment!
  11. (user-context-modifier 'user-environment))
  12. (define-command-syntax 'in "<struct> [<command>]"
  13. "go to package, or execute single command in package"
  14. '(name &opt command))
  15. (define (in name . maybe-command)
  16. (if (and (not (null? maybe-command))
  17. (command-just-evaluates-symbol? (car maybe-command)))
  18. (set-command-results! (list (environment-ref (really-get-package name)
  19. (cadr (car maybe-command)))))
  20. (in-package (get-package name) maybe-command)))
  21. (define (command-just-evaluates-symbol? command)
  22. (and (pair? command)
  23. (eq? (car command) 'run)
  24. (symbol? (cadr command))))
  25. (define-command-syntax 'new-package "" "make and enter a new package"
  26. '())
  27. (define (new-package)
  28. (let ((p (make-simple-package (list (get-structure 'scheme))
  29. #t ;unstable?
  30. (get-reflective-tower (user-environment))
  31. #f)))
  32. (set-package-integrate?! p
  33. (package-integrate? (environment-for-commands)))
  34. (set-environment-for-commands! p)))
  35. (define (get-reflective-tower env) ;Returns promise of (eval . env)
  36. (environment-macro-eval (if (package? env)
  37. (package->environment env)
  38. env))) ;Mumble
  39. ; load-package
  40. (define-command-syntax 'load-package "<struct>" "load package's source code"
  41. '(name))
  42. (define (load-package name)
  43. (quietly-ensure-loaded (get-structure name)))
  44. (define-command-syntax 'reload-package "<struct>" "load package's source code again"
  45. '(name))
  46. (define (reload-package name)
  47. (let ((s (get-structure name)))
  48. (if (not (package-unstable? (structure-package s)))
  49. (error "read-only structure" s))
  50. (set-package-loaded?! (structure-package s) #f)
  51. (quietly-ensure-loaded s)))
  52. (define-command-syntax 'structure "<name> <interface>"
  53. "create new structure over the current package"
  54. '(name expression))
  55. (define (structure name interface-expression)
  56. (let* ((c (config-package))
  57. (p (environment-for-commands))
  58. (s (make-structure p
  59. (lambda ()
  60. (eval interface-expression c))
  61. name)))
  62. ;; (check-structure s)
  63. (environment-define! c name s)))
  64. (define-command-syntax 'open "<struct> ..." "open a structure"
  65. '(&rest expression))
  66. (define (open . specs)
  67. (for-each (lambda (spec)
  68. (let* ((c (config-package))
  69. (thunk (lambda ()
  70. (eval spec c)))
  71. (probe (thunk)))
  72. (if (structure? probe)
  73. (if (ensure-loaded-query probe)
  74. (package-open! (environment-for-commands) thunk)
  75. (error "structure not loaded" spec))
  76. (error "not a structure" spec))))
  77. specs))
  78. (define (ensure-loaded-query struct)
  79. (let ((p (structure-package struct)))
  80. (cond ((or (package-loaded? p)
  81. (and (null? (package-clauses p))
  82. (every (lambda (struct)
  83. (package-loaded? (structure-package struct)))
  84. (package-opens p))))
  85. #t)
  86. ((or (batch-mode?)
  87. (not (ask-before-loading?))
  88. (y-or-n? (if (structure-name struct)
  89. (string-append "Load structure "
  90. (symbol->string
  91. (structure-name struct)))
  92. "Load structure")
  93. #f))
  94. (quietly-ensure-loaded struct)
  95. #t)
  96. (else #f))))
  97. ; Loading or asking is controlled by the user context.
  98. (define ask-before-loading?
  99. (user-context-accessor 'ask-before-loading?
  100. (lambda () #f)))
  101. (define set-ask-before-loading?!
  102. (user-context-modifier 'ask-before-loading?))
  103. (add-setting 'ask-before-loading #t
  104. ask-before-loading?
  105. set-ask-before-loading?!
  106. "will ask before loading modules"
  107. "will not ask before loading modules")
  108. (define-command-syntax 'for-syntax "[<command>]"
  109. "go to current package's package for syntax"
  110. '(&opt command))
  111. (define (for-syntax . maybe-command)
  112. (in-package (cdr (force (get-reflective-tower (environment-for-commands))))
  113. maybe-command))
  114. ; ,user goes to the user initial environment.
  115. (define-command-syntax 'user "[<command>]" "go to user package"
  116. '(&opt command))
  117. (define (user . maybe-command)
  118. (in-package (user-environment) maybe-command))
  119. (define-command-syntax 'user-package-is "[<struct>]"
  120. "designate user package (for ,user command)"
  121. '(&opt name))
  122. (define (user-package-is . name-option)
  123. (set-user-environment! (if (null? name-option)
  124. (environment-for-commands)
  125. (get-package (car name-option)))))
  126. (define set-user-environment!
  127. (user-context-modifier 'user-environment))
  128. ; Configuration package (should there be ,load-config as well?)
  129. (define-command-syntax 'config "[<command>]" "go to configuration package"
  130. '(&opt command))
  131. (define (config . maybe-command)
  132. (in-package (config-package) maybe-command))
  133. (define-command-syntax 'config-package-is "<struct>"
  134. "designate configuration package"
  135. '(name))
  136. (define (config-package-is name)
  137. (set-config-package! (get-package name)))
  138. ; ,exec goes to the exec initial environment.
  139. (define-command-syntax 'exec "[<command>]" "go to command execution package"
  140. '(&opt command))
  141. (define (exec . maybe-command)
  142. (in-package (user-command-environment) maybe-command))
  143. ; ,undefine foo removes definition of foo from current package.
  144. (define-command-syntax 'undefine "<name>" "remove definition"
  145. '(name))
  146. (define (undefine name)
  147. (package-undefine! (interaction-environment) name))
  148. ; --------------------
  149. ; Auxiliaries for package commands
  150. (define (in-package p maybe-command)
  151. (if (null? maybe-command)
  152. (set-environment-for-commands! p)
  153. (with-interaction-environment p
  154. (lambda ()
  155. (let ((command (car maybe-command)))
  156. (if (procedure? command)
  157. (command)
  158. (execute-command (car maybe-command))))))))
  159. (define (quietly-ensure-loaded s)
  160. (if (load-noisily?)
  161. (ensure-loaded s)
  162. (silently (lambda ()
  163. (ensure-loaded s)))))
  164. ; The initial value used to be user-environment, but that required that the
  165. ; user context be created and initialized separately.
  166. (define config-package
  167. (user-context-accessor 'config-package interaction-environment))
  168. (define set-config-package!
  169. (user-context-modifier 'config-package))
  170. (define (get-package name)
  171. (let ((p (really-get-package name)))
  172. (if (package-unstable? p)
  173. p
  174. (error "read-only structure" p))))
  175. (define (really-get-package name)
  176. (let ((s (get-structure name)))
  177. (ensure-loaded-query s)
  178. (structure-package s)))
  179. (define (get-structure name)
  180. (let ((thing (environment-ref (config-package) name)))
  181. (cond ((structure? thing) thing)
  182. (else (error "not a structure" name thing)))))
  183. ; Main entry point, with package setup.
  184. (define (new-command-processor info commands built-in . meta-structs)
  185. ;; Argument to ,build command
  186. (lambda (arg)
  187. (call-with-values (lambda ()
  188. (make-user-envs commands built-in meta-structs))
  189. (lambda (env init-thunk)
  190. (with-interaction-environment
  191. env
  192. (lambda ()
  193. (start-command-processor arg
  194. (lambda ()
  195. (greet-user info))
  196. init-thunk)))))))
  197. (define (make-user-envs commands built-in meta-structs)
  198. (let* ((tower (make-reflective-tower
  199. eval
  200. (list (*structure-ref built-in 'scheme))
  201. 'user))
  202. (user (make-user-package built-in tower))
  203. (config-package (make-config-package 'config
  204. tower
  205. built-in
  206. meta-structs))
  207. (exec-package (make-exec-package commands tower built-in)))
  208. (values
  209. user
  210. (lambda ()
  211. (set-user-environment! user)
  212. (set-config-package! config-package)
  213. (set-user-command-environment! exec-package)))))
  214. ; User package
  215. (define (make-user-package built-in tower)
  216. (let* ((scheme-structure (*structure-ref built-in 'scheme))
  217. (user
  218. (make-simple-package (list scheme-structure)
  219. #t ;unstable?
  220. tower
  221. 'user)))
  222. (set-package-integrate?! user #f)
  223. user))
  224. ; Configuration package
  225. (define (make-config-package name tower built-in meta-structs)
  226. (let* ((module-system (*structure-ref built-in 'module-system))
  227. (config
  228. (make-simple-package (cons module-system
  229. (append meta-structs
  230. (list built-in)))
  231. #t ;unstable?
  232. tower
  233. name)))
  234. (set-reflective-tower-maker!
  235. config
  236. (lambda (clauses id)
  237. (if (null? clauses)
  238. tower ;?
  239. (delay (let ((p (eval `(a-package ((for-syntax ,id)) ,@clauses)
  240. config)))
  241. (quietly-ensure-loaded (make-structure
  242. p
  243. (lambda ()
  244. (make-simple-interface #f '()))
  245. 'for-syntax))
  246. (cons eval p))))))
  247. config))
  248. ; Exec package
  249. (define (make-exec-package commands tower built-in)
  250. (make-simple-package (list commands (*structure-ref built-in 'scheme))
  251. #t ;unstable?
  252. tower
  253. 'exec))
  254. ; for prompt string
  255. (define-method &environment-id-string ((env :package))
  256. (if (eq? env (user-environment))
  257. ""
  258. (if (symbol? (package-name env))
  259. (symbol->string (package-name env))
  260. (number->string (package-uid env)))))
  261. (define user-environment
  262. (user-context-accessor 'user-environment interaction-environment))
  263. ; This is only used by misc/remote.scm, which I don't know if anyone uses.
  264. ;
  265. ; Extract a package-specific evaluator from a package. Eventually, it
  266. ; would be nice if load, eval-from-file, eval-scanned-forms, and
  267. ; perhaps other things were also generic over different kinds of
  268. ; environments.
  269. ;
  270. ;(define funny-name/evaluator (string->symbol ".evaluator."))
  271. ;
  272. ;(define (set-package-evaluator! p evaluator)
  273. ; (package-define-funny! p funny-name/evaluator evaluator))
  274. ;
  275. ;(define (package-evaluator p)
  276. ; (or (get-funny (package->environment p) funny-name/evaluator) eval))
  277. ;
  278. ;(define-method &evaluate (form (env :package))
  279. ; ((package-evaluator env) form env))