--- a/ReadEvalPrintLoop.st Wed Oct 26 23:35:39 2016 +0100
+++ b/ReadEvalPrintLoop.st Fri Nov 18 20:48:04 2016 +0000
@@ -15,8 +15,9 @@
Object subclass:#ReadEvalPrintLoop
instanceVariableNames:'inputStream outputStream errorStream compiler prompt
- doChunkFormat traceFlag timingFlag printFlag exitAction
- currentDirectory'
+ doChunkFormat traceFlag timingFlag profilingFlag printFlag
+ exitAction currentDirectory lastEditedClass lastEditedSelector
+ editorCommand'
classVariableNames:''
poolDictionaries:''
category:'System-Support'
@@ -42,20 +43,27 @@
"
A simple read-eval-print loop for non-GUI or stscript operation.
Invoked, for example if stx is started with a --repl argument.
-.
+
A line starting with '?' shows the usage message.
Lines starting with '#' are directives:
- #exit - exit the rep-loop
-
+ #exit - exit the rep-loop
+ type '?' to see more.
+
The input can be in one of two formats:
- 1) traditional chunk format (bang-separated chunks, bangs duplicated)
- this is the traditional fileIn format, as generated by fileOut from the browser
+ 1) traditional chunk format (bang-separated chunks, bangs duplicated)
+ this is the traditional fileIn format, as generated by fileOut from the browser
- 2) interactive line mode. Chunks are any number of lines up to either an empty line or
- a line ending in a period. This is more useful for an interactive REPL, where statements/expressions
- are entered linewise by a user.
+ 2) interactive line mode. Chunks are any number of lines up to either an empty line or
+ a line ending in a period. This is more useful for an interactive REPL, where statements/expressions
+ are entered linewise by a user.
The input can is switched to non-chunk format whenever a line with a '#' in the first column appears.
+
+ Try it (but only if you have a console):
+ Smalltalk readEvalPrintLoop
+
+ [Author:]
+ Claus Gittinger
"
! !
@@ -83,6 +91,27 @@
"Created: / 07-12-2006 / 18:24:04 / cg"
!
+editorCommand
+ |editor|
+
+ (editor := editorCommand) isNil ifTrue:[
+ editor := OperatingSystem getEnvironment:'STX_EDITOR'.
+ editor isNil ifTrue:[
+ editor := OperatingSystem getEnvironment:'EDITOR'.
+ editor isNil ifTrue:[
+ OperatingSystem isMSWINDOWSlike ifTrue:[
+ editor := 'notepad'.
+ ] ifFalse:[
+ editor := 'vi'.
+ ].
+ ].
+ ].
+ ].
+ ^ editor
+
+ "Created: / 08-11-2016 / 22:45:22 / cg"
+!
+
error:aStream
"assign an error stream"
@@ -188,6 +217,152 @@
"Created: / 07-12-2006 / 19:04:50 / cg"
!
+cmd_debug:lineStream
+ MiniDebugger enter.
+!
+
+cmd_edit:lineStream
+ "edit a class or selector in an external editor"
+
+ |errStream classOrMethodName cls methodName selector
+ code isNewClass editFullClass tmpFile modifiedTime|
+
+ errStream := self errorStream.
+
+ isNewClass := editFullClass := false.
+
+ lineStream skipSeparators.
+ lineStream atEnd ifTrue:[
+ cls := lastEditedClass.
+ methodName := lastEditedSelector.
+ ] ifFalse:[
+
+ classOrMethodName := lineStream
+ upToElementForWhich:[:ch |
+ ch isLetterOrDigit not and:[ch ~~ $_]
+ ].
+ "/
+ (classOrMethodName isUppercaseFirst) ifTrue:[
+ (cls := Smalltalk classNamed:classOrMethodName) isNil ifTrue:[
+ errStream show:'edit: no such class: ',classOrMethodName,' ; create (y/n)? '.
+ (self inputStream nextLine withoutSeparators startsWith:'y') ifFalse:[^ self].
+ isNewClass := true.
+ code :=
+'"/ change the code as required, then save and exit the editor.
+"/ To cancel this edit, leave the editor WITHOUT saving.
+"/
+
+Object
+ subclass:#%1
+ instanceVariableNames:''''
+ classVariableNames:''''
+ poolDictionaries:''''
+ category:''user classes''
+' bindWith:classOrMethodName.
+ ] ifFalse:[
+ lineStream skipSeparators.
+ lineStream atEnd ifFalse:[
+ methodName := lineStream upToSeparator.
+ ].
+ ].
+ ] ifFalse:[
+ methodName := classOrMethodName
+ ].
+ ].
+
+ isNewClass ifFalse:[
+ cls := cls ? lastEditedClass.
+ cls isNil ifTrue:[
+ errStream showCR:'edit usage:'.
+ errStream showCR:' #edit className selector'.
+ errStream showCR:' #edit className '.
+ errStream showCR:' #edit selector (class as in previous edit)'.
+ errStream showCR:' #edit (class/method as in previous edit)'.
+ ^ self.
+ ].
+ lastEditedClass := cls.
+ lastEditedSelector := methodName.
+
+ methodName isNil ifTrue:[
+ editFullClass := true.
+ code := cls source asString
+ ] ifFalse:[
+ ((selector := methodName asSymbolIfInterned) isNil
+ or:[ (cls implements:selector) not]) ifTrue:[
+ errStream show:('"',methodName,'" is a new method; create (y/n)? ').
+ (self inputStream nextLine withoutSeparators startsWith:'y') ifFalse:[^ self].
+ code :=
+'"/ change the code as required, then save and exit the editor.
+"/ To cancel this edit, leave the editor WITHOUT saving.
+
+%1
+ "this is a new method"
+ self halt
+' bindWith:methodName.
+ ] ifFalse:[
+ code := (cls compiledMethodAt:selector) source.
+ ].
+ ].
+ ].
+
+ [
+ |ok cmd|
+
+ tmpFile := Filename newTemporary.
+ tmpFile contents:code.
+ modifiedTime := tmpFile modificationTime.
+
+ cmd := '%1 "%2"'.
+ OperatingSystem isUNIXlike ifTrue:[
+ cmd := '%1 "%2" </dev/tty'.
+ ].
+
+ ok := OperatingSystem
+ executeCommand:(cmd bindWith:(self editorCommand) with:tmpFile pathName)
+ inputFrom:Stdin
+ outputTo:Stdout
+ errorTo:Stderr
+ auxFrom:nil
+ environment:nil
+ inDirectory:nil
+ lineWise:false
+ newPgrp:false
+ showWindow:true
+ onError:[:status | false].
+
+ (ok and:[tmpFile modificationTime ~= modifiedTime]) ifTrue:[
+ isNewClass ifTrue:[
+ Compiler evaluate:tmpFile contentsOfEntireFile.
+ errStream showCR:'Class (re)defined.'
+ ] ifFalse:[
+ editFullClass ifTrue:[
+ tmpFile fileIn.
+ errStream showCR:'Class (re)compiled.'
+ ] ifFalse:[
+ cls compile:tmpFile contentsOfEntireFile classified:'*as yet uncategorized'.
+ errStream showCR:'Method (re)compiled.'
+ ].
+ ].
+ ] ifFalse:[
+ errStream showCR:'No change.'
+ ].
+ ] ensure:[
+ tmpFile notNil ifTrue:[
+ tmpFile remove
+ ]
+ ].
+
+ "
+ Smalltalk readEvalPrintLoop
+
+ self new
+ input:Stdin;
+ cmd_edit:'MyClass foo' readStream
+ "
+
+ "Modified: / 08-11-2016 / 22:46:12 / cg"
+!
+
cmd_exit:lineStream
exitAction value
@@ -196,7 +371,7 @@
cmd_help:lineStream
self errorStream
- nextPutAll:
+ nextPutAll:
'Everything entered up to an empty line or a line ending in "." is called a "chunk" and evaluated.
Lines starting with "#" are commands to the read-eval-print interpreter.
@@ -204,75 +379,92 @@
#help ............... this text
#exit ............... exit interpreter loop
#use <package>....... use (load) a package
- stx:libwidg .............. GUI package
- stx:libtool .............. IDE tool package
- stx:goodies/regex ........ regex package
- stx:goodies/petitparser .. peg parser package
+ stx:libwidg .............. GUI package
+ stx:libtool .............. IDE tool package
+ stx:goodies/regex ........ regex package
+ stx:goodies/petitparser .. peg parser package
#read <filename>..... read another script or source file
#show <what> ........ show info
- variables .......... interpreter variables
- processes .......... processes
- memory ............. memory usage
- flags .............. flags
- modules ............ loaded modules
+ variables .......... interpreter variables
+ processes .......... processes
+ memory ............. memory usage
+ flags .............. flags
+ modules ............ loaded modules
+ packages ........... available packages to load
+ all ................ all of the above
#set/clear <flag> ... set or clear a flag
- trace .............. tracing execution
- timing ............. timing execution
- chunkFormat ........ traditional bang chunk format input mode
+ trace .............. tracing execution
+ timing ............. timing execution
+ profiling .......... show execution profile
+ chunkFormat ........ traditional bang chunk format input mode
+ editor ............. command used with #edit directive
+ #debug ................. enter a MiniDebugger
+ #edit <what> ........ open an external editor
+ class .............. on a class
+ class selector ..... on a method
+ <empty> ............ on previously edited method/last class
The MiniDebugger (if entered) shows its own help with "?".
'
"Created: / 07-12-2006 / 18:54:20 / cg"
+ "Modified: / 08-11-2016 / 22:53:53 / cg"
!
cmd_read:lineStream
- |filename newInput savedPrompt savedPrint savedInput savedCurrentDirectory|
+ |filename newInput savedPrompt savedPrint savedInput savedCurrentDirectory savedDoChunkFormat|
lineStream skipSeparators.
filename := lineStream upToEnd withoutSeparators.
filename isNil ifTrue:[
- '? which file?' errorPrintCR.
- ^ self.
+ self errorStream showCR:'? which file?'.
+ ^ self.
].
filename := filename withoutSeparators.
filename isEmpty ifTrue:[
- '? which file?' errorPrintCR.
- ^ self.
+ self errorStream showCR:'? which file?'.
+ ^ self.
].
+ currentDirectory := currentDirectory ? (Filename currentDirectory).
+
filename := filename asFilename.
filename isAbsolute ifFalse:[
- filename := currentDirectory construct:filename.
+ filename := currentDirectory construct:filename.
].
- newInput := filename readStream.
+ StreamError ignoreIn:[
+ newInput := filename readStream.
+ ].
newInput isNil ifTrue:[
- ('Could not find file: "',filename,'"') errorPrintCR.
- ^ self.
+ self errorStream showCR:('Could not find file: "',filename pathName,'"').
+ ^ self.
].
[
- savedCurrentDirectory := currentDirectory.
- savedInput := inputStream.
- savedPrint := printFlag.
- savedPrompt := prompt.
-
- currentDirectory := filename directory.
- inputStream := newInput.
+ savedCurrentDirectory := currentDirectory.
+ savedDoChunkFormat := doChunkFormat.
+ savedInput := inputStream.
+ savedPrint := printFlag.
+ savedPrompt := prompt.
- self
- basicReadEvalPrintLoopWithInput:newInput
- output:outputStream
- error:errorStream
- compiler:compiler
- prompt:false
- print:false.
+ currentDirectory := filename directory.
+ inputStream := newInput.
+
+ self
+ basicReadEvalPrintLoopWithInput:newInput
+ output:outputStream
+ error:errorStream
+ compiler:(compiler ? Compiler ? Parser)
+ prompt:false
+ print:false.
] ensure:[
- currentDirectory := savedCurrentDirectory.
- inputStream := savedInput.
- printFlag := savedPrint.
- prompt := savedPrompt
+ newInput close.
+ doChunkFormat := savedDoChunkFormat.
+ currentDirectory := savedCurrentDirectory.
+ inputStream := savedInput.
+ printFlag := savedPrint.
+ prompt := savedPrompt.
].
!
@@ -288,91 +480,111 @@
lineStream skipSeparators.
what := lineStream nextAlphaNumericWord.
what notNil ifTrue:[
- (what startsWith:'tra') ifTrue:[
- traceFlag := aBoolean.
- ^ self.
- ].
- (what startsWith:'tim') ifTrue:[
- timingFlag := aBoolean.
- ^ self.
- ].
- (what startsWith:'chunk') ifTrue:[
- doChunkFormat := aBoolean.
- ^ self.
- ].
+ (what startsWith:'tra') ifTrue:[
+ traceFlag := aBoolean.
+ ^ self.
+ ].
+ (what startsWith:'tim') ifTrue:[
+ timingFlag := aBoolean.
+ ^ self.
+ ].
+ (what startsWith:'pro') ifTrue:[
+ profilingFlag := aBoolean.
+ ^ self.
+ ].
+ (what startsWith:'chunk') ifTrue:[
+ doChunkFormat := aBoolean.
+ ^ self.
+ ].
+ (what startsWith:'edi') ifTrue:[
+ aBoolean ifTrue:[
+ "/ set editor cmd
+ lineStream skipSeparators.
+ editorCommand := lineStream upToEnd.
+ ] ifFalse:[
+ editorCommand := nil.
+ ].
+ ^ self.
+ ].
].
- self errorStream nextPutLine:'? which flag ?'.
+ self errorStream showCR:'? which flag ?'.
- "Modified: / 07-12-2006 / 19:13:34 / cg"
+ "Modified: / 08-11-2016 / 22:49:17 / cg"
!
cmd_show:lineStream
- |errStream what all printModule|
+ |errStream what showAll ok|
-"
- self basicNew cmd_show:'packages' readStream
-"
errStream := self errorStream.
lineStream skipSeparators.
what := lineStream nextAlphaNumericWord.
+ ok := false.
+
what notNil ifTrue:[
- (what startsWith:'var') ifTrue:[
- Workspace notNil ifTrue:[
- Workspace workspaceVariables keysAndValuesDo:[:nm :h |
- errStream nextPutAll:nm; nextPutAll:' -> '; nextPutLine:h value.
- ].
- ].
- ^ self.
- ].
- (what startsWith:'proc') ifTrue:[
- MiniDebugger basicNew showProcesses.
- ^ self.
- ].
- (what startsWith:'mod') ifTrue:[
- printModule :=
- [:mod |
- errStream
- nextPutAll:' ';
- nextPutAll:(mod package "libraryName");
- nextPutLine:' (',(mod type),')'.
- ].
+ showAll := (what startsWith:'all').
+
+ (showAll or:[ what startsWith:'var' ]) ifTrue:[
+ showAll ifTrue:[ errStream showCR:'Variables:'; showCR:'----------' ].
+ self showVariables.
+ ok := true.
+ ].
+
+ (showAll or:[ what startsWith:'proc' ]) ifTrue:[
+ showAll ifTrue:[ errStream cr; showCR:'Threads:'; showCR:'--------' ].
+ MiniDebugger basicNew showProcesses.
+ ok := true.
+ ].
+
+ ("showAll or:[" what startsWith:'pack' "]") ifTrue:[
+ showAll ifTrue:[ errStream cr; showCR:'Available Packages:'; showCR:'--------' ].
+ self showPackages.
+ ok := true.
+ ].
+
+ (showAll or:[ what startsWith:'mod' ]) ifTrue:[
+ showAll ifTrue:[ errStream cr; showCR:'Modules:'; showCR:'--------' ].
+ self showModules.
- errStream nextPutLine:'builtIn:'.
- ((ObjectMemory binaryModuleInfo
- reject:[:m | m dynamic])
- asSortedCollection:[:a :b | a name < b name]) do:printModule.
-
- errStream nextPutLine:'dynamic:'.
- ((ObjectMemory binaryModuleInfo
- select:[:m | m dynamic])
- asSortedCollection:[:a :b | a name < b name]) do:printModule.
-
- ^ self.
- ].
- (what startsWith:'mem') ifTrue:[
- all := ObjectMemory oldSpaceUsed + ObjectMemory symSpaceUsed
- + ObjectMemory newSpaceUsed.
- errStream
- nextPutLine:('overall: ',(all // 1024) printString,' Kb');
- nextPutLine:('in use : ',(ObjectMemory bytesUsed // 1024) printString,' Kb');
- nextPutLine:('free : ',(ObjectMemory freeSpace // 1024) printString,' Kb');
- nextPutLine:('minorGC: ',(ObjectMemory scavengeCount) printString);
- nextPutLine:('majorGC: ',(ObjectMemory garbageCollectCount) printString).
- ^ self.
- ].
- (what startsWith:'flag') ifTrue:[
- errStream
- nextPutLine:('trace : ',traceFlag printString);
- nextPutLine:('timing: ',timingFlag printString);
- nextPutLine:('chunkFormat: ',doChunkFormat printString).
- ^ self.
- ].
+ ok := true.
+ ].
+
+ (showAll or:[ what startsWith:'mem' ]) ifTrue:[
+ |allMem|
+
+ showAll ifTrue:[ errStream cr; showCR:'Memory:'; showCR:'-------' ].
+ "/ allMem := ObjectMemory oldSpaceUsed + ObjectMemory symSpaceUsed
+ "/ + ObjectMemory newSpaceUsed.
+ errStream
+ "/ showCR:('overall: ',(allMem // 1024) printString,' Kb');
+ showCR:('used : ',(ObjectMemory bytesUsed // 1024) printString,' Kb');
+ showCR:('free : ',(ObjectMemory freeSpace // 1024) printString,' Kb');
+ show:('minorGC: ',(ObjectMemory scavengeCount) printString);
+ showCR:(' majorGC: ',(ObjectMemory garbageCollectCount) printString).
+ ok := true.
+ ].
+
+ (showAll or:[ what startsWith:'flag' ]) ifTrue:[
+ showAll ifTrue:[ errStream cr; showCR:'Flags:'; showCR:'------' ].
+ errStream
+ showCR:('trace : ',(traceFlag ? false) printString);
+ showCR:('timing: ',(timingFlag ? false) printString);
+ showCR:('profiling: ',(profilingFlag ? false) printString);
+ showCR:('chunkFormat: ',(doChunkFormat ? false) printString);
+ showCR:('editor: ',self editorCommand printString).
+ ok := true.
+ ].
].
- errStream nextPutLine:'? show what ?'.
+ ok ifFalse:[
+ errStream showCR:'? show what ?'.
+ ].
+
+ "
+ self basicNew cmd_show:'packages' readStream
+ "
- "Modified: / 07-12-2011 / 22:15:07 / cg"
+ "Modified: / 08-11-2016 / 22:46:51 / cg"
!
cmd_use:lineStream
@@ -381,26 +593,26 @@
lineStream skipSeparators.
pkg := lineStream upToEnd.
pkg isNil ifTrue:[
- '? which package?' errorPrintCR.
- ^ self.
+ self errorStream showCR:'? which package?'.
+ ^ self.
].
pkg := pkg withoutSeparators.
pkg isEmpty ifTrue:[
- '? which package?' errorPrintCR.
- ^ self.
+ self errorStream showCR:'? which package?'.
+ ^ self.
].
[
- Smalltalk loadPackage:pkg.
+ Smalltalk loadPackage:pkg.
] on:PackageLoadError do:[:ex|
- "/ allow for some shortcuts...
- (pkg includes:$:) ifTrue:[
- self errorStream nextPutLine:('Failed to load package: "',pkg,'"').
- ] ifFalse:[
- "/ try stx standard package
- pkg := 'stx:', pkg.
- ex restart.
- ].
+ "/ allow for some shortcuts...
+ (pkg includes:$:) ifTrue:[
+ self errorStream showCR:('Failed to load package: "',pkg,'"').
+ ] ifFalse:[
+ "/ try stx standard package
+ pkg := 'stx:', pkg.
+ ex restart.
+ ].
].
"Created: / 07-12-2006 / 19:07:56 / cg"
@@ -411,22 +623,108 @@
s := line readStream.
s next. "/ skip the hash
+ s peek == $!! ifTrue:[
+ "/ skip shebang line
+ ^ self.
+ ].
s skipSeparators.
cmd := s nextAlphaNumericWord.
cmd notNil ifTrue:[
- self
- perform:('cmd_',cmd) asMutator with:s
- ifNotUnderstood:[
- self errorStream
- nextPutAll:'?? invalid command: ';
- nextPutAll:cmd;
- nextPutAll:'. Type "#help" for help.';
- cr.
- ].
+ AbortAllOperationRequest handle:[:ex |
+ self errorStream showCR:('Directive aborted: ', ex description)
+ ] do:[
+ Error handle:[:ex |
+ self errorStream showCR:('Caught in directive: ', ex description).
+ ex suspendedContext fullPrintAll.
+ ] do:[
+ ControlInterrupt handle:[:ex |
+ MiniDebugger enter.
+ "/ self errorStream showCR:('Ignored in directive: ', ex description).
+ "/ ex reject.
+ "/ ex proceed.
+ ] do:[
+ self
+ perform:('cmd_',cmd) asMutator with:s
+ ifNotUnderstood:[
+ self errorStream
+ show:'?? invalid command: '; show:cmd;
+ showCR:'. Type "#help" for help.'
+ ].
+ ].
+ ].
+ ].
].
"Created: / 07-12-2006 / 18:49:17 / cg"
+ "Modified: / 08-11-2016 / 21:59:16 / cg"
+!
+
+showModules
+ |errStream printModule|
+
+ errStream := self errorStream.
+
+ printModule :=
+ [:mod |
+ errStream
+ show:' ';
+ show:(mod package "libraryName");
+ showCR:' (',(mod type),')'.
+ ].
+
+ errStream nextPutLine:'builtIn:'.
+ ((ObjectMemory binaryModuleInfo
+ reject:[:m | m dynamic])
+ asSortedCollection:[:a :b | a name < b name]) do:printModule.
+
+ errStream nextPutLine:'dynamic:'.
+ ((ObjectMemory binaryModuleInfo
+ select:[:m | m dynamic])
+ asSortedCollection:[:a :b | a name < b name]) do:printModule.
+
+ "
+ ReadEvalPrintLoop basicNew showModules
+ "
+!
+
+showPackages
+ |all|
+
+ all := Set new.
+ Smalltalk knownLoadablePackagesDo:[:packageID :type :path |
+ all add:packageID
+ ].
+ all := all asOrderedCollection sort.
+ all do:[:eachPackage |
+ self errorStream show:eachPackage.
+ (Smalltalk isPackageLoaded:eachPackage) ifTrue:[
+ self errorStream show:' (loaded)'.
+ ].
+ self errorStream cr.
+ ].
+
+ "
+ ReadEvalPrintLoop basicNew showPackages
+ ReadEvalPrintLoop basicNew showModules
+ "
+!
+
+showVariables
+ Workspace notNil ifTrue:[
+ Workspace workspaceVariables keys asOrderedCollection sort do:[:nm |
+ |holder|
+ holder := Workspace workspaceVariables at:nm.
+ self errorStream
+ show:nm;
+ show:' -> ';
+ showCR:holder value printString.
+ ].
+ ].
+
+ "
+ ReadEvalPrintLoop basicNew showVariables
+ "
! !
!ReadEvalPrintLoop methodsFor:'evaluation'!
@@ -440,112 +738,130 @@
for included scripts.
If chunkFormat is true, chunks are read.
Otherwise, lines up to an empty line (or EOF) or a line ending in '.' are read.
- A '#' character appearing in the first column of the first line turns off chunkmode."
+ A '#' character appearing in the first column of the first line turns off chunkmode,
+ which allows for convenient shell scripts containing a #/bin/stx as the first line."
+
+ exitAction := [^ self].
[
- |lines chunk|
+ |lines chunk|
- prompt notNil ifTrue:[
- error nextPutAll:prompt.
- ].
+ prompt notNil ifTrue:[
+ error show:prompt.
+ ].
- input atEnd ifTrue:[
- error cr.
- ^ self.
- ].
+ input atEnd ifTrue:[
+ doPrint ifTrue:[ error cr ].
+ ^ self.
+ ].
- input peek == $# ifTrue:[
- self doChunkFormat:false.
- ].
+ input peek == $# ifTrue:[
+ self doChunkFormat:false.
+ ].
- self doChunkFormat ifTrue:[
- input skipSeparators.
- chunk := input nextChunk.
- ] ifFalse:[
- lines := OrderedCollection new.
- [
- |line|
+ self doChunkFormat ifTrue:[
+ input skipSeparators.
+ chunk := input nextChunk.
+ ] ifFalse:[
+ lines := OrderedCollection new.
+ [
+ |line|
- line := input nextLine.
- line notEmptyOrNil ifTrue:[
- line = '?' ifTrue:[
- self cmd_help:nil.
- prompt notNil ifTrue:[
- error nextPutAll:prompt.
- ].
- ] ifFalse:[
- (line startsWith:'#') ifTrue:[
- self directive:line.
- prompt notNil ifTrue:[
- error nextPutAll:prompt.
- ].
- ] ifFalse:[
- lines add:line.
- ]
- ]
- ].
- line notEmptyOrNil and:[(line endsWith:$.) not].
- ] whileTrue.
- chunk := lines asStringWith:Character cr.
- ].
+ line := input nextLine.
+ line notEmptyOrNil ifTrue:[
+ line = '?' ifTrue:[
+ self cmd_help:nil.
+ prompt notNil ifTrue:[
+ error show:prompt.
+ ].
+ ] ifFalse:[
+ (line startsWith:'#') ifTrue:[
+ self directive:line.
+ prompt notNil ifTrue:[
+ error show:prompt.
+ ].
+ ] ifFalse:[
+ lines add:line.
+ ]
+ ]
+ ].
+ line notEmptyOrNil and:[(line endsWith:$.) not].
+ ] whileTrue.
+ chunk := lines asStringWith:Character cr.
+ ].
- (chunk notEmptyOrNil and:[chunk withoutSeparators notEmpty]) ifTrue:[
- "abortAll is handled, but not asked for here!!"
- AbortAllOperationRequest handle:[:ex |
- error nextPutLine:('Evaluation aborted: ', ex description)
- ] do:[
- (Error, ControlInterrupt) handle:[:ex |
- prompt isNil ifTrue:[
- ex reject
- ].
- MiniDebugger enterWithMessage:(ex errorString) mayProceed:true.
- ex mayProceed ifTrue:[
- ex proceed.
- ].
- error nextPutLine:('Evaluation aborted: ', ex description).
- ex return.
- ] do:[
- |value ms us|
+ (chunk notEmptyOrNil
+ and:[chunk withoutSeparators notEmpty
+ and:[chunk withoutSeparators ~= '.']]
+ ) ifTrue:[
+ "abortAll is handled, but not asked for here!!"
+ AbortAllOperationRequest handle:[:ex |
+ error nextPutLine:('Evaluation aborted: ', ex description)
+ ] do:[
+ (Error, ControlInterrupt) handle:[:ex |
+ prompt isNil ifTrue:[
+ ex reject
+ ].
+ MiniDebugger enterWithMessage:(ex errorString) mayProceed:true.
+ ex mayProceed ifTrue:[
+ ex proceed.
+ ].
+ error showCR:('Evaluation aborted: ', ex description).
+ ex return.
+ ] do:[
+ |value ms us|
- ms := Time millisecondsToRun:[
- us := Time microsecondsToRun:[
- value := (compilerClass new
- requestor:self)
- evaluate:chunk
- compile:true.
- ].
- ].
- doPrint ifTrue:[
- value printOn:output. output cr.
- ].
+ profilingFlag == true ifTrue:[
+ MessageTally spyDetailedOn:[
+ value := (compilerClass new requestor:self)
+ evaluate:chunk
+ compile:true.
+ ].
+ doPrint ifTrue:[
+ value printOn:output. output cr.
+ output flush.
+ ].
+ ] ifFalse:[
+ us := Time microsecondsToRun:[
+ value := (compilerClass new requestor:self)
+ evaluate:chunk compile:true.
+ ].
+ doPrint ifTrue:[
+ value isVoid ifFalse:[
+ value printOn:output. output cr.
+ ].
+ ].
- timingFlag == true ifTrue:[
- 'execution time: ' printOn:error.
- ms < 1 ifTrue:[
- us < 1 ifTrue:[
- 'too small to measure (<1us)' printOn:error.
- ] ifFalse:[
- us printOn:output. 'us' printOn:error.
- ]
- ] ifFalse:[
- ms printOn:output. 'ms' printOn:error.
- ].
- error cr.
- ].
- Workspace notNil ifTrue:[
- Workspace workspaceVariableAt:'_$$' put:value.
- ].
- ].
- ].
- ].
+ timingFlag == true ifTrue:[
+ 'execution time: ' printOn:error.
+ us < 1000 ifTrue:[
+ us < 1 ifTrue:[
+ 'too small to measure (<1us)' printOn:error.
+ ] ifFalse:[
+ us printOn:output. 'us' printOn:error.
+ ]
+ ] ifFalse:[
+ ((us / 1000) asFixedPoint:2) printOn:output. 'ms' printOn:error.
+ ].
+ error cr.
+ ].
+ ].
+ Workspace notNil ifTrue:[
+ Workspace rememberResultAsWorkspaceVariable:value.
+ ].
+ ].
+ ].
+ ].
] loop.
"
+ Smalltalk readEvalPrintLoop.
+
(ReadEvalPrintLoop new prompt:'>') readEvalPrintLoop
"
"Created: / 07-12-2006 / 17:27:21 / cg"
- "Modified: / 06-12-2011 / 15:29:03 / cg"
+ "Modified: / 08-11-2016 / 22:41:47 / cg"
!
readEvalPrintLoop
@@ -557,35 +873,55 @@
A '#' character appearing in the first column of the first line
switches to chunkmode."
- exitAction := [^ self].
+ ControlInterrupt handle:[:ex |
+ self errorStream showCR:('Caught: ', ex description).
+ self inputStream atEnd ifTrue:[
+ ex return.
+ ].
+ MiniDebugger enter.
+ ex proceed.
+ "/ ex restart.
+ ] do:[
+ |input output error compilerClass|
- ControlInterrupt handle:[:ex |
- self errorStream nextPutLine:('Caught: ', ex description).
- ex restart.
- ] do:[
- |input output error compilerClass|
+ "/ re-evaluate these in the loop, so they can be changed dynamically
+ input := self inputStream.
+ output := self outputStream.
+ error := self errorStream.
- "/ re-evaluate these in the loop, so they can be changed dynamically
- input := self inputStream.
- output := self outputStream.
- error := self errorStream.
-
- compilerClass := compiler ? Compiler ? Parser.
- compilerClass isNil ifTrue:[
- self errorStream nextPutLine:('oops - no Compiler class found').
- ^ self.
- ].
- self
- basicReadEvalPrintLoopWithInput:input output:output error:error
- compiler:compilerClass prompt:prompt print:(printFlag ? true).
- ]
+ compilerClass := compiler ? Compiler ? Parser.
+ compilerClass isNil ifTrue:[
+ error showCR:('oops - no Compiler class found').
+ ^ self.
+ ].
+ StreamError handle:[:ex |
+ (input isOpen not or:[input atEnd]) ifTrue:[
+ error showCR:'EOF on input'.
+ ex return.
+ ].
+ (output isOpen not) ifTrue:[
+ error showCR:'no output'.
+ ].
+ (error isOpen not) ifTrue:[
+ ].
+ ] do:[
+ input signalAtEnd:true.
+ self
+ basicReadEvalPrintLoopWithInput:input output:output error:error
+ compiler:compilerClass prompt:prompt print:(printFlag ? true).
+ ]
+ ].
+ "/ self errorStream showCR:('done.').
"
+ Stdin atEnd
+ Stdin clearEOF
+ Smalltalk readEvalPrintLoop
(ReadEvalPrintLoop new prompt:'>') readEvalPrintLoop
"
"Created: / 07-12-2006 / 17:27:21 / cg"
- "Modified: / 06-12-2011 / 15:29:03 / cg"
+ "Modified: / 08-11-2016 / 22:42:21 / cg"
! !
!ReadEvalPrintLoop methodsFor:'queries'!