darcsden :: dnolen -> atomo -> blob

atomo programming languagehttp://atomo-lang.org/

root / prelude / repl.atomo

{ evaluate-all: [] in: _ := error: @no-expressions
  evaluate-all: [e] in: t := t evaluate: e
  evaluate-all: (e . es) in: t :=
    { t evaluate: e
      evaluate-all: es in: t
    } call

  do-input: (s: String) in: env :=
    s parse-expressions match: {
      [] -> @ok
      es -> (evaluate-all: es in: env) show print
    }

  get-value: t :=
    (interaction: "enter value: ") parse-expressions match: {
      [] -> get-value: t
      es -> evaluate-all: es in: t
    }

  get-n-values: 0 = []
  get-n-values: n :=
    (get-value: Lobby) . (get-n-values: (n - 1))

  repl-debugger =
    Object clone do:
      { run: e :=
          { Restart show-options-for: e

            { basic-repl } bind: {
              @prompt ->
                restart: 'use-prompt with: ["[!]> "]

              @(special: n) ->
                when: (n all?: @digit?) do: {
                  r = Restart get: (n as: Integer)
                  r jump: (get-n-values: r action arguments length)
                }
            }
          } call
      }

  (env: Object) basic-repl :=
    { prompt =
        { signal: @prompt; "> " } with-restarts: {
          use-prompt -> { p | p }
        }

      in =
        { interaction: prompt } handle: {
          @end-of-input -> { signal: @quit; "" } call
          @interrupt -> { signal: @quit; "" } call
        }

      in match: {
        $: . name ->
          signal: @(special: name)

        source ->
          { try :=
              { do-input: source in: env } with-restarts: {
                retry -> try
                abort -> @ok
              }

            try
          } call
      }

      signal: @loop
    } repeat

  (env: Object) repl :=
    { stop |
      with: *debugger* as: repl-debugger do: {
        frame = 0

        { env basic-repl } bind: {
          @prompt ->
            restart: 'use-prompt with: ["[" .. frame show .. "]> "]

          @loop -> (super frame = frame + 1)

          @(special: "h") ->
            ":h\thelp" print

          @quit ->
            { ask :=
                { "really quit? (y/n) " display
                  { read-char } (after: { "" print }) match: {
                    $y -> stop yield
                    $n -> @ok
                    _ -> ask
                  }
                } call

              ask
            } call
        }
      }
    } call/cc
} call