1 prototypes define: #REPL &parents: {Cloneable} &slots:
2 {#parser -> Syntax Parser clone.
3 #printer -> String writer.
5 #namespace -> lobby newSubSpace.
9 #inputs -> (RingBuffer new &capacity: 10).
10 #results -> (RingBuffer new &capacity: 10)}.
12 REPL traits define: #Workspace &parents: {Namespace}.
13 "A separate Namespace type for REPL usage."
15 repl@(REPL traits) refreshWorkspace
17 repl namespace: (repl Workspace newDelegatingTo: lobby).
19 repl parser currentScope: (repl parser currentScope for: repl namespace).
22 repl@(REPL traits) prompt
24 'slate[' ; repl lineCount printString ; ']' ; repl basePrompt
27 repl@(REPL traits) newBasedOn: resource@(ExternalResource traits)
28 "Answer a new REPL targetting the specified resource and reset it."
29 [repl clone `>> [on: resource. reset. ]].
31 repl@(REPL traits) on: resource
32 "Re-target the REPL to the specified resource."
34 repl parser: (repl parser newOn: resource reader).
35 repl printer: resource writer.
36 repl resource: resource.
40 repl@(REPL traits) reset
41 "Clear out the line number and the evaluation result Collection."
48 _@here interpretHook: block
49 "The default set of restarts for any errors in a block of code."
54 Abort -> [| :_ | ^ Nil].
59 repl@(REPL traits) installMethods
60 "This defines a number of namespace methods for convenient REPL access
63 _@(repl namespace) repl "Answer the currently used REPL." [repl].
64 "Set/clear the editting mode of the Parser."
65 ns@(repl namespace) pasteMode [ns repl parser parseInteractively: False].
66 ns@(repl namespace) interactiveMode [ns repl parser parseInteractively: True].
67 (#repl findOn: {repl namespace})
68 ifNotNilDo: [| :m | repl namespace addSlot: #previousREPLMethod valued: m].
69 "Define quick methods for the last 5 evaluation results."
70 ns@(repl namespace) it [ns it1].
71 ns@(repl namespace) it1 [ns repl results first].
72 ns@(repl namespace) it2 [ns repl results second].
73 ns@(repl namespace) it3 [ns repl results third].
74 ns@(repl namespace) it4 [ns repl results fourth].
75 ns@(repl namespace) it5 [ns repl results fifth].
77 ns@(repl namespace) in: ns [ns atSlotNamed: #parentNamespace put: ns].
79 ns@(repl namespace) inform: message &target: r
80 "A simple way to print a message onto an ExternalResource (by default the Console)."
81 [r `defaultsTo: ns repl resource.
82 r writer ; message ; '\n'.
85 ns@(repl namespace) print: obj &target: r
86 [r `defaultsTo: repl resource.
87 obj printOn: r writer.
91 ns@(repl namespace) query: message &target: r
92 "A simple way to ask input of the user on an ExternalResource (by default
93 the Console) and return a Slate String response."
95 r `defaultsTo: ns repl resource.
98 [response: (r interactor upTo: $\n).
99 response isEmpty] whileTrue. "Grabs the next line when it's available."
103 ns@(repl namespace) confirm: message &target: r
104 "A simple way to ask a Boolean question of the user on an ExternalResource
105 (by default the Console) and return a Slate Boolean answer."
107 response: (ns query: message ; ' (y/n) ') toLowercase.
108 {'y'. 'yes'} anySatisfy: [| :option | option = response]].
110 ns@(repl namespace) doubleConfirm: message &target: r
112 response: (ns confirm: message &target: r).
113 response /\ [ns confirm: 'Are you sure?' &target: r]
116 ns@(repl namespace) help &target: r
118 r `defaultsTo: ns repl resource.
119 r 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'
120 ; 'it\n\tAnswers the last result.\n'
121 ; 'itN\n\tAnswers the result from N (1..5) expressions ago in the history.\n'
122 ; 'repl\n\tAnswers the current REPL and its properties.\n'
123 ; 'pasteMode\n\t(Default) Evaluate only when a finished expression is followed by a period and newline.\n'
124 ; 'interactiveMode\n\tEvaluate when newline is entered and the expression is complete.\n'
125 ; 'inspect: obj\n\tStarts the interactive travelling inspector.\n'
126 ; 'inform: \'message\'\n\tPrints a message on a single line.\n'
127 ; 'query: \'message\'\n\tPrints a message, waiting on and answering a user response.\n'
128 ; 'confirm: \'message\'\n\tPrints a question on a single line and answering a user boolean response.\n'
129 ; 'resetOnStartup\n\tClears the history and line number on fresh runs of the VM.\n'
130 ; 'help\n\tPrints this helpful message.\n'.
133 ns@(repl namespace) ? [ns help].
134 ns@(repl namespace) ? obj [ns helpFor: obj].
138 repl@(REPL traits) removeMethods
139 "This removes methods defined in installMethods."
141 {#repl. #pasteMode. #interactiveMode. #it. #it1. #it2. #it3. #it4. #it5.
142 #inform:. #query:. #confirm:. #help}
144 (sel findOn: {repl namespace})
146 [| :m | m removeFrom: {repl namespace}]]
149 repl@(REPL traits) enter
150 "Sets up the convenient namespace methods and runs the interactive loop.
151 This does not normally exit unless there is a serious error."
153 [repl refreshWorkspace.
154 repl parser parseInteractively: True.
155 [repl on: repl resource.
156 repl lineCount: repl lineCount + 1.
157 repl printer ; repl prompt.
162 [expr: repl parser next]
163 on: Stream Exhaustion
164 do: [| :c | c stream == repl resource reader ifTrue:
165 [repl printer ; '\n'. ^ Nil]].
166 repl inputs addFirst: expr.
167 result: ([expr evaluateIn: repl namespace] on: SeriousCondition do:
169 repl noviceMode ifTrue:
170 [c describeOn: repl printer.
172 repl results addFirst: result.
173 [result printOn: repl printer] on: SeriousCondition do:
175 repl printer newLine.
176 warn: result printName ; ' (Printing failed)'.
178 repl printer newLine.
180 "repl namespace interpretHook: [currentProcess run &limit: 1000]"]
181 loop] ensure: [repl removeMethods].
185 repl@(REPL traits) completionsFor: word
186 "Answers an Array of all the possible complete Symbols defined in the system
187 which the given word is a valid prefix of.
188 TODO: Consult the recent literal frames for names.
189 TODO: sort the results by some suitable precedence."
192 globals Symbols keysDo:
193 [| :key | (word isPrefixOf: key) ifTrue: [result nextPut: key]]]
197 repl@(REPL traits) start &resource: r
198 "Enter a new REPL instance on the resource."
200 r `defaultsTo: repl resource.
201 (repl newBasedOn: r) enter
204 repl@(REPL traits) resetOnStartup
205 "Adds a handler for Image startup to reset the REPL."
206 [Image startupActions at: repl put: [repl reset]].