remote.scm 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey, Jonathan Rees, Mike Sperber
  3. ; This is a small mock-up of the Cornell mobile robot system.
  4. ; It is not intended as a remote procedure call mechanism.
  5. ; ,load-config =scheme48/misc/packages.scm
  6. ; ,open remote
  7. ; To start a server, do
  8. ; (define sock (make-socket))
  9. ; (serve sock)
  10. ; To start a client, do
  11. ; (remote-repl "hostname" <number>)
  12. ; where <number> is the number displayed by the server when it starts up.
  13. ; Server side
  14. (define (note-structure-locations! s)
  15. (define (recur name env trail)
  16. (let ((b (generic-lookup env name)))
  17. (if (binding? b)
  18. (begin
  19. (note-location! (binding-place b))
  20. (let ((t (binding-static b)))
  21. (if (and (transform? t) (not (member t trail)))
  22. (let ((trail (cons t trail))
  23. (env (transform-env t)))
  24. (for-each (lambda (name)
  25. (recur name env trail))
  26. (transform-aux-names (binding-static b))))))))))
  27. (for-each-declaration (lambda (name package-name type)
  28. (recur package-name s '()))
  29. (structure-interface s)))
  30. (note-structure-locations! scheme-level-2)
  31. (define (make-socket)
  32. (call-with-values socket-server cons))
  33. (define (serve sock)
  34. (let ((port-number (car sock))
  35. (accept (cdr sock)))
  36. (display "Port number is ")
  37. (write port-number)
  38. (newline)
  39. (let ((in #f)
  40. (out #f))
  41. (dynamic-wind (lambda ()
  42. (call-with-values accept
  43. (lambda (i-port o-port)
  44. (display "Open") (newline)
  45. (set! in i-port)
  46. (set! out o-port))))
  47. (lambda ()
  48. (start-server in out))
  49. (lambda ()
  50. (if in (close-input-port in))
  51. (if out (close-output-port out)))))))
  52. (define (start-server in out)
  53. (let loop ()
  54. (let ((message (restore-carefully in)))
  55. (case (car message)
  56. ((run)
  57. (dump (run-carefully (cdr message))
  58. (lambda (c) (write-char c out))
  59. -1)
  60. (force-output out)
  61. (loop))
  62. ((eof) (cdr message))
  63. (else (error 'start-server "unrecognized message" message))))))
  64. (define (run-carefully template)
  65. (call-with-current-continuation
  66. (lambda (escape)
  67. (with-handler
  68. (lambda (c punt)
  69. (if (serious-condition? c)
  70. (escape (cons 'condition c))
  71. (punt)))
  72. (lambda ()
  73. (call-with-values (lambda ()
  74. (invoke-closure (make-closure template #f)))
  75. (lambda vals
  76. (cons 'values vals))))))))
  77. ; Client side
  78. (define (make-remote-eval in out)
  79. (lambda (form p)
  80. (compile-and-run-forms (list form)
  81. p
  82. #f
  83. (lambda (template)
  84. (dump (cons 'run template)
  85. (lambda (c) (write-char c out))
  86. -1)
  87. (force-output out)
  88. (let ((reply (restore-carefully in)))
  89. (case (car reply)
  90. ((values)
  91. (apply values (cdr reply)))
  92. ((condition)
  93. (signal-condition (cdr reply)))
  94. ((eof)
  95. (error 'make-remote-eval "eof on connection")))))
  96. #f)))
  97. (define (make-remote-package in out opens id)
  98. (let ((p (make-simple-package opens
  99. #t
  100. (syntactic-tower
  101. (package->environment (interaction-environment)))
  102. id)))
  103. (set-package-evaluator! p (make-remote-eval in out))
  104. p))
  105. (define (remote-repl host-name socket-port-number)
  106. (let ((in #f) (out #f))
  107. (dynamic-wind
  108. (lambda ()
  109. (call-with-values (lambda ()
  110. (socket-client host-name socket-port-number))
  111. (lambda (i-port o-port)
  112. (set! in i-port)
  113. (set! out o-port))))
  114. (lambda ()
  115. (with-interaction-environment (make-remote-package in out (list scheme) 'remote)
  116. (lambda () (command-loop list #f))))
  117. (lambda ()
  118. (if in (close-input-port in))
  119. (if out (close-output-port out))))))
  120. ; Common auxiliary
  121. (define (restore-carefully in)
  122. (call-with-current-continuation
  123. (lambda (exit)
  124. (restore (lambda ()
  125. (let ((c (read-char in)))
  126. (if (eof-object? c)
  127. (exit (cons 'eof c))
  128. c)))))))