net-repl.ss
(module net-repl mzscheme

  (require
   (lib "thread.ss")
   (planet "parameter.ss" ("untyped" "unlib.plt" 1))
   (planet "exn.ss" ("untyped" "unlib.plt" 1)))

  (provide with-net-repl-port
           with-net-repl-timeout
           run-net-repl)
  
  (define-parameter net-repl-port
    9876
    (make-guard integer? "Natural number")
    with-net-repl-port)

  (define-parameter net-repl-timeout
    #f
    (make-guard (lambda (x)
                  (or (not x)
                      (>= x 0)))
                "Natural number or #f")
    with-net-repl-timeout)

  ;; net-repl-list : natural integer boolean -> tcp-listener
  ;;
  ;; Just like tcp-listen, but only listens on localhost for
  ;; security
  (define (net-repl-listen port-k max-allow-wait reuse?)
    (tcp-listen port-k max-allow-wait reuse? "127.0.0.1"))

  (define (net-repl-handler exn)
    (void))

  ;; net-repl-eval : ec -> (U sexp stx compiled) -> any
  ;;
  ;; Evals the given expression, and returns it value.  Uses
  ;; the current-eval parameter to eval all expressions,
  ;; except the expression (close) which calls the given
  ;; escape continuation
  (define net-repl-eval
    (let ([eval (current-eval)])
      (lambda (exit)
        (lambda (expr)
          (if (equal?
               (if (syntax? expr)
                   (syntax-object->datum expr)
                   expr)
               '(#%top-interaction close))
              (exit)
              (eval expr))))))
      
  
  ;; net-repl-connection : input-port output-port -> void
  (define (net-repl-connection ip op)
    (let/ec exit
      (parameterize
          ([current-input-port ip]
           [current-output-port op]
           [current-error-port op]
           [current-eval (net-repl-eval exit)])
        (read-eval-print-loop)))
    (close-input-port ip)
    (close-output-port op))

  ;; run-net-repl : () -> ()
  ;;
  ;; Runs the net-repl is a new thread
  (define (run-net-repl)
    (thread
     (lambda ()
       (run-server (net-repl-port)
                   net-repl-connection
                   (net-repl-timeout)
                   net-repl-handler
                   net-repl-listen))))
              


  )