1 prototypes define: #REPL &parents: {Cloneable} &slots: {
2 #parser -> (Parser newOn: '').
3 #printer -> String writer.
4 #resource -> DebugConsole.
5 #originalNamespace -> lobby.
6 #namespace -> lobby newSubSpace.
10 #inputs -> (RingBuffer new &capacity: 10).
11 #results -> (RingBuffer new &capacity: 10).
14 ns@(Namespace traits) inform: message &target
16 target `defaultsTo: REPL resource.
17 target writer ; (rest isEmpty ifTrue: [message] ifFalse: [#formatting sendTo: {message} ; rest]) ; '\n'.
21 ns@(Namespace traits) print: obj &target
23 target `defaultsTo: REPL resource.
24 obj printOn: target writer.
29 ns@(Namespace traits) query: message &target
30 "A simple way to ask input of the user on an ExternalResource (by default
31 the Console) and return a Slate String response."
33 target `defaultsTo: REPL resource.
34 target writer ; message.
36 "Grabs the next line when it's available."
37 [(response ::= target interactor upTo: $\n) isEmpty] whileTrue.
42 ns@(Namespace traits) confirm: message &target
43 "A simple way to ask a Boolean question of the user on an ExternalResource
44 (by default the Console) and return a Slate Boolean answer."
46 response ::= (ns query: message ; ' (y/n) ') toLowercase.
47 {'y'. 'yes'} anySatisfy: [| :option | option = response]
50 ns@(Namespace traits) doubleConfirm: message &target
52 (response ::= ns confirm: message &target: target)
53 /\ [ns confirm: 'Are you sure?' &target: target]
56 REPL traits NamespaceMethods ::= Dictionary new.
57 [| :assoc | REPL NamespaceMethods at: assoc key put: assoc value] for: {
58 #pasteMode -> [| :ns | ns repl parser parseInteractively := False].
59 #interactiveMode -> [| :ns | ns repl parser parseInteractively := True].
60 #it -> [| :ns | ns it1].
61 #it1 -> [| :ns | ns repl results first].
62 #it2 -> [| :ns | ns repl results second].
63 #it3 -> [| :ns | ns repl results third].
64 #it4 -> [| :ns | ns repl results fourth].
65 #it5 -> [| :ns | ns repl results fifth].
67 #in: -> [| :nsold :ns | ns atSlotNamed: #parentNamespace := ns].
69 #? -> [| :ns :obj | ns helpFor: obj].
73 target `defaultsTo: ns repl resource.
74 target writer ; 'The REPL is an interactive evaluator that parses expressions and prints their results back. It also keeps a return-value history and interaction messages:\n'
75 ; 'it\n\tAnswers the last result.\n'
76 ; 'itN\n\tAnswers the result from N (1..5) expressions ago in the history.\n'
77 ; 'repl\n\tAnswers the current REPL and its properties.\n'
78 ; 'pasteMode\n\t(Default) Evaluate only when a finished expression is followed by a period and newline.\n'
79 ; 'interactiveMode\n\tEvaluate when newline is entered and the expression is complete.\n'
80 ; 'inspect: obj\n\tStarts the interactive travelling inspector.\n'
81 ; 'inform: \'message\'\n\tPrints a message on a single line.\n'
82 ; 'query: \'message\'\n\tPrints a message, waiting on and answering a user response.\n'
83 ; 'confirm: \'message\'\n\tPrints a question on a single line and answering a user boolean response.\n'
84 ; 'resetOnStartup\n\tClears the history and line number on fresh runs of the VM.\n'
85 ; 'help\n\tPrints this helpful message.\n'.
89 REPL traits define: #Workspace &parents: {Namespace}.
90 "A separate Namespace type for REPL usage."
92 repl@(REPL traits) installMethods
93 "This defines a number of namespace methods for convenient REPL access
96 _@(repl namespace) repl "Answer the currently used REPL." [repl].
97 ns@(repl namespace) ? [ns help].
98 repl NamespaceMethods keysAndValuesDo:
99 [| :selector :method | method asMethod: selector on: {repl namespace}].
102 repl@(REPL traits) removeMethods
103 "This removes methods defined in installMethods."
106 (sel findOn: {repl namespace}) ifNotNilDo:
107 [| :m | m removeFrom: {repl namespace}]] for: repl NamespaceMethods keySet
110 repl@(REPL traits) refreshWorkspace
112 repl namespace := repl Workspace newDelegatingTo: repl originalNamespace.
114 repl parser currentScope := repl parser currentScope for: repl namespace.
117 repl@(REPL traits) prompt
119 'slate[%@]%s' formatting, repl lineCount, repl basePrompt
122 repl@(REPL traits) newBasedOn: resource@(ExternalResource traits)
123 "Answer a new REPL targetting the specified resource and reset it."
124 [repl clone `>> [on: resource. reset. ]].
126 repl@(REPL traits) on: resource
127 "Re-target the REPL to the specified resource."
129 repl resource := resource.
133 repl@(REPL traits) refreshIO
135 repl parser := repl parser newOn: repl resource reader.
136 repl printer := repl resource writer.
139 repl@(REPL traits) reset
140 "Clear out the line number and the evaluation result Collection."
148 _@here interpretHook: block
149 "The default set of restarts for any errors in a block of code."
154 Abort -> [| :_ | ^ Nil].
159 repl@(REPL traits) enter
160 "Sets up the convenient namespace methods and runs the interactive loop.
161 This does not normally exit unless there is a serious error."
163 [repl refreshWorkspace.
164 [repl on: repl resource.
166 repl printer ; repl prompt.
168 repl namespace interpretHook:
170 [expr := repl parser next] on: Stream Exhaustion
171 do: [| :c | c stream == repl resource reader ifTrue: [^ Nil]].
172 repl inputs addFirst: expr.
173 result ::= [expr evaluateIn: repl namespace] on: SeriousCondition do:
175 repl noviceMode ifTrue:
176 [c describeOn: repl printer.
178 repl results addFirst: result.
179 [result printOn: repl printer] on: SeriousCondition do:
181 repl printer newLine.
182 warn: result printName ; ' (Printing failed)'.
184 repl printer newLine.
186 "repl namespace interpretHook: [currentProcess run &limit: 1000]"]
187 loop] ensure: [repl removeMethods. Image startupActions removeKey: repl].
191 repl@(REPL traits) completionsFor: word
192 "Answers an Array of all the possible complete Symbols defined in the system
193 which the given word is a valid prefix of.
194 TODO: Consult the recent literal frames for names.
195 TODO: sort the results by some suitable precedence."
198 globals Symbols keysDo:
199 [| :key | (word isPrefixOf: key) ifTrue: [result nextPut: key]]]
203 repl@(REPL traits) start &namespace: ns &resource: r
204 "Enter a new REPL instance on the resource."
206 (repl newBasedOn: (r `defaultsTo: repl resource)) `>> [namespace := ns. enter]
209 repl@(REPL traits) resetOnStartup
210 "Adds a handler for Image startup to reset the REPL."
211 [Image startupActions at: repl := [repl reset]].
213 ns@(Namespace traits) newREPL
215 REPL start &namespace: ns