atomo-0.4: prelude/repl.atomo
{ *repl* = this
incomplete-input = ""
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 :=
{ parsed =
{ (incomplete-input .. s) parse-expressions
} with-restarts: {
incomplete ->
{ *repl* incomplete-input = incomplete-input .. s .. "\n"
[]
} call
} bind: {
@(parse-error: (@(unexpected: e) . _) at: _) ->
if: (e in?: ["", "ending"])
then: { restart: 'incomplete }
else: { *repl* incomplete-input = "" }
@(parse-error: _ at: _) ->
(*repl* incomplete-input = "")
}
parsed match: {
[] -> @ok
es ->
{ *repl* incomplete-input = ""
(evaluate-all: es in: env) show print
} call
}
} call
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 to: 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: (
if: incomplete-input empty?
then: { "[" .. frame show .. "]> " }
else: { "." .. ($. repeat: frame show length) .. ".. " }
)
@loop ->
(super frame = frame + 1) when: incomplete-input empty?
@(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